美文网首页
golang struct{} 2022-02-15

golang struct{} 2022-02-15

作者: 9_SooHyun | 来源:发表于2022-02-19 16:34 被阅读0次

    golang 空struct内存占用为0,且所有的空struct都引用的是同一地址

    func TestEmptyStruct(t *testing.T) {
        type emptyStruct struct{}
        type emptyInside struct {
            emptyStruct
        }
        type personStruct struct {
            E1 emptyStruct
            A  struct {
                Age int
            }
            E2 emptyStruct
            S  struct {
                Sex string
            }
            E3 struct {
            }
        }
        a := struct{}{}
        b := emptyStruct{}
        eInside := emptyInside{emptyStruct: emptyStruct{}}
        fmt.Printf("%p\n", &a)
        fmt.Printf("%p\n", &b)
        fmt.Printf("%p\n", &eInside)
        fmt.Println("size of a is ", unsafe.Sizeof(a), " size of b is ", unsafe.Sizeof(b), " size of eInside is ", unsafe.Sizeof(eInside))
        // 0x2c2bb60
        // 0x2c2bb60
        // 0x2c2bb60  -> 空结构体(包括不断嵌套但仍然无任何内置字段的空结构体)的变量的内存地址都是一样的,所有空struct都是引用全局变量zerobase的地址
        // size of a is  0  size of b is  0  size of eInside is  0
    
        c := personStruct{}
        fmt.Printf("%s, %p\n", "c", &c)
        fmt.Printf("%s, %p\n", "c.E1", &c.E1)
        fmt.Printf("%s, %p\n", "c.A", &c.A)
        fmt.Printf("%s, %p\n", "c.E2", &c.E2)
        fmt.Printf("%s, %p\n", "c.S", &c.S)
        fmt.Printf("%s, %p\n", "c.E3", &c.E3)
        // c, 0xc00016b8e0
        // c.E1, 0xc00016b8e0
        // c.A, 0xc00016b8e0 -> c, c.E1, c.A地址相同,空结构体不占任何内存空间
        // c.E2, 0xc00016b8e8 -> e8 - e0 = 8. golang int类型在32位系统4字节 64位系统8字节
        // c.S, 0xc00016b8e8
        // c.E3, 0xc00016b8f8 -> f8 - e8 = 16
    
        // golang string数据类型占用16字节空间,
        // 前8字节是一个指针,指向字符串值的地址,
        // 后八个字节是一个整数,标识字符串的长度;
        // 注意go语言的字符串内部并不以'\0'作为结尾,而是通过一个长度域来表示字符串的长度
    }
    

    go编译器在编译期间,识别到 struct {} 这种特殊类型的内存分配,会统统分配出 runtime.zerobase 的地址出去,代码逻辑是在 mallocgc 函数里面:
    代码如下:

    func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
        // 分配 size 为 0 的结构体,把全局变量 zerobase 的地址给出去即可;
        if size == 0 {
            return unsafe.Pointer(&zerobase)
        }
        // ...
    

    相关文章

      网友评论

          本文标题:golang struct{} 2022-02-15

          本文链接:https://www.haomeiwen.com/subject/wlrllrtx.html