Go Lang 实战

Go数据-结构体(五)

2019-08-02  本文已影响0人  草莓君_

结构体

结构体(struct)将多个不同类型命名字段(field)序列打包成一个复合类型。

type node struct {
    _    int
    id   int
    next *node
}

func main() {
    n1 := node{
        id: 1,
    }
    n2 := node{
        id:   2,
        next: &n1,
    }
    fmt.Println(n1, n2)
}

可按顺序初始化全部字段,或使用命名方式初始化指定字段

func main() {
    type user struct {
        name string
        age int
    }

    u1 := user{"Tom", 12}
    u2 := user{"tome"} //编译报错too few values in user literal
}

可直接定义匿名结构类型变量,或用作字段类型。但因其缺少类型标识,在作为字段类型时无法直接初始化。

func main() {
    u := struct {
        name string
        age int
    }{
        name: "Tom",
        age: 19,
    }

    type file struct {
        name string
        attr struct{
            owner int
            perm int
        }
    }

    f := file{
        name: "test.dat",
        //attr: {           //错误missing type in composite literal
        //  owner: 1,
        //  perm: 0121,
        //},
    }

    f.attr.owner = 1 //正确方式
    f.attr.perm = 2

    fmt.Println(u, f)
}

只有在所有字段类型全部支持时,才可能做相等操作。

func main() {
    type data struct {
        x int
        y map[string]int
    }

    d1 := data{
        x: 1,
    }

    d2 := data{
        x: 1,
    }

    println(d1 == d2) //无效操作struct containing map[string]int cannot be compared
}

可使用指针直接操作结构字段,但不能时多级指针。

func main() {
    type user struct {
        name string
        age  int
    }

    p := &user{
        name: "Tom",
        age:  19,
    }
    
    p.name = "Mary"
    p.age++
}

空结构

空结构(struct{})是指没有字段的结构类型。他比较特殊,因为无论是其自身,还是作为数组元素类型,其长度都为零。

func main() {
    var a struct{}
    var b [100]struct{}
    println(unsafe.Sizeof(a),unsafe.Sizeof(b))
}

输出: 0 0
尽管没有分配数组内存,但依然可以操作元素,对应切片len、cap属性也正常。

func main() {
    var d [100]struct{}
    s := d[:]

    d[1] = struct{}{}
    d[2] = struct{}{}

    fmt.Println(s[3], len(s), cap(s))
}

输出:

{} 100 100

匿名字段

所谓匿名字段,是指没有名字,仅有类型的字段,也被称作嵌入字段或嵌入类型。

type attr struct {
    perm int
}
type file struct {
    name string
    attr        //仅有类型名
}

不能将基础类型和其指针类型同时嵌入,因为两者隐式名字相同。

type data struct {
    *int
    int   //错误 duplicate field int
}

虽然可以像普通字段那样访问匿名字段成员,但会存在重名问题。默认情况下,编译器从当前显式命名字段开始,逐步向内查找匿名字段成员。如匿名字段成员被外层同名字段遮蔽,那么必须使用显式字段名。

func main() {
    d := data{
        name: "data",
        file: file{"file"},
    }
    d.name = "data2"        //当问data.name
    d.file.name = "file2"   //使用显式字段名访问 data.file.name

    fmt.Println(d.name, d.file.name)
}
上一篇 下一篇

猜你喜欢

热点阅读