【问题标题】:Go: Embedding a primitive type?Go:嵌入原始类型?
【发布时间】:2016-08-07 05:40:43
【问题描述】:

假设我们有这段代码:

type User struct {
    int32
    Name string
}

这种类型的嵌入有用吗?
int32 是否有任何其他人可以调用 User 实例的方法?
如何访问 User 嵌入的 int32 的值?

【问题讨论】:

  • 您可以使用 User 作为该类型。以if user > 0 ... 为例。如果原语有方法,那么这些方法也会被提升。
  • @eduncan911 你能粘贴一个示例代码吗?我无法在 Go Playground 上做到这一点。
  • @eduncan911 不,你不能这样做:u > int32(0) 导致invalid operation: u > int32(0) (mismatched types User and int32)
  • 啊,没错。你仍然需要通过名称访问属性:play.golang.org/p/mIk_7ewRkN

标签: go struct embedding


【解决方案1】:

int32 类型是predeclared type,它没有方法。验证:

fmt.Println(reflect.TypeOf(int32(0)).NumMethod()) // Prints 0

您可以使用不合格的类型名称作为字段名称(Spec: Struct types)来引用所有嵌入的字段,预声明的类型也不例外。看这个例子:

u := User{3, "Bob"}
fmt.Printf("%#v\n", u)
u.int32 = 4
fmt.Println(u.int32)

输出(在Go Playground 上试试):

main.User{int32:3, Name:"Bob"}
4

使用嵌入的主要收获是:

  • 嵌入类型的方法得到提升,因此更容易实现接口(您不需要提供得到提升的方法)

  • 您可以“覆盖”嵌入类型的方法(在嵌入器类型上):提供您自己的实现,当使用您的嵌入器类型的值时将调用该实现

  • 并且嵌入类型的字段得到提升,因此引用提升字段的代码更短(省略了字段名称)。

通过嵌入预先声明的类型,例如 int32,与仅使用常规字段(命名,而不是嵌入字段)相比,您不会获得任何优势,因为 int32 类型没有有任何方法或字段。

往前走,除了没有优势,你甚至还有劣势。由于预先声明的类型名称以小写字母开头,隐式嵌入它们会使它们未导出,因此您只能在嵌入器类型的声明包中引用它们。如果您将它们设为常规的命名字段,您可以选择使用大写名称使其导出,或使用小写名称使其不导出。

【讨论】:

  • 有趣地使用“”标签
  • 有趣的是,包含空格或符号(数组/切片、映射、通道)的原始类型不能以这种方式嵌入,需要“typedef”(类型声明),如type MapStringInt map[string]int 或@ 987654332@.
  • @SiuChingPong-AsukaKenji-这实际上是不合格的类型名称“成为”字段名称的结果,[ ] < -等字符不允许出现在identifiers中。
  • 是的,我注意到了。但遗憾的是,只提升了匿名字段的“方法”,而不是“操作符”。因此,即使在上面的User 中嵌入了匿名RecvChanInt(又名<-chan int),仍然无法做到<- u,而只能做到<- u.RecvChanInt
  • @SiuChingPong-AsukaKenji- 那是因为它会模棱两可。想象一下,您嵌入了 2 个通道(2 种不同类型,通道作为基础类型),然后您编写了 <- u。这意味着哪个频道?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-20
  • 2013-07-29
  • 2021-02-10
  • 2016-08-25
  • 1970-01-01
  • 2020-02-18
相关资源
最近更新 更多