满足接口的Go结构方法的类型 [英] Types of Go struct methods that satisfy an interface

查看:132
本文介绍了满足接口的Go结构方法的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下Go代码示例:

  package main 

importfmt
$ b b类型greeter接口{
hello()
goodbye()
}

类型tourGuide结构{
名称字符串


func(t tourGuide)hello(){
fmt.Println(Hello,t.name)
}

func t * tourGuide)goodbye(){
fmt.Println(Goodbye,t.name)
}

func main(){
var t1 tourGuide = tourGuide {James}
t1.hello()// Hello James
t1.goodbye()// Goodbye James(与(& t1).goodbye()相同)

var t2 * tourGuide =& tourGuide {Smith}
t2.hello()// Hello Smith
t2.goodbye()// Goodbye Smith(与(* t2)相同。 hello())

//非法:t1不能分配给g1(为什么?)
// var g1 greeter = t1

var g2 greeter = t2
g2.hello()// Hello Smith
g2.goodbye()//再见史密斯
}

我可以使用tourGuide类型的变量 t1 来调用struct tourGuide 的两个方法。或指向tourGuide t2 的指针。换句话说,我可以使用 T T 接收方的方法> * T 。同样,我可以使用 T 类型的变量来调用 * T 接收方的方法(if T addressable )或 * Ť。我知道编译器会处理这里的差异(请参阅我在代码中的注释)。

然而,当我们实现接口时事情会改变。在上面的代码中, greeter 接口类型的变量可以从指向 tourGuide 的指针指定,但不能从 tourGuide



有谁能告诉我为什么会出现这种情况?为什么我可以调用 t1.hello() t1.goodbye()但不知何故 t1 对于接口 greeter

解决方案如果一个方法有一个指针接收器,只有一个指针值可以用作接收器的值。因此,要在某个值上调用此方法,值本身必须是一个指针,或者必须可以获取其地址(用作接收者)。



例如,如果你有一个变量,它是 addressable ,因此可以得到它的地址和用它作为接收器。该规范允许你这样做,这是自动发生的。



封装在接口中的值不可寻址。当创建接口值时,将复制接口中包装的值。因此不可能采用它的地址。理论上你可以允许复制副本的地址,但这会成为(甚至)更多混淆的根源,因为地址会指向副本,而带指针接收器的方法只能修改副本而不是原来的。



看到这个答案哪些细节/证明值在创建接口值时被复制:片段如何包含自身?


Given the following Go code example:

package main

import "fmt"

type greeter interface {
    hello()
    goodbye()
}

type tourGuide struct {
    name string
}

func (t tourGuide) hello() {
    fmt.Println("Hello", t.name)
}

func (t *tourGuide) goodbye() {
    fmt.Println("Goodbye", t.name)
}

func main() {
    var t1 tourGuide = tourGuide{"James"}
    t1.hello()   // Hello James
    t1.goodbye() // Goodbye James (same as (&t1).goodbye())

    var t2 *tourGuide = &tourGuide{"Smith"}
    t2.hello()   // Hello Smith
    t2.goodbye() // Goodbye Smith (same as (*t2).hello())

    // illegal: t1 is not assignable to g1 (why?)
    // var g1 greeter = t1

    var g2 greeter = t2
    g2.hello()   // Hello Smith
    g2.goodbye() // Goodbye Smith
}

I'm able to call the two methods of the struct tourGuide using either a variable of type tourGuide t1 or a pointer to tourGuide t2. In other words, I can call a method with T receiver using a variable of type T or *T. Similarly, I can call a method with *T receiver using a variable of type T (if T is addressable) or *T. I understand that the compiler handles the differences here (see my comments in the code).

However, things change when we are implementing interfaces. In the above code, a variable of type greeter interface is assignable from a pointer to tourGuide but not from a tourGuide.

Can anyone tell me why this is the case? Why am I able to call t1.hello() and t1.goodbye() but somehow t1 is not enough for the interface greeter?

解决方案

If a method has a pointer receiver, only a pointer value can be used as the receiver value. So to call this method on some value, the value itself must be a pointer, or it must be possible to acquire its address (to be used as the receiver).

If you have a variable for example, it is addressable and thus it's possible to get its address and use that as the receiver. And the spec allows you to do this, this happens automatically.

Values wrapped in interfaces are not addressable. When an interface value is created, the value that is wrapped in the interface is copied. It is therefore not possible to take its address. Theoretically you could allow to take the address of the copy, but that would be the source of (even) more confusion than what benefit it would provide, as the address would point to a copy, and methods with pointer receiver could only modify the copy and not the original.

See this answer which details / proves that values are copied when the interface value is created: How can a slice contain itself?

这篇关于满足接口的Go结构方法的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆