复制或传递指针

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

Copying or passing the pointer

问题

我看到有人建议在getter和setter中使用以下方法,即在设置值时传递指针以更改原始数据,但在获取值时不需要。

在getter的情况下,如果没有指针,值会被复制。我的问题是,复制对象以获取其值是否效率低下,我们不能也使用指针吗?

type Foo struct {
     Body string
}

func (foo Foo) GetBody() interface{} {
	return foo.Body
}

func (foo *Foo) SetBody(body string) {
	foo.Body = body
}
英文:

I've seen recommendations to use the following in getters and setters, i.e. pass a pointer when you are setting the value in order to change the original data, but it's not required when getting the value.

In the case of a getter, without a pointer, the value is copied. My question is, isn't it inefficient to copy the object to get value out of it, could we not use a pointer as well?

type Foo struct {
     Body string
}

func (foo Foo) GetBody() interface{} {
	return foo.Body
}

func (foo * Foo) SetBody(body string) {
	foo.Body = body
}

答案1

得分: 2

你在哪里看到建议使用非指针接收器来获取器?我认为官方包中并没有这样做;例如,zip包明确使用指针接收器来定义获取器和设置器。

func (h *FileHeader) ModTime() time.Time
func (h *FileHeader) Mode() (mode os.FileMode)
func (h *FileHeader) SetModTime(t time.Time)
func (h *FileHeader) SetMode(mode os.FileMode)

另请参阅:

英文:

Where did you see a recommendation to use a non-pointer receiver for getters ? I don’t think this is done in the official packages; e.g., the zip package definitely uses pointer receivers for both getters and setters.

func (h *FileHeader) ModTime() time.Time
func (h *FileHeader) Mode() (mode os.FileMode)
func (h *FileHeader) SetModTime(t time.Time)
func (h *FileHeader) SetMode(mode os.FileMode)

See also :

答案2

得分: 2

你是否阅读了Go常见问题解答(FAQ)

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

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

> 顺便说一下,指针接收器与Java中的情况完全相同,尽管在Java中指针是隐藏在底层的;而Go中的值接收器则是不寻常的。

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

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

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

英文:

Did you read the Go Frequently Asked Questions (FAQ)?

> Should I define methods on values or pointers?
>
> 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.
>
> By the way, pointer receivers are identical to the situation in Java,
> although in Java the pointers are hidden under the covers; it's Go's
> value receivers that are unusual.
>
> 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.

答案3

得分: 0

在处理结构体时(就像上面的例子一样),尽可能使用指针。我认为将结构体作为指针传递没有任何问题,特别是当你不修改其值时。有些情况下,你不希望对结构体进行修改,为了确保不修改任何内容,你不会将其作为值传递,但在执行只读操作时,最好使用指针。;)

英文:

When working with struct (like the above example), use pointers whenever as possible. I don't see anything wrong passing a struct as a pointer especially when you're not modifying its value. There's cases when u don't want to do mutation on your struct so to make sure you're not modifying anything, you're not gonna pass it as a value, but when performing read only it's more prefered to use pointers in this case 复制或传递指针

huangapple
  • 本文由 发表于 2017年3月13日 02:18:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/42751274.html
匿名

发表评论

匿名网友

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

确定