這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
go語言已經出來5年了,最近才開始學習,真是慚愧。
如果要用一個詞來形容go語言的話,那麼沒有比高並發更合適的。levelDB就是用go語言來實現的。
下面主要看下go語言的資料類型
布爾型:bool,取值true, false 整型:int/uint 32位或64位
8位整型:int8/uint8 位元組型:byte(unit8別名)
16位整型:int16/uint16 32位整型:int32(rune)/uint32
64位整型:int64/uint64 浮點型:float32/float64 小數點精確到7/15位
複數:complex64/complex128 足夠儲存指標的32位和64位整數型:uintptr
其它實值型別:array, struct, string 參考型別:slice, map, chan
介面類型:interface 函數類型:func。函數是可以賦值給變數的
### 單個變數的聲明與賦值有如下三種方式:
1 2 3 4 5 6 7 8 9
|
//1 var x int x = 42
//2 var x int = 42
//3 x := 42
|
其中要注意的是第三種只能用於局部變數,而不能用於全域變數。第二種方式可以省略類型名,也就是採用類型自動推斷。
多個變數的聲明方式:
1 2 3 4 5 6 7 8 9
|
//1 var ( x int = 1 y int = 2 z int = 3 )
//2 var a, b, c int = 1, 2, 3
|
其中第一種方式不能用於局部變數。第二種方式很有用,比如交換兩個變數的值
1 2 3
|
var a = 1 var b = 2 a, b = b, a
|
go語言常量支援字元型,字串型,布爾型和數字型。常量的值在編譯時間就已經確定,定義格式與變數基本相同。定義常量組時,如果不提供初始值,則表示將使用上行的運算式,當然兩行聲明的常量個數必須是相同的。值得一提的是iota,常量行數計數器,從0開始,定義常量組時,每定義一個常量自動遞增。每遇到一個const關鍵字,iota就會重設為0.
1 2 3 4 5 6 7 8
|
const ( A = 1 B C = iota D ) const E = iota const F = iota
|
B沒有提供初始值,則使用A的右值,也就是B=1。C=iota,行數計數器,也就是2。D使用C的右值,也就是D=iota,則D=3。每個const中的iota都是從0開始,所以E=0, F=0。
數組與指標。
go語言中的數組是實值型別,也就是說,如果將數組作為函數的參數,那麼實際傳遞的參數是一份數組的拷貝,而不是指向數組的指標。數組的聲明以及賦值如下
1 2 3 4 5 6
|
var A [4]int //now A = {0,0,0,0} A = [4]int{1,2,3,4} var B = [4]int{1,2,3,4} var C = [...]int{1,2,3,4} var D = [20]int{18:1, 19:2}
|
D實現對數組指定下標進行賦值。指標和C語言指標基本一樣,但不使用”->”,而是直接採用“.”選擇符來操作指標。&訪問地址,*訪問值。那麼一個喜聞樂見的問題來了。區分指標數組與數組指標。指標數組是數組,數組的元素是指標;數組指標,指向數組。定義如下
1 2 3 4 5 6
|
//指標數組 var x, y = 1, 2 var a = [...]*int{&x, &y} //數組指標 var z = [...]int{x, y} var b *[2]int = &z
|
值得注意的是go語言中不同長度的數群組類型是不一樣的,所以聲明數組指標的時候一定要注意。
內建類型:slice, map, channel
slice類似於python中的切片。可以理解為一個指向數組的指標。而且這個指標還有兩個域:長度,容量。長度為當前元素個數,容量為最大元素個數,類似於STL中vector的size和capacity。正常情況下slice和數組共用一段儲存空間,當我們對slice操作使得slice超出數組大小時,則slice會重新分配空間。也可以用make為slice分配空間。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
slice1 := a[5:10] fmt.Println(slice1) //[6,7,8,9,10] a[5] = 10 fmt.Println(slice1) //[10,7,8,9,10] slice1 = append(slice1, 100) fmt.Println(slice1) //[10,7,8,9,10,100] a[6] = 11 fmt.Println(slice1) //[10,7,8,9,10,100]
|
map關聯陣列,兩個域key, value。我們知道關於map的實現有基於樹的實現,也有基於hash表的實現,那麼go語言中是怎麼來實現的呢?有空還是要去看下runtime源碼。go語言中的map是用hash表來實現的,hash衝突是用開鏈的方式解決的。下面寫下map的常見用法。
1 2 3 4 5 6 7 8
|
mymap := make(map[int]int) mymap[10] = 10 * 10 mymap[5] = 5 * 5 mymap[15] = 15 * 15
for k, v := range mymap { fmt.Println(k, v) }
|
channel主要用於goroutine,下次再說吧。