复合字面量用作接口的地址

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

Address of composite literal used as interface

问题

复合字面量的地址在作为接口使用时被评估为字面量本身。请问有人可以指出参考规范中处理这个问题的部分吗?

package main
import "fmt"

type ntfc interface {
    rx() int
}

type cncrt struct {
    x int
}

func (c cncrt) rx() int{
    return c.x
}

func rtrnsNtfca() ntfc {
    return &cncrt{3}
}

func rtrnsNtfc() ntfc {
    return cncrt{3}
}

func rtrnsCncrt() *cncrt {
    return &cncrt{3}
}

func main() {
    fmt.Println(rtrnsNtfca().rx())
    fmt.Println(rtrnsNtfc().rx())
    fmt.Println(rtrnsCncrt().rx())
}

还有这里。以后参考,只链接到 playground 而不包含代码,这样可以吗?

英文:

The address of a composite literal is evaluated as the literal itself when used as an interface. Can somebody please point to the part of the ref spec which deals with this ?

package main
import "fmt"

type ntfc interface {
	rx() int
}

type cncrt struct {
	x int
}

func (c cncrt) rx() int{
	return c.x
}

func rtrnsNtfca() ntfc {
	return &cncrt{3}
}

func rtrnsNtfc() ntfc {
	return cncrt{3}
}

func rtrnsCncrt() *cncrt {
	return &cncrt{3}
}

func main() {
	fmt.Println(rtrnsNtfca().rx())
	fmt.Println(rtrnsNtfc().rx())
	fmt.Println(rtrnsCncrt().rx())
}

Also here. For future ref., is it acceptable to just link to the playground without including the code here?

答案1

得分: 2

[规范:方法集:]

  • 类型可以有与之关联的“方法集”。接口类型的方法集就是它的接口。其他任何类型 T 的方法集都包括所有以接收器类型 T 声明的方法。相应的指针类型 *T 的方法集是所有以接收器 *TT 声明的方法的集合(也就是说,它还包含 T 的方法集)。

因此,*cncrt 的方法集包括 cncrt 的方法集。由于 rx()cncrt 的方法集的元素,它也将在 *cncrt 的方法集中。这意味着 cncrt*cncrt 类型都实现了 ntfc 接口。

如果你有一个指针值(*cncrt)并在其上调用 rx(),指针将自动被解引用,成为 rx() 方法的接收器。

在你的 rtnsNtfca()rtnsNtfc() 函数中,将自动创建并返回一个 ntfc 接口值。在 Go 中,接口值表示为(类型;值)对(更多细节请参见:反射定律 #接口的表示)。因此,rtnsNtfca()rtnsNtfc() 都返回一个接口值,但前者持有类型为 *cncrt 的动态值,而后者持有类型为 cncrt 的动态值。

而你的第三个方法 rtrnsCncrt() 返回一个具体类型(*cncrt),其中没有涉及接口封装。

注意:“反过来”

[规范:调用:]

  • 如果 x可寻址的,并且 &x 的方法集包含 m,那么 x.m()(&x).m() 的简写。

这意味着如果你声明 rx() 具有指针接收器,并且你有一个类型为 cncrt 的变量(注意:不是指针),如果它是可寻址的,你仍然可以在其上调用 rx() 方法,地址会自动被取出并用作接收器。

英文:

Spec: Method sets:

> A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).

So the method set of *cncrt includes the methods set of cncrt. Since rx() is an element of cncrt's method set, it will also be in *cncrt's method set. Which means both cncrt and *cncrt types implement the ntfc interface.

If you have a pointer value (*cncrt) and you call rx() on it, the pointer will automatically be dereferenced which will be the receiver of the rx() method.

In your rtnsNtfca() and rtnsNtfc() functions an interface value of ntfc will automatically be created and returned. Interface values in Go are represented as (type;value) pairs (for more details: The Laws of Reflection #The representation of an interface). So both rtnsNtfca() and rtnsNtfc() return an interface value, but the first one holds a dynamic value of type *cncrt and the latter one holds a dynamic value of type cncrt.

And your 3rd method rtrnsCncrt() returns a concrete type (*cncrt), there is no interface wrapping involved there.

Note: "The other way around"

Spec: Calls:

> If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().

This means if you would have declared rx() to have a pointer receiver, and you have a variable of type cncrt (note: not pointer), you could still call the rx() method on it if it is addressable, and the address would be taken automatically and used as the receiver.

huangapple
  • 本文由 发表于 2015年8月3日 22:36:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/31790113.html
匿名

发表评论

匿名网友

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

确定