The difference between go pointer receiver and value receiver
There are two main differences between pointer receivers and value receivers:
- In Go, function parameters are passed by values, so the pointer receiver passes the pointer copy of the receiver, and the value receiver passes the receiver's copy--in the method, the pointer receiver's variable will be modified, while the value receiver's member variable modification is invalid (after all, the incoming copy is a copy, and the modified naturally is also the copy's member variable).
- In interface implementation, if the value receiver implements a certain method, it is equivalent to both the value receiver and the pointer receiver implementing this method. Otherwise, it doesn't work, that is, the pointer receiver has implemented a certain method, and cannot be regarded as a value receiver to implement this method.
Note that point 2 only affects the implementation of the interface. If the interface is not involved, it will not be subject to this rule.
A mnemonic but not very correct view: the receiver is a pointer-type method, and it is likely that in the method, the receiver's attributes will be changed, thereby affecting the receiver; while in the method, the receiver is a value-type method, there will be no impact on the receiver itself.
Understanding angle: The pointer receiver can choose to modify its own value and not modify it. It is invalid for the value receiver to modify its own value (because it is a copy). Therefore, it can be regarded as the ability of the pointer receiver > the ability of the value receiver. Naturally: the pointer receiver implements a certain method, it can be regarded as the value receiver implements a certain method, otherwise it will not work.
package main import "fmt" type coder interface { code() debug() } type Gopher struct { language string } func (p Gopher) code() { ("I am coding %s language\n", ) } func (p *Gopher) debug() { ("I am debuging %s language\n", ) } func main() { var c coder = &Gopher{"Go"} //It works normally //The previous line is replaced by: var c coder = Gopher{"Go"} // An error is reported. Gopher does not implement coder (debug method has pointer receiver) () () }
Note 📢: For 👆🏻Additional point 2 above: Although the implicit implementation methods are different, if the interface is not involved, simply when calling, whether the pointer receiver or the value receiver implements a certain method, the pointer receiver and the value receiver can call it. Essentially the syntactic sugar of go.
Best Practices:
If a type has "primitive essence", that is, its members are all primitive types built into the Go language, such as strings, integer values, etc., then the method of defining the value receiver type.
Built-in reference types, such as slice, map, interface, channel, these types are quite special. When declaring them, a header is actually created, which is also a method to directly define the value receiver type. In this way, when calling a function, these types of headers are directly copied, and headers themselves are designed for copying.
If a type has a non-primitive nature and cannot be copied safely, this type should always be shared, then define the method of the pointer receiver.
Although this is said above, I personally feel that in actual use, you can basically use pointer receivers without any brains. The main reasons are: 1. The huge overhead brought by the pointer receiver without a value copy. 2. If you want to modify the value in the function, you must use the pointer receiver. 3. The only advantage of the value receiver is to prevent unexpected modifications. To prevent this, you can manually copy it by creating a function or method, and this does not bring much overhead.
Distinguishing easily wrong points
Whether to change the value of a structure depends on whether the method is the pointer receiver or the value receiver, rather than whether the caller is the pointer or the value. The reason is that the golang compiler will do some work behind the scenes, such as: dereferences, implicitly use references. The code example is as follows:
package main import "fmt" type Node struct { val int } func (receiver Node) changeVal1() { ++ } func (receiver *Node) changeVal2() { ++ } func main() { someOne := Node{} someOne.changeVal1() ("%d\n", ) //0, indicating that the value has not been changed, because the method receiver is the value receiver someOnePtr := &Node{} someOnePtr.changeVal1() ("%d\n", ) //0, indicating that the value has not been changed, because the method receiver is the value receiver, and it has nothing to do with whether the caller points or not. someTwo := Node{} someTwo.changeVal2() ("%d\n", ) //1, indicating that the value is changed successfully, because the method receiver is the pointer receiver, and it has nothing to do with whether the caller is pointer or not. someTwoPtr := &Node{} someTwoPtr.changeVal2() ("%d\n", ) //1, indicating that the value is changed successfully, because the method receiver is the pointer receiver, and it has nothing to do with whether the caller is pointer or not. }
refer to:/go-questions/interface/receiver/
This is the end of this article about the difference between go pointer receiver and value receiver. For more related go pointer receiver and value receiver content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!