golang 基礎

Go

Go 是一款編譯型,強類型語言。node

基礎

變量

GO 變量這一區域,藉助於 Js lua C 系列的合體。golang

  1. 全部變量都是強類型限定。
  2. 值類型變量皆存在非nil默認值,string 是值類型。
  • 值類型
類型 解釋 備註
uint8 無符號整型 位數 8,16,32,64
int8 有符號整型 位數 8,16,32,64
float32 浮點數 位數 32,64
complex64 複數 位數 64,128
經常使用 標識 大小
字節 byte 1 字節
布爾 bool 1 字節
整形 int, uint 8 字節, 64位
指針 uintptr 8 字節, 64位,(uint)
字符串 string 16 字節
  • 特性
  1. Js var const在此處做用相同。
  2. lua _ 以及棧式賦值,以及棧式返回,在此處亦有相同的做用。
  3. Go 變量類型可強限定,亦可動態限定,但只要被肯定一次即不可更改(本質上仍是強限定)。
  4. Go 變量動態限定類型僅可在局部函數內部使用,且全部Go變量必須使用纔可編譯經過。
// 常量強限定
const num int = 100;
// 常量動態限定,僅限於第一次
const num = 100;

// 變量強限定
var num int = 120;
// 變量動態限定,僅限於第一次
var cnt = 100;

// 強限定,棧式賦值
var num, cnt int = 100, 120;
// 動態限定,棧式賦值
var num, str = 120, "stack";

// 虛變量
_, b int = demo();

// 語法糖
var num = 120; num := 120;

// iota 特殊編譯器行數變量

流程控制

  • 運算符
  1. Go語言的運算符繼承了C,且保留了指針。
運算符 經常使用 備註
算術 + - * / % ++ -- / 整除運算
比較 > >= < <= == !=
邏輯 && || ! 默認短路,複合!要加()
& | ^ << >> 某些算法中,位運算很重要
賦值 = := ... 賦值運算也是大同小異
指針 &a 獲取a的地址 *a定義指針 & * 操做指針
  • 選擇控制
// if-then
if (true) {
    //TODO
}
// if-else
if (true) {
    //TODO
} else {
    //TODO
}

// switch val語句
switch (val) {
    case 0:  // case 執行完即會退出
    default:
}

// switch 語句
switch {
    case true: // case 執行完成即退出
    case true:
    default:
}

// go 中 switch屬於選擇語句,即默認只會選中一項
switch {
    case true:
        fallthrough // 此處 case 執行完後,直接執行下一條case(跳過判斷)
    default:
}

// for 語句實現循環
for {
    //TODO
}
  • 函數
  1. 函數支持多值返回。
  2. 全部參數都執行值傳遞過程。
  3. 函數支持返回函數,也支持參數爲函數。
// 默認無返回值函數
func demo() {
    //TODO
}

// 單值返回
func demo() int{
    //TODO
    return 0
}

// 棧式返回
func demo() (int, int){
    //TODO
    return 0,1
}

// 函數傳參類型
func demo(num int, cnt int){
    //TODO
}

// defer 語句塊,就至關於 finally 語句塊,函數最終必需要執行此方法
func demo() {
    defer //TODO
    //TODO
}

數據結構

  • 集合
// 聲明集合,此時爲 nil 值,即不可以使用狀態
var m = map[string] string
// 建立集合,此出事後纔可以使用
m = make(map[string] string)

// 此處是將前面兩步合在一塊兒執行
var mk = make(map[int] int)

// 經常使用方法
delete(mk, "str");

// 迭代集合
for k, v := range mk {
    // k, v
}
  • 數組
  1. 強內存、強類型限定的數組。
  2. 數組類型是兼容於 C 系列的數組。
  3. 數組的切片類型執行引用複製,不會從新複製內存。
// 新建數組變量
var cnt[10] int32;

// 默認初始化
var cnt = [2] int32{1,2};

// 自動肯定長度的數組
var cnt = [...] int32 {1,2,3,4,5,6,7,};

// 函數傳遞數組
func demo(arr int[], size int){
    // TODO
}

// 基於 arr生成切片,內存共享
var tmp = arr[1:];

len(tmp); // 數組長度,通常指切片數組或原始數組的大小,操做 idx 區間最大值
cap(tmp); // 數組底層大小,通常指原始數組長度

// 經常使用的一些方法
append(); copy();

// 迭代數組
for v := range arr{
    // v
}
  • 字符串
  1. Go string 是一個基本類型,而非引用類型。
  2. Go string 默認爲UTF-8編碼,unicode須要額外轉碼。
  3. 通常用,"str"表示,內部可轉義,不可多行。
  4. 特殊時,`str`表示,內部不可轉義,能夠多行。
// 定義並初始化字符串
var str string = "123456";

// 常見字符串拼接
var add = str + "789";

// 字符串,切片
var cut = str[2:];

len(str); // 獲取string,字節佔用大小
str[0]; // 獲取字節索引的 ASCII 數值

特性

模塊化

  • package
  1. 一個文件夾就是一個包,package
  2. 一個文件.go就是一個模塊,module
  3. 程序主入口是個特殊的類型 main/main.go => main()
package main  // 任何go程序,必須有 main 包,內部必須存在 main方法

import (
    "fmt"  // 標準庫 IO
)

// 引入多個包
import (
    . "fmt"    // 調用此模塊下方法,無需前置 fmt
    tm "time"  // 修改模塊別名 tm
    _ "sync"   // 執行一次 sync.init() 內部方法不可調用
)

// 任意模塊文件被引用或加載時會執行一次
func init() {
    fmt.Println("當前文件加載時,會執行一次!")
}

// 程序主入口
func main() {
    fmt.Println("程序啓動入口,必須存在!")
}

// go 的語法風格,會在行尾自動補齊 ;
  • module

待補充。算法

 
  • execute
# 編譯 demo 並執行
go run ./demo.go

# 編譯 demo 爲可執行文件 run
go build -o run ./demo.go

抽象化

  • 結構體
  1. 結構體部分主要繼承自C系列。
// 這裏通常都須要註釋,否則會提示
type Atk struct{
    idx int
    val int32
    nam string
}

// 新建結構體,固定位置填充
var atk = Atk{1, 2, "hello"}
// 新建結構體,索引位置填充,不索引時,以默認值填充
var atk = Atk{idx:1, val:2}
// 新建結構體,初始化默認值,並返回一個指針
var ptr = new(Atk)
ptr.idx, ptr.val, ptr.nam // 標準指針訪問過程
  • 接口
  1. Go的接口就是Java中接口以及實現類的一個衍生方式。
  2. 其本質上就是根據的結構體(實體),綁定不一樣的處理方法。
// 定義接口
type Abs interface{
    // Obj 訪問
    Name() string
    // *Obj 訪問
    name() string
}

// 定義結構體
type Obj struct{
    idx int
    nam string
}

// 綁定 Obj 結構體,Name方法
func (e Obj) Name() string{
    return e.nam
}

// 綁定 *Obj 結構體,Name方法
func (e *Obj) name() string{
    e.nam = e.name + "tl"
    return e.nam
}

var obj = Object{1, "zsh"}
var ptr = &obj

// 指針以及非指針,傳參不一樣,故用法不一樣
obj.Name()
ptr.name()
  • error
  1. Go 的異常處理機制基本類似於Java C等語言。
// 內置異常接口
type error interface{
    Error() string
}

// 測試結構體
type Obj struct{
    idx int
    val string
}

// 預約義返回錯誤的方法
func logError(e Obj) error{
    if(e.idx == 0){
        errors.New("idx == 0")
    }
    errors.New("ok")
}

func main(){
    var obj = Obj{0, 1}
    // 輸出預約義異常
    fmt.Println(logError(obj))
}

// golang - 通用性異常處理方式
func demo(){
    defer func(){
        var err = recover() // 捕獲異常
    }()                     // 匿名函數
    panic("throws-errors!") // 拋出異常
}

併發控制

  • 攜程
  1. Java 中的線程使用的是OS級別的資源,而此處攜程使用的是虛擬機資源。
  2. OS線程,並行處理,但切換上下文消耗資源,且自己的異步控制也較爲複雜。
  3. 虛擬機線程,僞並行處理,不存在上下文切換,自己不會產生過多的異步控制邏輯。
// 開啓攜程,返回值會被拋棄,僞並行
func demo() {
    var cnt = 0
    for i := 0; i < 1000; i++ {
        // go 啓動攜程
        go func(){
            cnt++
        }()
    }
    fmt.Println("cnt", cnt)
}

// 併發的鎖控制,代碼控制併發,簡單高效
var cnt = 0

func demo(lock *sync.Mutex) {
    lock.Lock()
    cnt++
    fmt.Println("cnt", cnt)
    lock.Unlock()
}

func main() {
    var lock = &sync.Mutex{}
    for i:=0; i < 50; i++ {
        go demo(lock)
    }

    for {
        lock.Lock()
        tmp := cnt
        lock.Unlock()
        // 讓出時間片
        runtime.Gosched()
        // 退出循環
        if (tmp == 50) {
            break
        }
    }
}
  • 通道
  1. 通道是一種在不一樣線程之間傳遞數據的機制,核心機制相似 MQ
  2. 通道僅支持不一樣線程之間的數據交互,單線程會發生死鎖,不可以使用。
  3. 無緩衝通道,即數據必須即刻送達,其中一方未準備好,即阻塞另外一方。
  4. 緩衝通道,即數據無需便可送達,僅當超過必定閾值時,阻塞其中一方。
// 無緩衝通道
var ch = make(chan int)

ch <- 123           // 向 ch 通道發送數據,無返回值
var dat, ok = <-ch  // 從 ch 通道取出數據,雙返回值

// 緩衝通道,數據量超過閾值則發生阻塞
var ch = make(chan int, 10)

close(ch)  // 關閉通道,通道被關閉後,即不可以使用

// demo =====>
var ch = make(chan int, 2)

go func(){
    ch <- 1
    time.Sleep(time.Second)
    ch <- 2
    time.Sleep(time.Second)
    close(ch)
    fmt.Println("ch - closed")
}()

for i := 0; i < 4; i++ {
    var dat, ok = <-ch
    fmt.Println(ok, dat)
}
/*
true 1
true 1
ch - closed
false 0
false 0
*/
  • chan - 用法
  1. chan 結構的設計很是類似於node的異步設計。
  2. 可經過內置的異步方式,實現諸多的設計。
// 迭代型 for-range
var ch = make(chan int)
go func(){
    for i := 0; i < 4; i++ {
        ch <- i
        fmt.Println("sending", i)
        time.Sleep(time.Second)
    }
    close(ch)
}()

for i := range ch {
    fmt.Println("receive", i)
}

fmt.Println("ending")

// 選擇型 select
var ch1 = make(chan int)
var ch2 = make(chan int)

go func(){
    ch1 <- 123
    close(ch1)
}()

go func(){
    ch2 <- 456
    close(ch2)
}()

// 單選退出
select {
case i := <-ch1:
    fmt.Println("ch1", i)
case i := <-ch2:
    fmt.Println("ch2", i)
default:
    fmt.Println("default")
}

// time 內置的時間觸發器,內部就是個 chan
var ch = time.NewTicker(time.Second)
for t := range ch.C {
    fmt.Println(t)
}
相關文章
相關標籤/搜索