首页 > 文章列表 > 在Go中,为什么不能将嵌入的结构分配给父结构?

在Go中,为什么不能将嵌入的结构分配给父结构?

165 2024-05-05
问题内容

我有下面的代码尝试将嵌入结构分配给其父结构。有两套结构: guider 是父结构,datablock 从它扩展。方法 func put(x guider) 接受类型为 guider 的参数。当我传递 datablock 变量时它起作用。

另一种情况是mock继承自zerolog.event,但是在方法test(e zerolog.event)上传递参数失败

我收到以下错误:

cannot use m (variable of type mock) as type zerolog.event in argument to test

为什么这两种情况的工作方式不同?我怎样才能让它们都工作?

package main

import (
    "fmt"

    "github.com/rs/zerolog"
)

type Guider interface {
    Guid() string
}
type FSEntity struct {
    guid string
}

func (e FSEntity) Guid() string {
    return e.guid
}

func Put(x Guider) {
    fmt.Printf("%+vn", x)

}

type Mock struct {
    zerolog.Event
}

func Test(e zerolog.Event) {

}

//Child struct:

type DataBlock struct {
    FSEntity
    data []byte
}

func main() {
    myVar := DataBlock{}
    myVar.guid = "test"
    myVar.data = []byte("moar test")
    Put(myVar) // it works

    m := Mock{}
    Test(m) // it doesn't work. cannot use m (variable of type Mock) as type zerolog.Event in argument to Test
}


正确答案


首先,有几个定义:

多态性

多态性是为不同类型的实体提供单一接口或使用单一符号来表示多种不同类型。

子类型

子类型(也称为子类型多态性或包含多态性)是类型多态性的一种形式,其中子类型是通过某种可替换性概念与另一种数据类型(超类型)相关的数据类型,这意味着程序元素(通常是子例程或函数) ,编写为对超类型的元素进行操作也可以对子类型的元素进行操作

继承

在面向对象编程中,继承是将一个对象或类建立在另一个对象(基于原型的继承)或类(基于类的继承)之上的机制,并保留类似的实现。

对象组合

对象组合和对象聚合是将对象或数据类型组合成更复杂的对象或数据类型的密切相关的方法。

Golang遵循组合优于继承原则,例如它不支持继承。所以当你说

模拟扩展自zerolog.Event

您实际上的意思是 Mock 包含 zerolog.Event 结构。

Golang实现多态的方式是interface。所有实现某个接口的类型都可以在其位置上使用。这就是您使用 Guider 时看到的内容。

但是,它不适用于简单的结构。 zerolog.EventMock 内部的一个结构体。

因此,通常情况下,Test函数应该接受某个接口作为参数,并且模拟事件和真实事件都应该实现该接口。然而,看起来zerolog并没有提供Event的接口。因此,您应该访问结构体的 Event 字段。 示例