复制或传递指针
Copying or passing the pointer
我在 getters 和 setter 中看到了使用以下内容的建议,即在设置值时传递指针以更改原始数据,但在获取值时不需要.
在getter的情况下,没有指针,值被复制。我的问题是,复制对象以从中获取价值不是很低效吗,我们不能也使用指针吗?
type Foo struct {
Body string
}
func (foo Foo) GetBody() interface{} {
return foo.Body
}
func (foo * Foo) SetBody(body string) {
foo.Body = body
}
您在哪里看到关于使用非指针接收器作为 getter 的建议?我不认为这是在官方包中完成的;例如,zip package 肯定对 getter 和 setter 使用指针接收器。
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)
另见:
在使用结构时(如上例),尽可能使用指针。我没有看到将结构作为指针传递有任何错误,尤其是当您不修改其值时。有些情况下你不想对你的结构进行突变以确保你没有修改任何东西,你不会将它作为值传递,但是在执行只读时它更倾向于在这种情况下使用指针;)
你读过 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.
我在 getters 和 setter 中看到了使用以下内容的建议,即在设置值时传递指针以更改原始数据,但在获取值时不需要.
在getter的情况下,没有指针,值被复制。我的问题是,复制对象以从中获取价值不是很低效吗,我们不能也使用指针吗?
type Foo struct {
Body string
}
func (foo Foo) GetBody() interface{} {
return foo.Body
}
func (foo * Foo) SetBody(body string) {
foo.Body = body
}
您在哪里看到关于使用非指针接收器作为 getter 的建议?我不认为这是在官方包中完成的;例如,zip package 肯定对 getter 和 setter 使用指针接收器。
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)
另见:
在使用结构时(如上例),尽可能使用指针。我没有看到将结构作为指针传递有任何错误,尤其是当您不修改其值时。有些情况下你不想对你的结构进行突变以确保你没有修改任何东西,你不会将它作为值传递,但是在执行只读时它更倾向于在这种情况下使用指针;)
你读过 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.