golang之類型零值初始化及比較


  1. 綜述

變量聲明時未賦初值,則變量被自動賦值為該類型的零值(固定值)

func new(Type) *Type

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()只適用於slicemapchan,此三種類型創建時推薦使用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零值為0string零值為""

數組指針初始化為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 []}
-------------------------------------------

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM