使用指针和值接收器构造类型的实例

时间:2018-10-06 08:07:40

标签: go struct interface

让我们举一个非常小的例子,它具有一个在struct内部修改值的函数:

package learn

type Point struct {
    x int
    y int
}

func (p *Point) Set(x int, y int) {
    p.x = x
    p.y = y
}

这正常工作,例如这样使用:

package main

import (
    "NewPattern/learn"
    "fmt"
)

func main() {
    p := learn.Point{}
    p.Set(5, 6)
    fmt.Print(p)
}

它输出期望值:{5,6}

现在让我们说我不希望用户拥有构造函数,我可以通过添加以下函数来更改代码:

func NewPoint(x int, y int) Point {
    return Point{x, y}
}

然后我可以像这样在main中使用

func main() {
    p := learn.NewPoint(3, 8)
    fmt.Print(p)
    p.Set(5, 6)
    fmt.Print(p)
}

,它按预期返回{3 8}{5 6}

现在,我们想防止在不调用构造函数的情况下创建点-此处并非如此,但对于复杂的类却有意义-因此我们避免导出Point而是创建一个接口,因此我将代码重构如下: (这不起作用!)

package learn

type point struct {
    x int
    y int
}

type Point interface {
    Set(x int, y int)
}

func (p *point) Set(x int, y int) {
    p.x = x
    p.y = y
}

func NewPoint(x int, y int) Point {
    return point{x, y} //error here
}

这说:

cannot use point literal (type point) as type Point in return argument:
    point does not implement Point (Set method has pointer receiver)

我可以通过修改以下方法来“修复”此问题:

func NewPoint(x int, y int) point {
    return point{x, y}
}

但是这只是移动了main中的错误,其重构方式如下:

func main() {
    var p learn.Point
    p = learn.NewPoint(3, 8) //error here!
    fmt.Print(p)
    p.Set(5, 6)
    fmt.Print(p)
}

,错误是:

cannot use learn.NewPoint(3, 8) (type learn.point) as type learn.Point in assignment:
    learn.point does not implement learn.Point (Set method has pointer receiver)

通过谷歌搜索,我设法以这种方式解决:

func NewPoint(x int, y int) *point {
    return &point{x, y}
}

但是作为主要结果,我们得到了:&{3 8}&{5 6}作为印刷品,广告以及我也没有真正了解幕后发生的事情。

我想这与事物的传递有某种联系,也许是通过价值“归还”了,是这样吗?但是我不知道第一个没有界面的例子是如何工作的。能否请有人澄清这些我认为对理解Go必不可少的细节。

1 个答案:

答案 0 :(得分:2)

point*point(即指向指针的指针)是两种不同的类型。在您的代码中,接口Point是通过*point类型实现的。您可以将构造函数实现为:

func NewPoint(x int, y int) Point {
    return &point{x, y} 
}

打印将显示&,因为基础值是一个指针。