GO类型嵌套

在GO结构体类型中嵌套一个其他的类型可以到达继承的目的。

语法:

struct {

T | *T

}

A field or method f of an anonymous field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.

Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the struct.


Given a struct type S and a type named T, promoted methods are included in the method set of the struct as follows:

  • If S contains an anonymous field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.
  • If S contains an anonymous field *T, the method sets of S and *S both include promoted methods with receiver T or *T.

example1:通过类型组合达到继承的目的
//main.go
package main
import "fmt"
type Father struct { //父类
    name string
    age  int
}
func (f Father) Speek(x string) { //父类Speek方法
    fmt.Println(x)
}
func (f *Father) Grow() { //父类Grow方法
    f.age += 1
}
type Child struct { //子类
    Father //类型组合
    height float32
}
func main() {
    var f = Father{name: "zlf", age: 30}
    var c = Child{Father: f, height: 170} //由于c.Father类型是值类型,所以将f赋值给c.Father时,会发生值拷贝过程
    c.Speek("Hello World")                //子类对象直接调用父类的Speek方法
    fmt.Println(c)
    c.Grow() //子类对象调用父类的Grow方法,但是Grow方法的接收器是c.Father,而不是c,更不是f
    fmt.Println("c = ", c)
    fmt.Println("f = ", f)
}
 
编译运行:

C:/go/bin/go.exe run test5.go [E:/project/go/proj/src/test]

Hello World

{{zlf 30} 170}

c = {{zlf 31} 170}

f = {zlf 30}

成功: 进程退出代码 0.

example2:嵌套类型Father,查看子类型Child的方法集

//main.go
package main
 
 
import "fmt"
 
 
type Father struct { //父类
    name string
    age  int
}
 
 
func (f Father) Speek(x string) { //父类Speek方法
    fmt.Println(x)
}
func (f Father) Grow() { //父类Grow方法
    f.age += 1
}
 
 
type Child struct { //子类
    Father //类型组合
    height float32
}
 
 
type SpeekGrower interface {
    Speek(x string)
    Grow()
}
 
 
func main() {
    var f = Father{name: "zlf", age: 30}
    var c = Child{Father: f, height: 170} //由于c.Father类型是值类型,所以将f赋值给c.Father时,会发生值拷贝过程
    var sg SpeekGrower
    sg = c  //类型CHILD
    sg.Speek("This is a test.")
    sg = &c  //类型*CHILD
    sg.Speek("This is a test.")
}
编译运行:

C:/go/bin/go.exe run test7.go [E:/project/go/proj/src/test]

This is a test.

This is a test.

成功: 进程退出代码 0.

//main.go
//main.go
package main
import "fmt"
type Father struct { //父类
    name string
    age  int
}
func (f Father) Speek(x string) { //父类Speek方法
    fmt.Println(x)
}
func (f *Father) Grow() { //父类Grow方法
    f.age += 1
}
type Child struct { //子类
    Father //类型组合
    height float32
}
type SpeekGrower interface {
    Speek(x string)
    Grow()
}
func main() {
    var f = Father{name: "zlf", age: 30}
    var c = Child{Father: f, height: 170} //由于c.Father类型是值类型,所以将f赋值给c.Father时,会发生值拷贝过程
    var sg SpeekGrower
    sg = c  //因为c类型是Child,值类型,赋值给接口时,会发生值拷贝,所以,该操作成功的前提是Child的所有方法都必须是值接收器
    sg.Speek("This is a test.")
    sg = &c
    sg.Speek("This is a test.")
}
编译运行:

C:/go/bin/go.exe run test7.go [E:/project/go/proj/src/test]

# command-line-arguments

.\test7.go:32: cannot use c (type Child) as type SpeekGrower in assignment:

Child does not implement SpeekGrower (Grow method has pointer receiver)

错误: 进程退出代码 2.


总结:通过上面两个例子,可以看出,当嵌套类型是Father时,类型Child的方法集只包括Father中接收器为值的方法;类型*Child的方法集包含了Father中所有的方法,所以*Child实现了上述的接口。


example3:嵌套类型*Father,查看子类型Child的方法集
//main.go
package main
 
 
import "fmt"
 
 
type Father struct { //父类
    name string
    age  int
}
 
 
func (f Father) Speek(x string) { //父类Speek方法
    fmt.Println(x)
}
func (f *Father) Grow() { //父类Grow方法
    f.age += 1
}
 
 
type Child struct { //子类
    *Father //类型组合
    height  float32
}
 
 
type SpeekGrower interface {
    Speek(x string)
    Grow()
}
 
 
func main() {
    var f = Father{name: "zlf", age: 30}
    var c = Child{Father: &f, height: 170}
    var sg SpeekGrower
    sg = c //类型Child,这里会发生值拷贝
    sg.Speek("This is a test.")
    sg = &c //类型*Child,这里会发生引用传递
    sg.Speek("This is a test.")
}
 编译运行: 

C:/go/bin/go.exe run test7.go [E:/project/go/proj/src/test]

This is a test.

This is a test.

成功: 进程退出代码 0.


OK,通过上面的案例可以看出,当内嵌类型是*Father时,类型Child和*Child都包含了Speek和Grow方法,所以实现了SpeekGrower接口。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Go语言中,结构体嵌套是一种将一个结构体类型作为另一个结构体类型的字段的方式。通过结构体嵌套,我们可以创建更复杂的数据结构,方便地组织和访问数据。 要获取嵌套结构体中的数据,可以通过以下两种方式进行操作: 1. 使用点操作符(.):通过点操作符可以直接访问嵌套结体中的字段。例如,如果有一个结构体A内嵌了结构体B,而B有一个字段叫做"field",那么可以通过"A.B.field"来获取该字段的值。 2. 使用匿名字段:当一个结构体嵌套了另一个结构体,并且嵌套的字段没有指定名称时,被嵌套的结构体称为匿名字段。通过匿名字段,可以直接访问嵌套结构体中的字段,就像直接访问当前结构体的字段一样。例如,如果有一个结构体A内嵌了结构体B,而B有一个字段叫做"field",那么可以直接使用"A.field"来获取该字段的值。 下面是一个示例代码,演示了如何使用结构体嵌套获取数据: ```go package main import "fmt" type Address struct { City string State string } type Person struct { Name string Age int Address Address } func main() { p := Person{ Name: "John", Age: 30, Address: Address{ City: "New York", State: "NY", }, } fmt.Println("Name:", p.Name) fmt.Println("Age:", p.Age) fmt.Println("City:", p.Address.City) fmt.Println("State:", p.Address.State) } ``` 输出结果为: ``` Name: John Age: 30 City: New York State: NY ``` 通过上述代码可以看到,我们可以通过点操作符或者直接访问匿名字段的方式来获取嵌套结构体中的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

历史五千年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值