When is it a good idea to return a pointer to a structure?

I study and I'm a little confused when to use pointers. In particular, when returning a struct function from a function, when is it advisable to return the instance of the structure itself and when is it advisable to return a pointer to the structure?

Code example:

 type Car struct { make string model string } func Whatever() { var car Car car := Car{"honda", "civic"} // ... return car } 

What are the situations where I want to return a pointer and where I do not want? Is there a good rule of thumb?

+7
source share
3 answers

There are two things you want to keep in mind, performance and the API.

How is a car used? Is it an object that has a state? Is this a big structure? Unfortunately, it is impossible to answer when I have no idea what a car is. In truth, the best way is to see what others are doing and copy. In the end, you feel that way. Now I will describe three examples from the standard library and explain why I think they used what they did.

  • hash/crc32 : The crc32.NewIEEE() function returns a pointer type (in fact, an interface, but the base type is a pointer). The hash instance has a state. When you write information to a hash, it sums the data, so when you call the Sum() method, it will give you the state of this single instance.

  • time : the time.Date function returns a time structure. What for? Time is time. He has no condition. This is like an integer in which you can compare them, prefix math on them, etc. The API designer decided that changing the time would not change the current one, but make a new one. As a library user, if I want time in a month, I need a new time object so as not to change the current one that I have. Time is also only 3 words. In other words, it is small and there will be no increase in performance when using the pointer.

  • math/big : big.NewInt () is interesting. We may well agree that when you change big.Int you often need a new one. A big.Int has no internal state, so why is it a pointer? The answer is simply performance. Programmers realized that big ints ... are big. Constant distribution every time you do a math operation can be impractical. So they decided to use pointers and let the programmer decide when to allocate new space.

Do I answer your question? Probably no. This is a design decision, and you need to understand each case. I use the standard library as a guide when I design my own libraries. It really all comes down to judgment and how do you expect client code to use your types.

+12
source

Often, when you want to simulate an object-oriented style, where you have an “object” that stores state and “methods” that can modify the object, then you will have a “constructor” function that returns a pointer to (think about it as an "object reference", as in other OO languages). Mutator methods would have to be pointer-to-structure methods instead of the structure type itself in order to change the fields of the object, so it’s convenient to have a pointer to the structure instead of the structure of the value itself, so that all the methods will be installed in its method.

For example, to reproduce something like this in Java:

 class Car { String make; String model; public Car(String myMake) { make = myMake; } public setMake(String newMake) { make = myMake; } } 

In Go, you'll often see something like this:

 type Car struct { make string model string } func NewCar(myMake string) *Car { return &Car{myMake, ""} } func (self *Car) setMake(newMake string) { self.make = newMake } 
+2
source

Very slightly, exceptions may occur in certain circumstances:

  • Returns a value when it is really small (no more than a few words).
  • Returns a pointer when copying overhead can significantly affect performance (size is a lot of words).
+1
source

All Articles