[golang ] 结构体

结构体的定义:

type person struct {
	name string
	age  int
}

使用:

var lily person

未赋值的结构体,其中所有字段拥有对应类型的零值。与 map 不同,声明后显式赋值为空或没有赋值,效果都一样,都是将结构体内各字段设置为零值,所以上面的声明和下面赋值的结果是等效的:

lily := person{}

初始化结构体中的字段有两种形式,一种是不指定字段名,按照结构体中字段声明的顺序依次指定初始值;另一种类似 map,指定键值对:

func main() {
	foo := person{
		"foo",
		1,
	}
	bar := person{
		name: "bar",
		age:  2,
	}
	fmt.Println(foo, bar) // {foo 1} {bar 2}
}

结构体中字段的访问:

foo.age = 22
fmt.Println(foo.name)

注意与 map 区分,后者使用方括号访问字段。

匿名结构体

可以声明变量时实现结构体的功能而不单独声明该结构体类型,此时隐式地创建了匿名结构体,这在将其他数据转成 Go 中的结构体或将 Go 数据转成 JSON 时会常用到:

func main() {
	var person struct {
		name string
		age  int
	}
	person.name = "foo"

	pet := struct {
		name string
		leg  int
	}{
		name: "blah",
		leg:  4,
	}

	fmt.Println(person, pet) // {foo 0} {blah 4}
}

结构体的比较和转换

结构体是否可进行比较取决于其中包含的字段是不是全部可比较,如果包含 slice,map 类型的字段,则不能被比较。

不同类型的原始值之间不能进行比较,同埋,不同类型的结构体也一样。

但有种情况下,结构体之间可进行互相转换:结构体内字段名一样,字段类型一致,且字段顺序也一样。转换后即可进行比较。

考察如下示例代码:

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

  // 可转换,因为字段名,类型,顺序均匹配
	type person2 struct {
		name string
		age  int
	}
  // 不可转换,因为字段顺序不一致
	type person3 struct {
		age  int
		name string
	}
  // 不可转换,因为字段名不匹配
	type person4 struct {
		firstName string
		age       int
	}
  // 不可转换,因为有多余字段
	type person5 struct {
		name   string
		age    int
		gender byte
	}

}

另外,如果进行比较的两个结构体,至少一个是匿名结构体的话,且满足字段名,类型和顺序一致,则无须转换直接比较。