在 Go 中,将接收器变量命名为“自我"是误导还是良好实践? [英] In Go is naming the receiver variable 'self' misleading or good practice?

查看:26
本文介绍了在 Go 中,将接收器变量命名为“自我"是误导还是良好实践?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看过相当多的博客 &Go 上的视频,据我所知,在编写方法时,没有一个作者使用self"或this"作为接收器变量.然而,似乎有很多关于堆栈溢出的问题会这样做,这让我开始思考这是否会误导将变量命名为self"?

I have seen a fair amount of blogs & videos on Go and as far as I recall, none of the authors use 'self' or 'this' for the receiver variable when writing methods. However there seems to be a number of questions on stack overflow that do this, and it got me thinking about if this is misleading to name the variable 'self'?

阅读方法集的规范并没有提供任何证据(在我的解释中).

Reading the Spec for Method Sets does not provide any evidence either way (in my interpretation).

我似乎记得在某个地方发现它不是真正的自我指针,任何人都可以列出证据或以任何方式提供推理,如果将其视为自我"可能会出现任何问题/陷阱?

I seem to recall finding somewhere that it was not really a self pointer, can anyone list evidence or provide reasoning either way, and if any problems/traps that might occur from thinking of it as 'self'?

一个简单的例子:

type MyStruct struct {
    Name string
} 

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

Which method is more appropriate, or both?

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

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

推荐答案

除了其他人所说的(特别是 PeterSOdskinner——在他对彼得回答的评论中),注意几个重要的事情:

In addition to what others said (especially PeterSO and dskinner—in his comment to the Peter's answer), note several important things:

在 Go 中,您可以调用任何方法函数,而不是作为接收器上的方法,而是作为常规函数调用 - 只需使用定义为方法的类型的名称限定其名称并显式传递给它一个接收器参数(从一个方法中获取一个简单的函数被称为使用方法表达式).

In Go, you can call any method function not as a method on a receiver but rather as a regular function—simply by qualifying its name with the name of the type it's defined to be a method on and explicitly passing it a receiver argument (obtaining a simple function from a method is called using a method expression).

演示:

package main

import "fmt"

type Foo int

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

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

(游乐场链接.)

运行时,这个程序打印:

When run, this program prints:

My receiver is 46
My receiver is 51

正如你所看到的,self 在这里失去了它的神圣意义,因为你刚刚调用了一个方法人工为其构建上下文,这与很多引用调用对象的方法是将消息传递给该对象"概念.

As you can see, self loses its sacred meaning here because you've just called a method artificially constructing the context for it which has nothing to do with the much cited "calling an object's method is passing a message to that object" concept.

总结一下,在 Go 中,方法只是一个在语义上绑定到特定类型的函数,它接收一个额外的参数——它的接收者——不管它是如何调用的.与许多其他主流语言相反,Go 并没有把这个事实隐藏在地毯下.

To recap, in Go, a method is just a function semantically bound to a particular type which receives a single extra argument—its receiver—no matter how it's called. Contrary to many other mainstream languages, Go does not hide this fact under the carpet.

如我的示例所示,我在非指针接收器上定义了一个方法 Bar(),如果您尝试为接收器分配一个值,该方法将成功但不会影响调用者,因为接收者——就像 Go 中的一切一样——已经通过值传递(所以整数刚刚被复制).

As demonstrated in my example, I've defined a method, Bar(), on a non-pointer receiver, and if you'll try to assign a value to the receiver that will succeed but won't affect the caller because the receiver—as everything in Go—has been passed by value (so that integer has just been copied).

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

To be able to mutate the receiver's value in the method, you'd have to define it on an appropriately-typed pointer, like

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

再次,您可以看到使用 self 表示我"、我的内部"在这里变得没有意义:在我的示例中,该方法仅接收一个它知道类型的值.您可以看到这与许多 OO 语言形成对比,在这些语言中,对象是通常通过引用传递的黑盒.在 Go 中,您几乎可以在任何东西上定义一个方法(包括其他方法,由net/http 标准包,顺便说一句)它侵蚀了方法是用于对象的";概念.

Again, you can see that using self meaning "me", "my internals" becomes moot here: in my example the method merely received a value which type it knows. You can see this is in contrast with many OO-languages in which an object is a black box usually passed around by reference. In Go, you can define a method on virtually anything (including other methods, which is used by the net/http standard package, by the way) which erodes that "methods are for objects" concept.

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

In Go, methods are a convenient way to group functionality around particular types, and different sets of methods might be applicable to the same value in different points of the program flow. Combined with interfaces and duck-typing they provide, this concept really flourishes. The idea is that in Go, there's an idiom of defining "support" types which perform certain operation on values of some other type.

一个很好的例子是标准包sort:对于例如,它提供了 IntSlice 类型,它允许你对一个整数切片进行排序——一个 []int 类型的值.要做到这一点,您将切片类型转换为 sort.IntSlice 并且作为结果获得的值有一整套用于对切片进行排序的方法,而值的内部表示没有改变了——因为 sort.IntSlice定义为 typeIntSlice []int.在那个 IntSlice 类型的每个方法中,很难将它们的接收者值的含义与 self 协调起来——仅仅是因为该类型的存在只是为了为另一种类型提供一组方法;在哲学意义上,这种效用类型没有自我"的概念.;-)

A good example of this is the standard package sort: for instance, it provides the type IntSlice which allows you to sort a slice of integers—a value of type []int. To do that you type-convert your slice to sort.IntSlice and the value you get as a result has a whole set of methods for sorting your slice while the internal representation of your value has not changed— because sort.IntSlice is defined as type IntSlice []int. In each method of that IntSlice type, it's hard to reconcile the meaning of their receiver value with self—simply because the type solely exists to provide a set of methods for another type; in a philosophical sense, such utility types have no concept of "self" ;-)

所以我想说的是,保持头脑简单,不要试图超载"Go 所采用的清晰简单的方法及其语义并未明确说明它提供的内容.

So I'd say, keep things simple in your head and do not try to "overload" the clear and simple approach taken by Go with semantics it does not explicitly state it provides.

还有一个注意事项.在我学习围棋的习语时,我个人对围棋成语的看法是围棋最重要的属性是它的实用性(与理想主义等相反)所以如果你看到一些感觉"的概念不自然地尝试弄清楚为什么它是这样设计的,而且大多数情况下,您会发现为什么如此点击"这个概念.在你的大脑中,变得自然.(我必须承认,要通过理解 Go 中的方法来解决这个特殊问题,熟悉 C 会大有帮助.)

One more note. My personal perception of Go's idioms as I learned them is that the paramount property of Go is its practicality (as opposed to idealism etc) so if you see some concept which "feels" unnatural try to work out why it's designed that way, and most often you'll discover why so the concept "clicks" in your brain and gets natural. (I must admit that to grok this particular problem with understanding methods in Go, a good working familiarity with C would be of much help.)

这篇关于在 Go 中,将接收器变量命名为“自我"是误导还是良好实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆