zoukankan      html  css  js  c++  java
  • 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
    ", &ai, ai)
        fmt.Printf("string array [%p] init value: %v
    ", &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
    ", &ai, ai)
        fmt.Printf("string array [%p] init value: %v
    ", &as, as)
        fmt.Println("---------------------------")
    
        var pai *[10]int
        var pas *[10]string
        fmt.Printf("int point array [%p] init value: %v
    ", &pai, pai)
        fmt.Printf("string point array [%p] init value: %v
    ", &pas, pas)
        fmt.Println("---------------------------")
    
        pai = &ai
        pas = &as
        pai[0] = 1
        pas[0] = "1"
        fmt.Printf("int point array [%p] init value: %v
    ", &pai, *pai)
        fmt.Printf("string point array [%p] init value: %v
    ", &pas, *pas)
        fmt.Println("---------------------------")
    
        paii := new([10]int)
        pass := new([10]string)
        fmt.Printf("int point array [%p] init value: %v
    ", &paii, *paii)
        fmt.Printf("string point array [%p] init value: %v
    ", &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
    ", &paii, *paii)
        fmt.Printf("string point array [%p] init value: %v
    ", &pass, *pass)
        fmt.Println("---------------------------")
    
        paii[0] = 1
        pass[0] = "1"
        fmt.Printf("%v
    ==
    %v 
    ???
    %t
    ", ai, *paii, (ai==*paii))
        fmt.Println("---------------------------")
        fmt.Printf("%v
    ==
    %v 
    ???
    %t
    ", 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
    ", &si, si, len(si), cap(si))
        fmt.Printf("string slice [%p] init value: %v, len:%d, cap:%d
    ", &ss, ss, len(ss), cap(ss))
    //    fmt.Printf("int slice [%p] init value: %v
    ", &si, si[0])
    //    fmt.Printf("string slice [%p] init value: %v
    ", &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
    ", &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
    ", &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
    ", &psi, psi, len(*psi), cap(*psi))
    //    fmt.Printf("string slice pointer [%p] init value: %v, len:%d, cap:%d
    ", &pss, pss, len(*pss), cap(*pss))
        fmt.Printf("int slice pointer [%p] init value: %v
    ", &psi, psi)
        fmt.Printf("string slice pointer [%p] init value: %v
    ", &pss, pss)
        fmt.Println("---------------------------------------")
        psi = &si
        pss = &ss
        fmt.Printf("int slice pointer [%p] init value: %v, len:%d, cap:%d
    ", &psi, *psi, len(*psi), cap(*psi))
        fmt.Printf("string slice pointer [%p] init value: %v, len:%d, cap:%d
    ", &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
    ", &sim, sim, len(sim), cap(sim))
        fmt.Printf("string slice make [%p] init value: %v, len:%d, cap:%d
    ", &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
    ", &sim, sim, len(sim), cap(sim))
        fmt.Printf("string slice make [%p] init value: %v, len:%d, cap:%d
    ", &ssm, ssm, len(ssm), cap(ssm))
        fmt.Println("---------------------------------------")
    
    //    fmt.Printf("%v
    ==
    %v
    ???
    %t
    ", si, *psi, (si==*psi))
        fmt.Println("---------------------------------------")
    //    fmt.Printf("%v
    ==
    %v
    ???
    %t
    ", 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
    ", &mi, mi, len(mi))
        fmt.Printf("string map [%p] init value: %v, len:%d
    ", &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
    ", &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
    ", &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
    ", &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
    ", &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
    ", &pmi, pmi, len(*pmi))
    //    fmt.Printf("string map pointer [%p] init value: %v, len:%d
    ", &pms, pms, len(*pms))
        fmt.Printf("int map pointer [%p] init value: %v
    ", &pmi, pmi)
        fmt.Printf("string map pointer [%p] init value: %v
    ", &pms, pms)
        fmt.Println("-------------------------------")
    
        pmi = &mi
        pms = &ms
        fmt.Printf("int map pointer [%p] init value: %v, len:%d
    ", &pmi, pmi, len(*pmi))
        fmt.Printf("string map pointer [%p] init value: %v, len:%d
    ", &pms, pms, len(*pms))
        fmt.Println("-------------------------------")
    
    //    fmt.Printf("%v
    ==%v
    ???
    %t
    ", mi, *pmi, (mi==*pmi))
        fmt.Println("-------------------------------")
    //    fmt.Printf("%v
    ==%v
    ???
    %t
    ", 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
    ", &mii, mii, len(mii))
        fmt.Printf("string map [%p] init value: %v, len:%d
    ", &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
    ", &mii, mii, len(mii))
        fmt.Printf("string map [%p] init value: %v, len:%d
    ", &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
    ", &tmp, tmp)
        fmt.Println("-------------------------------------------")
    
        ptmp, _ := testReturnPointer() 
        fmt.Printf("return pointer [%p]:[%p] value: %v
    ", &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
    ", &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
    ", &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 []}
    -------------------------------------------
  • 相关阅读:
    SQL Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表?
    SQL Server 分区表
    SQL Server表分区
    Red Gate系列之一 SQL Compare 10.4.8.87 Edition 数据库比较工具 完全破解+使用教程
    C# WinForm开发系列
    C# WinForm开发系列
    富文本编辑器 CKeditor 配置使用
    C# ListView用法详解
    C# WinForm给Button或其它控件添加快捷键响应
    WebApi安全性 使用TOKEN+签名验证
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/12006394.html
Copyright © 2011-2022 走看看