Pointer and Value semantics in the definition of the method recipient

Creating new data types is an important part of the work of every programmer. In most languages, a type definition consists of a description of its fields and methods. In Golang, in addition to this, you need to decide which recipient semantics for methods of the new type to use: value (value) or pointer (pointer). At first glance, this decision may seem secondary, because in most cases the program will work with any semantics of the recipient. Therefore, many people miss this point and write the code, and have not figured it out to the end, which is affected by the semantics of the method recipient. And to figure it out, you need to go a little deeper into how Golang works.



Consider a small example. Define a cat structure with one Name field and sayHello (person string) method. Hereinafter, by a method I will refer to a function associated with a particular type, an object to a variable that has methods, and the recipient of the method will be the variable indicated in parentheses after the word func in the method description.



type cat struct { Name string } func (c *cat) sayHello(person string) { fmt.Println(fmt.Sprintf("Meow, meow, %s!", person) }
      
      





If we define a pointer to cat and request the Name field from it, then, obviously, we will get an error, since the field is called from nil :



 var c *cat // c=nil fmt.Println(c.Name) //panic: runtime error: invalid memory address or nil pointer dereference
      
      





https://play.golang.org/p/L3FnRJXKqs0



However, when the sayHello () method is called on the same variable, there will be no error:



 var c *cat // c=nil c.sayHello(“Human”) //Meow, meow, Human!
      
      





https://play.golang.org/p/EMoFgKL1HEi



Why can nil call a method in this example, and how is this explained in terms of the architecture of the language itself? This becomes possible because the method in Go is syntactic sugar, or, in other words, a wrapper around a function that has a receiver as one of its arguments. When the c.sayHello (“Human”) method is called, the (* cat) .sayHello (c, s) construct ( https://play.golang.org/p/X9leJeIvxcA ) will actually be called. By calling the nil method from the example above, we practically call the function with nil in the arguments, and this is already quite a normal situation. Therefore, in Go nil, it is the correct recipient for methods.



Since the method receiver is actually an argument, the recommendations for using the semantics “value” or “pointer” for the method receiver are similar to the recommendations for function arguments. They, in turn, are inferred from Go's basic rule: arguments are always passed to the function by value . This means that the transfer of any argument to the function occurs through its copying: if the function accepts a structure as an input, then a full copy of this structure will come inside it; if it takes a pointer to an object, then a new variable will come with a pointer to the same object. This can be seen by comparing the variable address before passing it to the function with the address of the argument inside the function ( https://play.golang.org/p/oc2ssC_Irs8 , https://play.golang.org/p/FeQa2HUdX0a ).



When link passing is used:





When using value transfer:





When you need to think about the semantics of the recipient:





What is the result



In Go Value, semantics means copying a value; pointer semantics means giving access to a value. This applies both to the arguments of the methods and to their recipients. For built-in types, such as numbers, lines, slices, maps, channels, and small structures, you almost always need to use value-based transfer. For structures that occupy a large amount of memory, and structures whose state can be indirectly changed by their methods, you need to use the transfer by reference. Also, the semantics of the recipient may depend on the domain that the type describes, the semantics returned in its factory, and the semantics of the recipient already used in other methods of this type.



All Articles