The context is relevant here:
However, the type system of Go is so complex; programmers need to know
all the details about the implementation of standard types, before
they can use them correctly. For example, it is efficient ...
The author is saying that maps and channels look like values but act like pointers when they are copied.
For other datatypes, the parameter has a *
in it, which is a clear signal it could be modified in place. Often the argument has a &
in front as well, which is another signal that the argument is being modified.
When passing maps and channels, those syntactic signals are not there. That leads to unexpected results like this one:
http://play.golang.org/p/lS1FXZnxb8
A similar criticism could be applied to the big difference between arrays like [256]byte
and slices like []byte
, where the absence of a size is the only signal of different copying behavior.
All of this being aside, the author incorrectly equates copying and inefficiency. It is true that copying sometimes requires more CPU cycles or memory accesses than passing a pointer. However, that is not always the case. It depends on the size of the structure and optimizations performed by the compiler.
The decision to copy, i.e. pass a value, vs. pass a pointer is also about whether the argument might be modified by the function.
For small structures and arrays which are not intended to be modified by the function, pass them by value. This eliminates an entire class of bugs caused by accidental modifications in place, and is even better than const
as used in other languages, because there is no way to cheat and get around it. Of course, always be careful with embedded pointers, including maps and slices, because those may still be modified inside the function.