douningzhi1991 2016-07-03 05:07
浏览 92
已采纳

为什么不能将类型的值分配给实现带有接收者类型指针的方法的接口?

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.

This code is running perfectly:

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())
}

The error is:

interface.go:18: cannot use myVer (type Vertex) as type Abser in assignment: Vertex does not implement Abser (Abs method has pointer receiver)

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).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!

  • 写回答

4条回答 默认 最新

  • dongmei1828 2016-07-03 06:00
    关注

    "Intro++ to Go Interfaces" illustrates the issue:

    *Vertex is a type. It’s the “pointer to a Vertex” type. It’s a distinct type from (non-pointer) Vertex. The part about it being a pointer is part of its type.

    You need consistency of type.

    "Methods, Interfaces and Embedded Types in Go":

    The rules for determining interface compliance are based on the receiver for those methods and how the interface call is being made.
    Here are the rules in the spec for how the compiler determines if the value or pointer for our type implements the interface:

    • The method set of the corresponding pointer type *T is the set of all methods with receiver *T or T

    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.

    • The method set of any other type T consists of all methods with receiver type T.

    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's answer about method set is detailed also in go wiki:

    The method set of an interface type is its interface.

    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)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 在不同的执行界面调用同一个页面
  • ¥20 基于51单片机的数字频率计
  • ¥50 M3T长焦相机如何标定以及正射影像拼接问题
  • ¥15 keepalived的虚拟VIP地址 ping -s 发包测试,只能通过1472字节以下的数据包(相关搜索:静态路由)
  • ¥20 关于#stm32#的问题:STM32串口发送问题,偶校验(even),发送5A 41 FB 20.烧录程序后发现串口助手读到的是5A 41 7B A0
  • ¥15 C++map释放不掉
  • ¥15 Mabatis查询数据
  • ¥15 想知道lingo目标函数中求和公式上标是变量情况如何求解
  • ¥15 关于E22-400T22S的LORA模块的通信问题
  • ¥15 求用二阶有源低通滤波将3khz方波转为正弦波的电路