I'm exploring Go after 9 years of C++ development. In C++ it is a bad practice to pass function's arguments by value except variables of built-in types because of performance penalty: all fields of the argument will be copied and in most cases it will be a very costly operation.
Is this true for Go? It looks very expensive to pass "this" by value only to assign "const" semantic to the method. Is Go compiler smart enough to prevent variable from being copied before first modification? Why isn't passing "this" by value an anti-pattern in Go as it is in C/C++?
The other answers are good but in my opinion, there's some information missing.
Receivers in Go are just syntactic sugar, as demonstrated by the following code:
package main
import "fmt"
type Something struct {
Value int
}
func (s *Something) ChangeValue(n int) {
s.Value = n
}
func main() {
o := new(Something) // o is of type *Something
fmt.Println(o.Value) // Prints 0
o.ChangeValue(8) // Changes o.Value to 8
fmt.Println(o.Value) // Prints 8
(*Something).ChangeValue(o, 16) // Same as calling o.ChangeValue(16)
fmt.Println(o.Value) // Prints 16
}
Based on this, consider what would happen if the receiver of ChangeValue
was a value of type Something
instead of a pointer to one...
That's right! You could never actually mutate o
's Value
field through this method. Most of the time, you use pointer receivers to do encapsulation.
I would say your C++ knowledge will translate fine into Go about what is expensive as a function argument (passing structs by value) and what isn't (builtin types, eg int).
The major difference would be the reference types, slices, map
s and channel
s. These, though they appear to be passed by value (you don't need to use a pointer) are actually passed by reference, so don't in general use a pointer to a slice, map or channel.
string
s are also special - they are reference types under the hood, but they are also immutable, so pass them around directly.
As for the specific case of this
or the receiver as it is called in Go - same rules apply (note that you can have builtin types as a receiver unlike C++), and I don't think the compiler is smart enough to avoid copies, so use a pointer for large structs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With