将接口嵌入结构体为什么会导致接口的方法集被定义为nil指针?

huangapple go评论77阅读模式
英文:

Why does embedding an Interface in a struct cause the Interface methodset to be defined as nil pointer?

问题

我正在学习Go语言,并遇到了在Go中将接口嵌入结构体的问题。

我理解接口及其实现的好处,但我对于将接口嵌入结构体的执行原因感到困惑。

当我在结构体中嵌入一个接口时,该结构体获得了该接口的方法集,并且现在可以作为接口类型变量的值使用,例如:

type Foo interface {
  SetBaz(baz) 
  GetBaz() baz
}

type Bar struct {
  Foo
}

现在我们有了一个嵌入了Foo的结构体类型Bar。因为Bar嵌入了Foo,所以Bar现在满足任何需要类型为Foo的接收器或参数,即使Bar并没有明确定义它们。

尝试调用Bar.GetBaz()会导致运行时错误:panic: runtime error: invalid memory address or nil pointer dereference

为什么Go会在嵌入接口的结构体上定义空方法,而不是通过编译器明确要求定义这些方法呢?

英文:

I'm working through learning Go, and I've come across embedding Interfaces into structs in Go.

I understand the joys of Interfaces and their implementations, but I'm confused as the reasoning for the current execution of embedding one inside a struct.

When I embed an interface in a struct, the struct gains the methodset of the Interface and can now be used as a value of an Interface type variable, eg:

type Foo interface {
  SetBaz(baz) 
  GetBaz() baz
}

type Bar struct {
  Foo
}

So now we have a struct type Bar which embeds Foo. Because Bar embeds Foo, Bar now satisfies any receivers or arguments that require type Foo, even though Bar hasn't even defined them.

Trying to call Bar.GetBaz() causes the runtime error: panic: runtime error: invalid memory address or nil pointer dereference.

Why does Go define nil methods on a struct that embeds an interface instead of explicitly requiring those methods to be defined through the compiler?

答案1

得分: 7

你对于nil方法的理解是错误的,实际上是嵌入到struct Bar中的interfacenil
当你使用接口的方法时,实际上调用的是这个接口。这个技巧允许我们覆盖接口方法。

要理解将interface嵌入到struct中的用法和目的,最好的例子是在sort包中:

type reverse struct {
	// 这个嵌入的接口允许 Reverse 使用另一个接口实现的方法。
	Interface
}

// Less 返回嵌入实现的 Less 方法的相反结果。
func (r reverse) Less(i, j int) bool {
	return r.Interface.Less(j, i)
}

// Reverse 返回数据的逆序。
func Reverse(data Interface) Interface {
	return &reverse{data}
}
英文:

You're wrong about the nil method, it's the interface embedded into the struct Bar that is nil.
When you use the methods of the interface, that is this interface that is called. The trick allow you to override an interface method with our own.

To understand the usage and goals of embedding interfaces into struct, the best example is in the sort package:

type reverse struct {
	// This embedded Interface permits Reverse to use the methods of
	// another Interface implementation.
	Interface
}

// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
	return r.Interface.Less(j, i)
}

// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
	return &reverse{data}
}

huangapple
  • 本文由 发表于 2016年1月13日 05:35:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/34754210.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定