为什么我不能将类型的值分配给实现带有接收者类型指针的方法的接口? [英] Why can't I assign type's value to an interface implementing methods with receiver type pointer to that type?
问题描述
我在Golang的世界里只有2天大的时间,正在经历去旅行.我忍不住注意到了一种特殊性,我似乎无法用适当的推理来达成共识.
I am 2-days old in the world of Golang, and going through the go tour. I couldn't help but notice a peculiarity which I cannot seem to be able to come at terms with a proper reasoning.
此代码运行良好:
package main
import (
"fmt"
"math"
)
type Vertex struct{
X,Y float64
}
type Abser interface{
Abs() float64
}
func (v Vertex) Abs() float64{ //method with value receiver argument
return math.Sqrt(v.X*v.X+v.Y*v.Y)
}
func main(){
var myVer Vertex = Vertex{3,4}
var inter Abser
inter = &myVer //assigning *Vertex type to inter
fmt.Println(inter.Abs())
}
同时,以下代码显示错误:
Meanwhile, the following code shows an error:
package main
import (
"fmt"
"math"
)
type Vertex struct{
X,Y float64
}
type Abser interface{
Abs() float64
}
func (v *Vertex) Abs() float64{ //method with pointer receiver argument
return math.Sqrt(v.X*v.X+v.Y*v.Y)
}
func main(){
var myVer Vertex = Vertex{3,4}
var inter Abser
inter = myVer //assigning Vertex type to inter
fmt.Println(inter.Abs())
}
错误是:
interface.go:18:无法在分配中使用myVer(顶点类型)作为Abser类型:顶点不实现Abser(Abs方法具有指针接收器)
interface.go:18: cannot use myVer (type Vertex) as type Abser in assignment: Vertex does not implement Abser (Abs method has pointer receiver)
在进入本节之前,我可以理解Go的创建者已经放弃了诸如此类的繁琐符号
Until reaching this section of the tour, I could understand that the creators of Go have let-go of the cumbersome notations like
(* v).method1name()
(*v).method1name()
(& v).method2name()
(&v).method2name()
因此具有值接收器的方法可以与值和指针一起使用,反之亦然.
So that methods with value receivers can be used with both values and pointers, and vice versa.
在使用接口时,为什么该语言区分两者(值和指针)?如果可以在此处应用相同的引用/取消引用原则会更方便吗?
Why does the language discriminate between the two (value and pointer) when working with interfaces? Wouldn't it be more convenient if the same reference/dereference principles could apply here?
我希望我不要错过太明显的东西.谢谢!
I hope that I am not missing something too apparent. Thanks!
推荐答案
" Intro ++ to Go Interfaces "说明了此问题:
* Vertex
是一种类型.这是指向Vertex
的指针"类型.它是与(非指针)Vertex
不同的类型.关于它是指针的部分是其类型的一部分.
*Vertex
is a type. It’s the "pointer to aVertex
" type. It’s a distinct type from (non-pointer)Vertex
. The part about it being a pointer is part of its type.
您需要类型的一致性.
" Go中的方法,接口和嵌入式类型":
确定接口符合性的规则基于这些方法的接收者以及如何进行接口调用.
规范中的规则是有关编译器如何确定我们类型的值或指针是否实现接口的规则:
- 相应指针类型
* T
的方法集是具有接收者* T
或T
的所有方法的集合
- The method set of the corresponding pointer type
*T
is the set of all methods with receiver*T
orT
- 任何其他类型
T
的方法集由所有接收方类型为T
的方法组成. - The method set of any other type
T
consists of all methods with receiver typeT
.
此规则说明,如果我们用来调用特定接口方法的接口变量包含一个指针,则具有基于值和指针的接收器的方法将满足该接口.
This rule is stating that if the interface variable we are using to call a particular interface method contains a pointer, then methods with receivers based on both values and pointers will satisfy the interface.
该规则说明,如果我们用来调用特定接口方法的接口变量包含一个值,那么只有具有基于值的接收者的方法才可以满足该接口.
This rule is stating that if the interface variable we are using to call a particular interface method contains a value, then only methods with receivers based on values will satisfy the interface.
Karrot Kake 的方法集 的6309> answer 详细也在 go Wiki 中:
接口类型的方法集是其接口.
The method set of an interface type is its interface.
接口中存储的具体值不可寻址,就像 map
元素不可寻址一样.
因此,当您在接口上调用方法时,该方法必须具有相同的接收器类型,或者必须与具体类型可以直接区分.
The concrete value stored in an interface is not addressable, in the same way that a map
element is not addressable.
Therefore, when you call a method on an interface, it must either have an identical receiver type or it must be directly discernible from the concrete type.
可以按照预期使用指针和值分别调用指针和值接收器方法.
可以使用指针值调用值接收器方法,因为它们可以先被取消引用.
不能使用值调用指针-接收器方法,因为存储在接口中的值没有地址.
Pointer- and value-receiver methods can be called with pointers and values respectively, as you would expect.
Value-receiver methods can be called with pointer values because they can be dereferenced first.
Pointer-receiver methods cannot be called with values, however, because the value stored inside an interface has no address.
(没有地址"实际上意味着它是不可寻址)
("has no address" means actually that it is not addressable)
这篇关于为什么我不能将类型的值分配给实现带有接收者类型指针的方法的接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!