-
綜述
變量聲明時未賦初值,則變量被自動賦值為該類型的零值(固定值)
new()返回一個指針,指向新分配的該類型的零值,不是空指針(nil)。the value returned is a pointer to a newly allocated zero value of that type.
func make(t Type, size ...IntegerType) Type
make()只適用於slice、map、chan,此三種類型創建時推薦使用make()而不是new()。The make built-in function allocates and initializes an object of type slice, map, or chan (only). Unlike new, make's return type is the same as the type of its argument, not a pointer to it. The specification of the result depends on the type:
Slice: The size specifies the length. The capacity of the slice is equal to its length. A second integer argument may be provided to specify a different capacity; it must be no smaller than the length. For example, make([]int, 0, 10) allocates an underlying array of size 10 and returns a slice of length 0 and capacity 10 that is backed by this underlying array. Map: An empty map is allocated with enough space to hold the specified number of elements. The size may be omitted, in which case a small starting size is allocated. Channel: The channel's buffer is initialized with the specified buffer capacity. If zero, or the size is omitted, the channel is unbuffered.
如下將按照類型實體、指針、new/make、類型比較等詳述各種數據類型。
2. 數組
數組是值類型而不是引用類型。當數組賦值給一個變量時,該變量會得到一個原始數組的副本。對新變量的更改,不會影響原始數組。
數組實體被初始化數組值類型的零值,如int零值為0,string零值為""。
數組指針初始化為nil。
new()返回指向類型零值的指針。
數組是值類型,可以直接比較。
package main import ( "fmt" "strconv" ) func main(){ var ai [10]int var as [10]string fmt.Printf("int array [%p] init value: %v\n", &ai, ai) fmt.Printf("string array [%p] init value: %v\n", &as, as) fmt.Println("---------------------------") var i int for i = 0; i < len(ai); i++ { ai[i] = 100 + i } for i, _ := range as { as[i] = strconv.Itoa(100 + i) } fmt.Printf("int array [%p] init value: %v\n", &ai, ai) fmt.Printf("string array [%p] init value: %v\n", &as, as) fmt.Println("---------------------------") var pai *[10]int var pas *[10]string fmt.Printf("int point array [%p] init value: %v\n", &pai, pai) fmt.Printf("string point array [%p] init value: %v\n", &pas, pas) fmt.Println("---------------------------") pai = &ai pas = &as pai[0] = 1 pas[0] = "1" fmt.Printf("int point array [%p] init value: %v\n", &pai, *pai) fmt.Printf("string point array [%p] init value: %v\n", &pas, *pas) fmt.Println("---------------------------") paii := new([10]int) pass := new([10]string) fmt.Printf("int point array [%p] init value: %v\n", &paii, *paii) fmt.Printf("string point array [%p] init value: %v\n", &pass, *pass) fmt.Println("---------------------------") for i = 0; i < len(*paii); i++ { paii[i] = 100 + i } for i, _ := range *pass { pass[i] = strconv.Itoa(100 + i) } fmt.Printf("int point array [%p] init value: %v\n", &paii, *paii) fmt.Printf("string point array [%p] init value: %v\n", &pass, *pass) fmt.Println("---------------------------") paii[0] = 1 pass[0] = "1" fmt.Printf("%v\n==\n%v \n???\n%t\n", ai, *paii, (ai==*paii)) fmt.Println("---------------------------") fmt.Printf("%v\n==\n%v \n???\n%t\n", as, *pass, (as==*pass)) }
運行結果:
int array [0xc000072000] init value: [0 0 0 0 0 0 0 0 0 0] string array [0xc000074000] init value: [ ] --------------------------- int array [0xc000072000] init value: [100 101 102 103 104 105 106 107 108 109] string array [0xc000074000] init value: [100 101 102 103 104 105 106 107 108 109] --------------------------- int point array [0xc00000e030] init value: <nil> string point array [0xc00000e038] init value: <nil> --------------------------- int point array [0xc00000e030] init value: [1 101 102 103 104 105 106 107 108 109] string point array [0xc00000e038] init value: [1 101 102 103 104 105 106 107 108 109] --------------------------- int point array [0xc00000e040] init value: [0 0 0 0 0 0 0 0 0 0] string point array [0xc00000e048] init value: [ ] --------------------------- int point array [0xc00000e040] init value: [100 101 102 103 104 105 106 107 108 109] string point array [0xc00000e048] init value: [100 101 102 103 104 105 106 107 108 109] --------------------------- [1 101 102 103 104 105 106 107 108 109] == [1 101 102 103 104 105 106 107 108 109] ??? true --------------------------- [1 101 102 103 104 105 106 107 108 109] == [1 101 102 103 104 105 106 107 108 109] ??? true
3. 切片
切片是值類型而不是引用類型。切片本身不擁有任何數據,只是對現有數組的引用。對切片的所有修改都會反映到底層數組上。
切片實體初始化為切片類型的零值 nil。一個 nil 切片的長度和容量為 0。
切片指針初始化為nil。
make返回類型零值的切片,非nil。
切片只能和nil作比較,要比較切片需比較切片的每個元素值。
package main import ( "fmt" "strconv" ) func main(){ var si []int var ss []string fmt.Printf("int slice [%p] init value: %v, len:%d, cap:%d\n", &si, si, len(si), cap(si)) fmt.Printf("string slice [%p] init value: %v, len:%d, cap:%d\n", &ss, ss, len(ss), cap(ss)) // fmt.Printf("int slice [%p] init value: %v\n", &si, si[0]) // fmt.Printf("string slice [%p] init value: %v\n", &ss, ss[0]) fmt.Println("---------------------------------------") var i int if si == nil { for i = 0; i < 10; i++ { si = append(si, 100+i) fmt.Printf("int slice [%p] append %d element: %v, len:%d, cap:%d\n", &si, i, si, len(si), cap(si)) } } fmt.Println("---------------------------------------") if ss == nil { for i = 0; i < 10; i++ { ss = append(ss, strconv.Itoa(100+i)) fmt.Printf("string slice [%p] append %d element: %v, len:%d, cap:%d\n", &ss, i, ss, len(ss), cap(ss)) } } fmt.Println("---------------------------------------") var psi *[]int var pss *[]string // fmt.Printf("int slice pointer [%p] init value: %v, len:%d, cap:%d\n", &psi, psi, len(*psi), cap(*psi)) // fmt.Printf("string slice pointer [%p] init value: %v, len:%d, cap:%d\n", &pss, pss, len(*pss), cap(*pss)) fmt.Printf("int slice pointer [%p] init value: %v\n", &psi, psi) fmt.Printf("string slice pointer [%p] init value: %v\n", &pss, pss) fmt.Println("---------------------------------------") psi = &si pss = &ss fmt.Printf("int slice pointer [%p] init value: %v, len:%d, cap:%d\n", &psi, *psi, len(*psi), cap(*psi)) fmt.Printf("string slice pointer [%p] init value: %v, len:%d, cap:%d\n", &pss, *pss, len(*pss), cap(*pss)) fmt.Println("---------------------------------------") sim := make([]int, 10, 10) ssm := make([]string, 10, 10) fmt.Printf("int slice make [%p] init value: %v, len:%d, cap:%d\n", &sim, sim, len(sim), cap(sim)) fmt.Printf("string slice make [%p] init value: %v, len:%d, cap:%d\n", &ssm, ssm, len(ssm), cap(ssm)) fmt.Println("---------------------------------------") for i = 0; i < len(sim); i++ { sim[i] = 100 + i } for i,_ := range ssm { ssm[i] = strconv.Itoa(100+i) } fmt.Printf("int slice make [%p] init value: %v, len:%d, cap:%d\n", &sim, sim, len(sim), cap(sim)) fmt.Printf("string slice make [%p] init value: %v, len:%d, cap:%d\n", &ssm, ssm, len(ssm), cap(ssm)) fmt.Println("---------------------------------------") // fmt.Printf("%v\n==\n%v\n???\n%t\n", si, *psi, (si==*psi)) fmt.Println("---------------------------------------") // fmt.Printf("%v\n==\n%v\n???\n%t\n", ss, ssm, (ss==ssm)) }
運行結果:
int slice [0xc00006a020] init value: [], len:0, cap:0 string slice [0xc00006a040] init value: [], len:0, cap:0 --------------------------------------- int slice [0xc00006a020] append 0 element: [100], len:1, cap:1 int slice [0xc00006a020] append 1 element: [100 101], len:2, cap:2 int slice [0xc00006a020] append 2 element: [100 101 102], len:3, cap:4 int slice [0xc00006a020] append 3 element: [100 101 102 103], len:4, cap:4 int slice [0xc00006a020] append 4 element: [100 101 102 103 104], len:5, cap:8 int slice [0xc00006a020] append 5 element: [100 101 102 103 104 105], len:6, cap:8 int slice [0xc00006a020] append 6 element: [100 101 102 103 104 105 106], len:7, cap:8 int slice [0xc00006a020] append 7 element: [100 101 102 103 104 105 106 107], len:8, cap:8 int slice [0xc00006a020] append 8 element: [100 101 102 103 104 105 106 107 108], len:9, cap:16 int slice [0xc00006a020] append 9 element: [100 101 102 103 104 105 106 107 108 109], len:10, cap:16 --------------------------------------- string slice [0xc00006a040] append 0 element: [100], len:1, cap:1 string slice [0xc00006a040] append 1 element: [100 101], len:2, cap:2 string slice [0xc00006a040] append 2 element: [100 101 102], len:3, cap:4 string slice [0xc00006a040] append 3 element: [100 101 102 103], len:4, cap:4 string slice [0xc00006a040] append 4 element: [100 101 102 103 104], len:5, cap:8 string slice [0xc00006a040] append 5 element: [100 101 102 103 104 105], len:6, cap:8 string slice [0xc00006a040] append 6 element: [100 101 102 103 104 105 106], len:7, cap:8 string slice [0xc00006a040] append 7 element: [100 101 102 103 104 105 106 107], len:8, cap:8 string slice [0xc00006a040] append 8 element: [100 101 102 103 104 105 106 107 108], len:9, cap:16 string slice [0xc00006a040] append 9 element: [100 101 102 103 104 105 106 107 108 109], len:10, cap:16 --------------------------------------- int slice pointer [0xc00007e020] init value: <nil> string slice pointer [0xc00007e028] init value: <nil> --------------------------------------- int slice pointer [0xc00007e020] init value: [100 101 102 103 104 105 106 107 108 109], len:10, cap:16 string slice pointer [0xc00007e028] init value: [100 101 102 103 104 105 106 107 108 109], len:10, cap:16 --------------------------------------- int slice make [0xc00006a340] init value: [0 0 0 0 0 0 0 0 0 0], len:10, cap:10 string slice make [0xc00006a360] init value: [ ], len:10, cap:10 --------------------------------------- int slice make [0xc00006a340] init value: [100 101 102 103 104 105 106 107 108 109], len:10, cap:10 string slice make [0xc00006a360] init value: [100 101 102 103 104 105 106 107 108 109], len:10, cap:10 --------------------------------------- ---------------------------------------
4. map
Map是引用類型,當 map 被賦值為一個新變量的時候,它們指向同一個內部數據結構。因此,改變其中一個變量,就會影響到另一變量。
map的零值是nil,不能插入元素。map沒有容量的概念,其長度為目前元素的個數。
只要map不為nil就可以無限插入元素。“map[]=”插入元素。
map實體初始化為nil。需要make()或“=map[int]int{}”進行初始化后才能加元素。
map指針初始化為nil。
make返回類型零值的map,且長度為0,無論make中是否指定len或指定len大小。
map只能和nil作比較。要比較map,需比較兩個map的每個元素。
package main import ( "fmt" "strconv" ) func main(){ var mi map[int]int var ms map[string]string fmt.Printf("int map [%p] init value: %v, len:%d\n", &mi, mi, len(mi)) fmt.Printf("string map [%p] init value: %v, len:%d\n", &ms, ms, len(ms)) fmt.Println("-------------------------------") var i int if mi == nil { mi = make(map[int]int) fmt.Printf("int map make [%p] init value: %v, len:%d\n", &mi, mi, len(mi)) for i = 0; i < 10; i++ { mi[i] = 100 + i fmt.Printf("int map make [%p] init %d value: %v, len:%d\n", &mi, i, mi, len(mi)) } } fmt.Println("-------------------------------") if ms == nil { ms = make(map[string]string, 10) fmt.Printf("string map make [%p] init value: %v, len:%d\n", &ms, ms, len(ms)) for i = 0; i < 10; i++ { k := strconv.Itoa(100+i) ms[k] = strconv.Itoa(100+i) fmt.Printf("string map make [%p] init [%v] value: %v, len:%d\n", &ms, k, ms, len(ms)) } } fmt.Println("-------------------------------") var pmi *map[int]int var pms *map[string]string // fmt.Printf("int map pointer [%p] init value: %v, len:%d\n", &pmi, pmi, len(*pmi)) // fmt.Printf("string map pointer [%p] init value: %v, len:%d\n", &pms, pms, len(*pms)) fmt.Printf("int map pointer [%p] init value: %v\n", &pmi, pmi) fmt.Printf("string map pointer [%p] init value: %v\n", &pms, pms) fmt.Println("-------------------------------") pmi = &mi pms = &ms fmt.Printf("int map pointer [%p] init value: %v, len:%d\n", &pmi, pmi, len(*pmi)) fmt.Printf("string map pointer [%p] init value: %v, len:%d\n", &pms, pms, len(*pms)) fmt.Println("-------------------------------") // fmt.Printf("%v\n==%v\n???\n%t\n", mi, *pmi, (mi==*pmi)) fmt.Println("-------------------------------") // fmt.Printf("%v\n==%v\n???\n%t\n", ms, *pms, (ms==*pms)) var mii map[int]int = map[int]int{} var mss map[string]string = map[string]string{} fmt.Printf("int map [%p] init value: %v, len:%d\n", &mii, mii, len(mii)) fmt.Printf("string map [%p] init value: %v, len:%d\n", &mss, mss, len(mss)) fmt.Println("-------------------------------") for i = 0; i < 10; i++ { mii[i] = 100 + i } for i = 0; i < 10; i++ { k := strconv.Itoa(100+i) mss[k] = strconv.Itoa(100+i) } fmt.Printf("int map [%p] init value: %v, len:%d\n", &mii, mii, len(mii)) fmt.Printf("string map [%p] init value: %v, len:%d\n", &mss, mss, len(mss)) fmt.Println("-------------------------------") }
運行結果:
int map [0xc00007e018] init value: map[], len:0 string map [0xc00007e020] init value: map[], len:0 ------------------------------- int map make [0xc00007e018] init value: map[], len:0 int map make [0xc00007e018] init 0 value: map[0:100], len:1 int map make [0xc00007e018] init 1 value: map[0:100 1:101], len:2 int map make [0xc00007e018] init 2 value: map[0:100 1:101 2:102], len:3 int map make [0xc00007e018] init 3 value: map[0:100 1:101 2:102 3:103], len:4 int map make [0xc00007e018] init 4 value: map[0:100 1:101 2:102 3:103 4:104], len:5 int map make [0xc00007e018] init 5 value: map[0:100 1:101 2:102 3:103 4:104 5:105], len:6 int map make [0xc00007e018] init 6 value: map[0:100 1:101 2:102 3:103 4:104 5:105 6:106], len:7 int map make [0xc00007e018] init 7 value: map[0:100 1:101 2:102 3:103 4:104 5:105 6:106 7:107], len:8 int map make [0xc00007e018] init 8 value: map[0:100 1:101 2:102 3:103 4:104 5:105 6:106 7:107 8:108], len:9 int map make [0xc00007e018] init 9 value: map[0:100 1:101 2:102 3:103 4:104 5:105 6:106 7:107 8:108 9:109], len:10 ------------------------------- string map make [0xc00007e020] init value: map[], len:0 string map make [0xc00007e020] init [100] value: map[100:100], len:1 string map make [0xc00007e020] init [101] value: map[100:100 101:101], len:2 string map make [0xc00007e020] init [102] value: map[100:100 101:101 102:102], len:3 string map make [0xc00007e020] init [103] value: map[100:100 101:101 102:102 103:103], len:4 string map make [0xc00007e020] init [104] value: map[100:100 101:101 102:102 103:103 104:104], len:5 string map make [0xc00007e020] init [105] value: map[100:100 101:101 102:102 103:103 104:104 105:105], len:6 string map make [0xc00007e020] init [106] value: map[100:100 101:101 102:102 103:103 104:104 105:105 106:106], len:7 string map make [0xc00007e020] init [107] value: map[100:100 101:101 102:102 103:103 104:104 105:105 106:106 107:107], len:8 string map make [0xc00007e020] init [108] value: map[100:100 101:101 102:102 103:103 104:104 105:105 106:106 107:107 108:108], len:9 string map make [0xc00007e020] init [109] value: map[100:100 101:101 102:102 103:103 104:104 105:105 106:106 107:107 108:108 109:109], len:10 ------------------------------- int map pointer [0xc00007e030] init value: <nil> string map pointer [0xc00007e038] init value: <nil> ------------------------------- int map pointer [0xc00007e030] init value: &map[0:100 1:101 2:102 3:103 4:104 5:105 6:106 7:107 8:108 9:109], len:10 string map pointer [0xc00007e038] init value: &map[100:100 101:101 102:102 103:103 104:104 105:105 106:106 107:107 108:108 109:109], len:10 ------------------------------- ------------------------------- int map [0xc00007e040] init value: map[], len:0 string map [0xc00007e048] init value: map[], len:0 ------------------------------- int map [0xc00007e040] init value: map[0:100 1:101 2:102 3:103 4:104 5:105 6:106 7:107 8:108 9:109], len:10 string map [0xc00007e048] init value: map[100:100 101:101 102:102 103:103 104:104 105:105 106:106 107:107 108:108 109:109], len:10 -------------------------------
5. struct
結構體是值類型,可以直接用=賦值。
結構體實體初始化為每個成員的零值,僅為某些字段指定初始值時,忽略的字段會賦值為零值。
結構體指針值為nil。
new()返回指向類型零值的指針。
如果它的每一個字段都是可比較的,則該結構體也是可比較的。如果兩個結構體變量的對應字段相等,則這兩個變量也是相等的。如果結構體包含不可比較的字段,則結構體變量也不可比較。
map可以以指針和實體方式返回,函數返回后可以通過返回值訪問到原來函數內部的結構體(即函數內部的結構體不會隨着函數結束而被回收)。
package main import ( "fmt" ) type People struct { Name string Phone string Addr []string } func main(){ var pStruct People // if pStruct == nil { // fmt.Println("var initvalue is null") // } else { fmt.Println("var initvalue init: ",pStruct) fmt.Println("var initvalue init: Name: ", pStruct.Name) fmt.Println("var initvalue init: Name: ", pStruct.Phone) fmt.Println("var initvalue init: Name: ", pStruct.Addr, ", len:", len(pStruct.Addr)) pStruct = People{"wang", "123456", []string{"Beijing", "Shanghai"}} fmt.Println("after var initvalue init: ", pStruct) // } fmt.Println("-------------------------------------------") var p *People if p == nil { fmt.Println("pointer initvalue is null") } else { fmt.Println("pointer initvalue is ", p) } fmt.Println("-------------------------------------------") peo := new(People) if peo == nil { fmt.Println("new struct initvalue is null") } else { fmt.Println("new struct initvalue is ", peo) peo.Name = "wang" peo.Phone = "123456" fmt.Println("after new struct initvalue is ", peo) } fmt.Println("-------------------------------------------") tmp, _ := testReturn() fmt.Printf("return [%p] value: %v\n", &tmp, tmp) fmt.Println("-------------------------------------------") ptmp, _ := testReturnPointer() fmt.Printf("return pointer [%p]:[%p] value: %v\n", &ptmp, ptmp, *ptmp) fmt.Println("-------------------------------------------") } func testReturnPointer()(*People, error){ tmp := People{} tmp.Name = "wang" tmp.Phone = "123" fmt.Printf("In function, return pointer [%p] value: %v\n", &tmp, tmp) return &tmp, nil } func testReturn()(People, error){ tmp := People{} tmp.Name = "wang" tmp.Phone = "123" fmt.Printf("In function, return [%p] value: %v\n", &tmp, tmp) return tmp, nil }
運行結果:
var initvalue init: { []} var initvalue init: Name: var initvalue init: Name: var initvalue init: Name: [] , len: 0 after var initvalue init: {wang 123456 [Beijing Shanghai]} ------------------------------------------- pointer initvalue is null ------------------------------------------- new struct initvalue is &{ []} after new struct initvalue is &{wang 123456 []} ------------------------------------------- In function, return [0xc0000841c0] value: {wang 123 []} return [0xc000084180] value: {wang 123 []} ------------------------------------------- In function, return pointer [0xc000084280] value: {wang 123 []} return pointer [0xc00007e020]:[0xc000084280] value: {wang 123 []} -------------------------------------------