Go 是一款編譯型,強類型語言。node
GO
變量這一區域,藉助於Js
lua
C
系列的合體。golang
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 字節 |
Js var const
在此處做用相同。lua _
以及棧式賦值,以及棧式返回,在此處亦有相同的做用。Go
變量類型可強限定,亦可動態限定,但只要被肯定一次即不可更改(本質上仍是強限定)。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 特殊編譯器行數變量
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 }
// 默認無返回值函數 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 }
C
系列的數組。// 新建數組變量 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 }
Go
string 是一個基本類型,而非引用類型。Go
string 默認爲UTF-8
編碼,unicode
須要額外轉碼。"str"
表示,內部可轉義,不可多行。`str`
表示,內部不可轉義,能夠多行。// 定義並初始化字符串 var str string = "123456"; // 常見字符串拼接 var add = str + "789"; // 字符串,切片 var cut = str[2:]; len(str); // 獲取string,字節佔用大小 str[0]; // 獲取字節索引的 ASCII 數值
package
。.go
就是一個模塊,module
。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 的語法風格,會在行尾自動補齊 ;
待補充。算法
# 編譯 demo 並執行 go run ./demo.go # 編譯 demo 爲可執行文件 run go build -o run ./demo.go
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 // 標準指針訪問過程
Go
的接口就是Java
中接口以及實現類的一個衍生方式。// 定義接口 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()
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!") // 拋出異常 }
Java
中的線程使用的是OS
級別的資源,而此處攜程使用的是虛擬機
資源。OS
線程,並行處理,但切換上下文消耗資源,且自己的異步控制也較爲複雜。虛擬機
線程,僞並行處理,不存在上下文切換,自己不會產生過多的異步控制邏輯。// 開啓攜程,返回值會被拋棄,僞並行 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 } } }
MQ
。// 無緩衝通道 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 */
node
的異步設計。// 迭代型 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) }