微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

即使结构指针未实现接口,为什么我们仍可以将结构指针分配给接口变量? 程序1 程序2

如何解决即使结构指针未实现接口,为什么我们仍可以将结构指针分配给接口变量? 程序1 程序2

我在下面介绍了两个程序:程序1和程序2。

我希望程序1无法编译,并且确实无法编译。这样很好。

我希望程序2无法编译,但可以成功!这个问题是关于程序2成功的原因。

程序1

https://play.golang.org/p/qX9nY8VLlx0

package main

import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

type Vertex struct {
    X float64
    Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
    var a Abser
    
    a = Vertex{3,4}
    fmt.Println(a.Abs())
}

无法通过此错误进行编译:

./prog.go:24:4: cannot use Vertex literal (type Vertex) as type Abser in assignment:
Vertex does not implement Abser (Abs method has pointer receiver)

我之所以会遇到此错误,是因为*Vertex实现了Abser,但Vertex没有实现,因此我们无法将Vertex对象分配给Abser变量。 / p>

程序2

https://play.golang.org/p/4bIs-fHGhYm

package main

import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

type Vertex struct {
    X float64
    Y float64
}

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
    var a Abser
    
    a = &Vertex{3,4}
    fmt.Println(a.Abs())
}

这将成功编译。该程序的输出为:

5

为什么成功?在这里Vertex实现了Abser,但是*Vertex没有实现Abser。然后如何为*Vertex分配类型为Abser的值?

要知道为什么成功,我需要了解哪些语言语义规则?

解决方法

assignability要求阐明了使用接口时的要求:

值x可分配给类型T的变量(“ x可分配给 T“)如果满足以下条件之一:

... T是接口类型,x实现T。 ...

要确定“ x实现T”的规则,我们转向method sets的概念:

类型可能具有与之关联的方法集。一个方法集 接口类型是它的接口。任何其他类型T的方法集 包含以接收方类型T声明的所有方法。

乍看之下,这意味着第一个示例中的Vertex方法集为空,而第二个示例中的*Vertex方法集也为空。

但是,规范会继续指定:

相应指针类型* T的方法集为所有 用接收者* T或T声明的方法(也就是说,它还包含 T的方法集。

这意味着{strong>方法集*Vertex自动包含Vertex的方法集,但反之则不包括。

这在您的第一个示例中无济于事,但是在第二个示例中,Vertex的方法集确实包含Abs() float64。由于这是实现Abser接口所需的全部内容,因此*Vertex被认为是实现Abser的地方。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。