谈一谈golang接口和结构体的三种嵌套及匿名字段

4,680 阅读2分钟

谈一谈golang接口和结构体的三种嵌套及匿名字段

1.结构体嵌套结构体(struct,struct)

在Go语言中,可以将一个命名结构体当作另一个结构体类型的匿名字段和非匿名字段使用。

type tag1 struct {
    info1 string
}
​
type tag2 struct {
    info2 string
}
​
type User struct {
    name string
    tag1 tag1 //非匿名结构体
    tag2      //匿名结构体
}
​
func main() {
​
    u := &User{
        name: "DoveOne",
        tag1: tag1{info1: "this is tag1"},
        tag2: tag2{info2: "this is tag2"},
    }
    fmt.Printf("User's name is %s\n", u.name)
    fmt.Println(u.tag1.info1) //非匿名字段必须指定字段名才能引用字段的方法
    fmt.Println(u.info2)      //匿名字段可以直接引用该字段的方法
    fmt.Println(u.tag2.info2) //匿名字段也可以指定字段名引用字段的方法
}
​

输出

User's name is DoveOne
this is tag1
this is tag2
this is tag2

2.接口嵌套接口(interface,interface)

在Go语言中,不仅结构体与结构体之间可以嵌套,接口与接口间也可以通过嵌套创造出新的接口

一个接口可以包含一个或多个其他的接口,这相当于直接将这些内嵌接口的方法列举在外层接口中一样。只要接口的所有方法被实现,则这个接口中的所有嵌套接口的方法均可以被调用。

比如接口Person包含了Number和Name的所有方法,它还额外有一个Hello()方法

type Name interface {
   WriteName(name string)
}
​
type Number interface {
   WriteNumber(number string)
}
​
type Person interface {
   Name
   Number
   Hello()
}
​
type person struct {
   name   string
   number string
}
​
func (p *person) WriteName(name string) {
   p.name = name
}
​
func (p *person) WriteNumber(number string) {
   p.number = number
}
​
func (p person) Hello() {
   fmt.Println("hello")
}
​
func main() {
   p := person{}
   fmt.Println("Person:", p.name, p.number)
   p.WriteName("DoveOne")
   p.WriteNumber("1")
   p.Hello()
   fmt.Println("Person:", p.name, p.number)
}

输出

Person:
hello           
Person: DoveOne 1

3.在结构体中内嵌接口(struct,interface)

在go源码中能经常看到这种嵌套方式,结构体内嵌接口,要满足接口的赋值对象实现了该接口的所有方法

当初始化结构体Person时,需要传入一个实现接口Hello的结构体赋值,定义了hello结构体。

type HelloWorld interface {
    Hello()
}
​
type Person1 struct {
    Name   string
    Number string
    HelloWorld  //匿名字段
}
​
type Person2 struct {
    Name   string
    Number string
    tag    HelloWorld //非匿名字段
}
​
type hello struct {
}
​
func (h hello) Hello() {
    fmt.Println("hello")
}
​
func main() {
    h := hello{}
    p1 := &Person1{"DoveOne", "1", h}
    //p1.Hello() //结构体内嵌接口时,匿名字段不可以直接引用该字段的方法
    // 这里会报错cannot call non-function p1.Hello (type Hello)
​
    p1.HelloWorld.Hello()
    p2 := &Person2{"DoveOne", "1", h}
    p2.tag.Hello() //非匿名字段必须指定字段名才能引用字段的方法
}

输出

hello
hello

本文正在参加技术专题18期-聊聊Go语言框架