综述
变量声明时未赋初值,则变量被自动赋值为该类型的零值(固定值)
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 []} -------------------------------------------