Golang结构体继承不按预期工作?

28

看看这个沙盒

当声明一个从另一个结构体继承的结构体时:

type Base struct {
    a string
    b string
}

type Something struct {
    Base
    c string
}

然后调用指定继承值的函数会导致编译错误:

f(Something{
    a: "letter a",
    c: "letter c",
})

错误信息为:在结构体字面量中未知的 Something 字段 'a'

这对我来说似乎非常奇怪。这真的是预期的功能吗?

谢谢帮助!

4个回答

40

Golang没有提供典型的继承概念。你所做的是嵌入。它不会给外层结构体提供内部结构体的字段,而是允许外层结构体访问内部结构体的字段。

为了创建外层结构体Something,你需要为其提供包括内部结构体Base在内的字段。

在你的情况下:

Something{Base: Base{a: "letter a"}, c: "letter c"}

2
一个好的结果是,如果你使用json.Marshal,你将得到你想要的{a,b,c}结构。 - Kat Lim Ruiz

11

你需要明确地创建基础字段,如下所示

f(Something{
    Base: Base{a: "letter a"},
    c:    "letter c",
})

Go语言没有继承,只有组合。


2
组合是普遍存在的计算机科学术语,但值得指出的是这里实际使用的Go特性是嵌入。 - evanmcdonnal
1
@evanmcdonnal 没错,但我故意使用了这个措辞,因为参考了 https://en.wikipedia.org/wiki/Composition_over_inheritance - Grzegorz Żur

5

你需要实例化嵌入的结构体。需要注意的是,Go语言中并没有继承这一概念,因此该特性被称为embedding。Embedding从嵌入类型继承字段和方法,并提升它们到嵌入器的作用域。所以,你尝试进行的组合字面量实例化应该像这样:

f(Something{
    Base: Base{a: "a", b: "b"},
    c:    "c",
})

0
阅读来自Go by Example: Struct Embedding的示例,诀窍在于我们需要显式地初始化嵌入的结构体,但我们可以直接访问嵌入的字段。
type base struct {
    num int
}
type container struct {
    base
    str string
}
// initialize the embedding explicitly
co := container{
    base: base{
       num: 1,
    },
    str: "some name",
}
// however, the embedded field can be accessed directly
fmt.Printf("co={num: %v, str: %v}\n", co.num, co.str)
// this also works
fmt.Println("also num:", co.base.num)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接