在Golang中,通过星号引用的方法和没有引用的方法之间有什么区别?

huangapple go评论96阅读模式
英文:

what's the difference between a method referenced by an asterisk and method that isn't in Golang?

问题

假设我有一个结构体,这个结构体有两个方法。其中一个方法使用了一个星号,另一个方法没有使用。
以下是理解这个例子的代码。

type object struct{
    name string
    age int
}

func (obj *object) methodOne{
    // 做一些事情
} 
func (obj object) methodTwo{
    // 做一些事情
}

我知道指针的概念,但在这个例子中仍然不理解。

英文:

Let's suppose I have a struct, and this struct has 2 methods. one is written with an asterisk and the other one isn't.
Here is the code to understand the example.

type object struct{
    name string
    age int
}

func (obj *object) methodOne{
    // do something
} 
func (obj object) methodTwo{
    // do something
}

I know about pointers, but still didn't understand the concept in this example.

答案1

得分: 2

根据文档所说:

func (s *MyStruct) pointerMethod() { } // 指针方法
func (s MyStruct) valueMethod()   { } // 值方法

对于不习惯使用指针的程序员来说,这两个示例之间的区别可能会令人困惑,但实际情况非常简单。在为类型定义方法时,接收器(上述示例中的s)的行为就像它是方法的参数一样。因此,将接收器定义为值还是指针是同一个问题,就像函数参数应该是值还是指针一样。有几个考虑因素。

首先,最重要的是,方法是否需要修改接收器?如果需要修改,接收器必须是指针。(切片和映射作为引用,所以它们的情况稍微复杂一些,但是例如要在方法中更改切片的长度,接收器仍然必须是指针。)在上面的示例中,如果pointerMethod修改s的字段,调用者将看到这些更改,但是valueMethod是使用调用者参数的副本调用的(这就是传递值的定义),因此它所做的更改对调用者是不可见的。

其次是效率的考虑。如果接收器很大,比如一个大的结构体,使用指针接收器会更便宜。

接下来是一致性的考虑。如果类型的某些方法必须具有指针接收器,那么其余的方法也应该具有指针接收器,以便无论如何使用类型,方法集都是一致的。有关详细信息,请参阅有关方法集的部分。

对于基本类型、切片和小结构体等类型,值接收器非常便宜,因此除非方法的语义要求指针,否则值接收器是高效和清晰的。

英文:

As docs says:

func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct)  valueMethod()   { } // method on value

> For programmers unaccustomed to pointers, the distinction between
> these two examples can be confusing, but the situation is actually
> very simple. When defining a method on a type, the receiver (s in the
> above examples) behaves exactly as if it were an argument to the
> method. Whether to define the receiver as a value or as a pointer is
> the same question, then, as whether a function argument should be a
> value or a pointer. There are several considerations.
>
> First, and most important, does the method need to modify the
> receiver? If it does, the receiver must be a pointer. (Slices and maps
> act as references, so their story is a little more subtle, but for
> instance to change the length of a slice in a method the receiver must
> still be a pointer.) In the examples above, if pointerMethod modifies
> the fields of s, the caller will see those changes, but valueMethod is
> called with a copy of the caller's argument (that's the definition of
> passing a value), so changes it makes will be invisible to the caller.
>
> Second is the consideration of efficiency. If the receiver is large, a
> big struct for instance, it will be much cheaper to use a pointer
> receiver.
>
> Next is consistency. If some of the methods of the type must have
> pointer receivers, the rest should too, so the method set is
> consistent regardless of how the type is used. See the section on
> method sets for details.
>
> For types such as basic types, slices, and small structs, a value
> receiver is very cheap so unless the semantics of the method requires
> a pointer, a value receiver is efficient and clear.

huangapple
  • 本文由 发表于 2022年9月5日 16:08:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/73606307.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定