go语言中结构体匿名字段和嵌套结构体(继承)

结构体的匿名字段:

结构体允许其成员字段在声明时没有字段名而只有类型,这种没有名字的字段就称为名匿名字段。
匿名字段默认采用类型名作为字段名,结构体要求类型必须唯一

结构体中匿名字段的简单使用

package main
import ("fmt")

// 结构体匿名
type Person struct {
	string
	int
}

func main()  {
	var p1 = Person{
		"张三",
		18,
	}
	fmt.Println("%v",p1)
}

结构体的类型

结构体的字段类型可以是:基本数据类型、也可以是切片、Map 以及结构体
如果结构体的字段类型是:指针,slice,和map的零值都是 ni1,即还没有分配空间
如果需要使用这样的字段,需要先make,才能使用

package main
import ("fmt")
// 结构体匿名
type Person struct {
	name string
	age int
	hobby []string
	map1 map[string]string
}
func main()  {
	var p1 Person
	p1.name = "张三"
	p1.age = 18
	// 可以这样定义
	// p1.hobby = []string{"吃饭","睡觉","打豆豆"}

	p1.hobby = make([]string,2,6)
	p1.hobby[0] = "吃饭"
	p1.hobby[1] = "睡觉"

	p1.map1 = make(map[string]string)
	p1.map1["address"] = "王者峡谷"
	p1.map1["phone"] = "123456789"
	fmt.Println("%v",p1)
}

结构体嵌套结构体

package main
import ("fmt")

type User struct{ 
	Username string
	Password string
	// 表示:User结构体嵌套Address结构体
	Address Address
}
type Address struct{ 
	City  string
	Phone string
}


func main()  {
	var u User
	u.Username = "张三"
	u.Password = "123456"
	u.Address.City = "北京"
	u.Address.Phone = "123456789"
	fmt.Printf("%#v", u)
}

main.User{Username:"张三", Password:"123456", Address:main.Address{City:"北京", Phone:"123456789"}}

嵌套匿名结构体

type User struct{ 
	Username string
	Password string
	// 表示:User结构体嵌套Address结构体
	Address 
  // 等价与:Address Address ===> Address  嵌套匿名结构体
}
type Address struct{ 
	City  string
	Phone string
}

修改结构体的另外一种方式

先看 User 自己有没有直接字段 Phone;
如果没有,再看它嵌入的匿名字段 Address 有没有 Phone;
如果有,就解析成 u.Address.Phone。
总结:当访问结构体成员时会先在结构体中查找该字段,找不到再去匿名结构体中查找。

package main
import ("fmt")
type User struct{ 
	Username string
	Password string
	// 表示:User结构体嵌套Address结构体
	Address
}
type Address struct{ 
	City  string
	Phone string
}
func main()  {
	var u User
	u.Username = "张三"
	u.Password = "123456"
	u.Address.City = "北京"
	// 为啥这样也能够正常修改呢 ?
	u.Phone = "123456789"
	fmt.Printf("%#v", u)
}

main.User{Username:"张三", Password:"123456", Address:main.Address{City:"北京", Phone:"123456789"}}

结构体中有相同的字段,优先外层

package main
import ("fmt")
type User struct{ 
	Username string
	Password string
	// 表示:User结构体嵌套Address结构体
	Phone string // 结构体中有相同的字段
	Address
}
type Address struct{ 
	City  string
	Phone string // 结构体中有相同的字段
}
func main()  {
	var u User
	u.Username = "张三"
	u.Password = "#XC"
	u.Phone = "123456789"
	fmt.Printf("%#v", u)
}

规则:外层优先
Go 在查找 u.Phone 时,会按这个顺序:
先找 User 有没有接字段 Phone;
如果有,就用 User.Phone;
如果没有,才去嵌入字段 Address 里找 Address.Phone。
所以这里因为 User 自己就有 Phone,就直接修改了 User.Phone,不会去碰 Address.Phone。

结构体中有相同的字段,设置值时必须指明设置哪一个结构体

Address和 Info结构体中都有City字段,
如果我们设置 city字段时,必须写明设置哪一个结构体,否则会报错的哈。
u.City = "cd" 会报错。
因为City字段是Address和Info结构体中都有的。我们需要指明设置哪一个结构体。

package main
import ("fmt")
type User struct{ 
	Username string
	Password string
	Phone string 
	// 下面是结构体的嵌套
	Address
	Info
}
type Address struct{ 
	City  string
	Phone string 
}

type Info struct{ 
	City  string
}
func main()  {
	var u User
	u.Username = "张三"
  // 会报错的哈。会报错的哈
	u.City = "cd"
	fmt.Printf("%#v", u)
}

通过结构体的嵌套来实现继承

package main
import ("fmt")

type Animal struct { 
	name string
}
func (a Animal) run()  {
	fmt.Println("跑")
}

type Dog struct { 
	age string
	// 这个是匿名结构体,通过结构体的嵌套来实现继承哈
	Animal 
}
func (d Dog) wang()  {
	fmt.Println("汪汪汪")
}

func main()  {
	var d  = Dog{
		age: "1岁",
		Animal: Animal{name:"小狗"},
	}
	d.wang()
	// 我们可以去调用动物的跑,我们通过嵌套结构体来实现继承
	d.run()
}

输出:
汪汪汪
跑

一个结构体中可以嵌套另一个结构体或结构体指针

package main
import ("fmt")

type Animal struct { 
	name string
}
func (a Animal) run()  {
	fmt.Println("跑")
}

type Dog struct { 
	age string
	// 嵌套的是一个指针;某个内存地址所对应的值
	*Animal 
}
func (d Dog) wang()  {
	fmt.Println("汪汪汪")
}

func main()  {
	var d  = Dog{
		age: "1岁",
    // 通过[&变量名]来获取变量的内存地址
		Animal: &Animal{name:"小狗"},
	}
	d.wang()
	// 我们可以去调用动物的跑,我们通过嵌套结构体来实现继承
	d.run()
}

&变量名: 表示变量的内存地址,也叫做指针
*p表示:某个内存地址所对应的值;

posted @ 2026-09-29 23:04  何人陪我共长生  阅读(85)  评论(0)    收藏  举报