我在Go上看到了相当多的博客和视频,据我回忆,在编写方法时,没有一个作者使用‘self’或‘this’作为接收器变量.然而,堆栈溢出上似乎有很多问题会这样做,这让我思考,将变量命名为"self"是否具有误导性?

阅读Method Sets的规格并不能提供任何证据(在我的解释中).

我似乎记得在某个地方发现它并不是一个真正的self 指针,有没有人能列出证据或以任何一种方式提供推理,如果认为它是"self "可能会出现任何问题/trap ?

下面是一个快速示例:

type MyStruct struct {
    Name string
} 

哪种方法更合适,还是两者兼而有之?

func (m *MyStruct) MyMethod() err或 {
    // do something useful
}

func (self *MyStruct) MyMethod() err或 {
    // do something useful
}

推荐答案

除了其他人所说的话(尤其是他对彼得回答的 comments 中的PeterSOdskinner),请注意以下几点:

您可以像调用简单函数一样调用方法

在Go中,您可以调用any方法函数,而不是作为接收器上的方法,而是作为常规函数-只需使用定义为方法的类型的名称限定其名称,然后explicitly将其传递给接收器参数(从方法获取简单函数将被调用 使用method expression).

要演示,请执行以下操作:

package main

import "fmt"

type Foo int

func (f Foo) Bar() {
    fmt.Printf("My receiver is %v\n", f)
}

func main() {
    a := Foo(46)
    a.Bar()
    b := Foo(51)
    Foo.Bar(b)
}

(Playground link.)

运行时,此程序打印:

My receiver is 46
My receiver is 51

正如您所看到的,self在这里失go 了它的神圣意义,因为您刚刚调用了一个为其构造上下文的方法artificially,该方法与经常引用的"调用对象的方法就是向该对象传递消息"的概念没有任何关系.

总而言之,在Go中,方法只是一个语义上绑定到特定类型的函数,它从接收方接收一个额外的参数,无论如何调用它.与许多其他主流语言相反,围棋并没有掩盖这一事实.

A receiver is not necessarily mutable inside a method defined on its type

如我的示例所示,我已经在一个非指针接收器上定义了一个方法Bar(),如果您try 将一个值赋给接收器,该值将会成功,但不会影响调用者,因为接收器-就像GO中的所有东西-都是通过值传递的(所以刚刚复制了整数).

为了能够在方法中改变接收器的值,您必须在适当类型的指针上定义它,如

func (f *Foo) Bar() {
    // here you can mutate the value via *f, like
    *f = 73
}

同样,您可以看到,使用self表示"我","我的内部 struct "在这里变得毫无意义:在我的示例中,该方法只接收了它所知道的类型的值.您可以看到,这与许多面向对象语言形成对比,在这些语言中,对象是一个黑盒,通常通过引用传递.在Go中,您可以在几乎任何东西(顺便说一句,net/http标准包使用的是including other methods)上定义一个方法,这会削弱"方法是用于对象"的概念.

不同的方法集可能在不同的时间适用于相同的值

在GO中,方法是围绕特定类型对功能进行分组的便捷方式,不同的方法集可能适用于程序流的不同点中的相同值.与它们提供的接口和鸭子类型相结合,这个概念真正蓬勃发展.其 idea 是,在GO中,有一种习惯用法定义"支持"类型,这些类型对其他类型的值执行特定操作.

standard package sort就是一个很好的例子:例如,它提供了类型IntSlice,允许您对一片整数进行排序-一个类型为[]int的值.要做到这一点,您可以键入-将您的切片转换为sort.IntSlice,结果是您获得的值有一套完整的方法来对您的切片进行排序,而the internal representation of your value has not changed-因为sort.IntSlicedefined as type IntSlice []int.在IntSlice种类型中每种方法中,很难使它们的接收器值的含义与self一致-简单地说,因为该类型的存在仅仅是为了为另一种类型提供一组方法;在哲学意义上,这样的效用类型没有"self "的概念;-)

结论

所以我想说,在你的头脑中保持事情的简单,不要试图"过载"Go所采取的清晰而简单的方法,因为Go没有explicitly声明它提供的语义.

再加一个音符.我个人对围棋习语的看法是,围棋最重要的属性是它的实用性(而不是理想主义等等),所以如果你看到一些"感觉"不自然的概念,试着把它设计成这样,大多数时候你会发现为什么这个概念会在你的大脑中"点击",变得自然.(我必须承认,要理解围棋中的方法来理解这个特殊的问题,熟悉C的工作会很有帮助.)

Go相关问答推荐

如何在gocql中设置gocqlSYS标志?

Go-Colly:将数据切片为POST请求

AWS S3 SelectObjectContent在AWS SDK v2 for Go中不返回结果

golang.org/x/oauth2 oauth2.Config.Endpoint.TokenURL mock:缺少access_token

ChromeDriver不存在(高朗selenium)

在不耗尽资源的情况下处理S3文件下载

将类型定义为泛型类型实例化

在Golang中Mergesort的递归/并行实现中出现死锁

理解Golang中的IOTA和常量

go grpc:无法导入github.com/golang/protobuf/proto(没有所需的模块提供包github.com/gorang/protobuf-proto)

如何以干净的方式在中间件中注入 repo 或服务?

golang:解组动态 YAML 注释

使用 unsafe.Pointer 将 struct point直接转换为另一个 struct 是否安全?

Gorm delete with clauses sqlmock 测试

Golang泛型在用作 map 元素时不起作用

从 Go struct 中提取标签作为 reflect.Value

如何正确判断 io.Reader 是否为零?

带有 grpc 的 protobuf 用于拆分包中的 Go

Golang 'defer' 导致发送(接收)API 响应延迟

处理程序中的无限循环