Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

pointers

go

I'm learning Go, and I'm a little confused about when to use pointers. Specifically, when returning a struct from a function, when is it appropriate to return the struct instance itself, and when is it appropriate to return a pointer to the struct?

Example code:

type Car struct {
  make string
  model string
}

func Whatever() {
  var car Car

  car := Car{"honda", "civic"}

  // ...

  return car
}

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

like image 583
Carson Avatar asked Jun 11 '12 20:06

Carson


People also ask

When would you use a pointer to a struct?

Pointer to structure holds the add of the entire structure. It is used to create complex data structures such as linked lists, trees, graphs and so on. The members of the structure can be accessed using a special operator called as an arrow operator ( -> ).

Should I return a struct or a pointer to a struct?

As explained in a better answer, it depends on the size of the struct. Small ones can be easily "copied" into and out of the stack without the pointer argument, while larger ones, besides requiring more stack room, could require more "work" to pop them out.

Can you return a pointer to a struct in C?

There are two ways of "returning a structure." You can return a copy of the data, or you can return a reference (pointer) to it.

Should I use a pointer instead of a copy of my struct?

For many Go developers, the systematic use of pointers to share structs instead of the copy itself seems the best option in terms of performance.


1 Answers

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

How is a Car used? Is it an object which has state? Is it a large struct? Unfortunately, it is impossible to answer when I have no idea what a Car is. Truthfully, the best way is to see what others do and copy them. Eventually, you get a feeling for this sort of thing. I will now describe three examples from the standard library and explain why I think they used what they did.

  1. hash/crc32: The crc32.NewIEEE() function returns a pointer type (actually, an interface, but the underlying type is a pointer). An instance of a hash function has state. As you write information to a hash, it sums up the data so when you call the Sum() method, it will give you the state of that one instance.

  2. time: The time.Date function returns a Time struct. Why? A time is a time. It has no state. It is like an integer where you can compare them, preform maths on them, etc. The API designer decided that a modification to a time would not change the current one but make a new one. As a user of the library, if I want the time one month from now, I would want a new time object, not to change the current one I have. A time is also only 3 words in length. In other words, it is small and there would be no performance gain in using a pointer.

  3. math/big: big.NewInt() is an interesting one. We can pretty much agree that when you modify a big.Int, you will often want a new one. A big.Int has no internal state, so why is it a pointer? The answer is simply performance. The programmers realized that big ints are … big. Constantly allocating each time you do a mathematical operation may not be practical. So, they decided to use pointers and allow the programmer to decide when to allocate new space.

Have I answered your question? Probably not. It is a design decision and you need to figure it out on a case by case basis. I use the standard library as a guide when I am designing my own libraries. It really all comes down to judgement and how you expect client code to use your types.

like image 98
Stephen Weinberg Avatar answered Nov 09 '22 10:11

Stephen Weinberg