golang: return a pointer or pass a reference - go

What is the best way to "build" an object.
Leme write some code:
type Car struct {
Wheels int
Doors int
}
This cars are stored somewhere, somehow. So should my interface be the type of
func (s Store) GetCar() *Car
or should I make it
func (s Store) GetCar(*Car)
and pass a reference to a variable?
Im looking for some sort of rule of thumb.
Thanks!

Go manages the heap/stack, keeping track when the reference goes outside of scope. So, you can return the pointer without any worries.
func (s *Store) GetCar() *Car {
return &Car{Store: s}
}

In many cases this is preferable
func (s Store) GetCar() *Car
because it is more convenient and readable, but has consequences. All variables such as Car are created inside the function which means they are placed onto stack. After function return this memory of stack is marked as invalid and can be used again. It a bit differs for pointer values such as *Car. Because pointer is virtually means you want to share the value with other scope and return an address, the value has to be stored somewhere in order to be available for calling function. It is copied onto heap memory and stays there until garbage collection finds no references to it.
It implies overheads:
copying values from stack to heap
additional work for garbage collection
The overheads is not significant if the value is relatively small. This is a reason why we have to pass an argument in io.Reader and io.Writer rather than have the value in return.
If you'd like to dive yourself into guts follow the links:
Language Mechanics On Stacks And Pointers
and
Bad Go: pointer returns

The most common way to do that would be to write it as:
func (s Store) GetCar() *Car
Or, if you don't want to use pointers, you can do it like:
func (s Store) GetCar() Car
The other alternative, making it GetCar(aCar *Car) might work, but it will not be as clear since it's not obvious that aCar should be sent empty and then populated by the function.

Create them on heap from beginning by new.

Related

Stringer method requires value

The Go FAQ answers a question regarding the choice of by-value vs. by-pointer receiver definition in methods. One of the statements in that answer is:
If some of the methods of the type must have pointer receivers, the rest should too, so the method set is consistent regardless of how the type is used.
This implies that if I have for a data type a few methods that mutate the data, thus require by-pointer receiver, I should use by-pointer receiver for all the methods defined for that data type.
On the other hand, the "fmt" package invokes the String() method as defined in the Stringer interface by value. If one defines the String() method with a receiver by-pointer it would not be invoked when the associated data type is given as a parameter to fmt.Println (or other fmt formatting methods). This leaves one no choice but to implement the String() method with a receiver by value.
How can one be consistent with the choice of by-value vs. by-pointer, as the FAQ suggests, while fulfilling fmt requirements for the Stringer interface?
EDIT:
In order to emphasize the essence of the problem I mention, consider a case where one has a data type with a set of methods defined with receiver by-value (including String()). Then one wishes to add an additional method that mutates that data type - so he defines it with receiver by-pointer, and (in order to be consistent, per FAQ answer) he also updates all the other methods of that data type to use by-pointer receiver. This change has zero impact on any code that uses the methods of this data type - BUT for invocations of fmt formatting functions (that now require passing a pointer to a variable instead of its value, as before the change). So consistency requirements are only problematic in the context of fmt. The need to adjust the manner one provides a variable to fmt.Println (or similar function) based on the receiver type breaks the capability to easily refactor one's package.
If you define your methods with pointer receiver, then you should use and pass pointer values and not non-pointer values. Doing so the passed value does indeed implement Stringer, and the fmt package will have no problem "detecting" and calling your String() method.
Example:
type Person struct {
Name string
}
func (p *Person) String() string {
return fmt.Sprintf("Person[%s]", p.Name)
}
func main() {
p := &Person{Name: "Bob"}
fmt.Println(p)
}
Output (try it on the Go Playground):
Person[Bob]
If you would pass a value of type Person to fmt.Println() instead of a pointer of type *Person, yes, indeed the Person.String() would not be called. But if all methods of Person has pointer receiver, that's a strong indication that you should use the type and its values as pointers (unless you don't intend its methods to be used).
Yes, you have to know whether you have to use Person or *Person. Deal with it. If you want to write correct and efficient programs, you have to know a lot more than just whether to use pointer or non-pointer values, I don't know why this is a big deal for you. Look it up if you don't know, and if you're lazy, use a pointer as the method set of (the type of) a pointer value contains methods with both pointer and non-pointer receiver.
Also the author of Person may provide you a NewPerson() factory function which you can rely on to return the value of the correct type (e.g. Person if methods have value receivers, and *Person if the methods have pointer receivers), and so you won't have to know which to use.
Answer to later adding a method with pointer receiver to a type which previously only had methods with value receiver:
Yes, as you described in the question, that might not break existing code, yet continuing to use a non-pointer value may not profit from the later added method with pointer receiver.
We might ask: is this a problem? When the type was used, the new method you just added didn't exist. So the original code made no assumption about its existence. So it shouldn't be a problem.
Second consideration: the type only had methods with value receiver, so one could easily assume that by their use, the value was immutable as methods with value receiver cannot alter the value. Code that used the type may have built on this, assuming it was not changed by its methods, so using it from multiple goroutines may have omitted certain synchronization rightfully.
So I do think that adding a new method with pointer receiver to a type that previously only had methods with value receiver should not be "opaque", the person who adds this new method has the responsibility to either modify uses of this type to "switch" to pointers and make sure the code remains safe and correct, or deal with the fact that non-pointer values will not have this new method.
Tips:
If there's a chance that a type may have mutator methods in the future, you should start creating it with methods with pointer receivers. Doing so you avoid later having to go through the process described above.
Another tip could be to hide the type entirely, and only publish interfaces. Doing so, the users of this type don't have to know whether the interface wraps a pointer or not, it just doesn't matter. They receive an interface value, and they call methods of the interface. It's the responsibility of the package author to take care of proper method receivers, and return the appropriate type that implements the interface. The clients don't see this and they don't depend on this. All they see and use is the interface.
In order to emphasize the essence of the problem I mention, consider a case where one has a data type with a set of methods defined with receiver by-value (including String()). Then one wishes to add an additional method that mutates that data type - so he defines it with receiver by-pointer, and (in order to be consistent, per FAQ answer) he also updates all the other methods of that data type to use by-pointer receiver. This change has zero impact on any code that uses the methods of this data type - BUT for invocations of fmt formatting functions (that now require passing a pointer to a variable instead of its value, as before the change).
This is not true. All interface of it and some of type assertions will be affected as well - that is why fmt is affected. e.g. :
package main
import (
"fmt"
)
type I interface {
String() string
}
func (t t) String() string { return "" }
func (p *p) String() string { return "" }
type t struct{}
type p struct{}
func S(i I) {}
func main() {
fmt.Println("Hello, playground")
T := t{}
P := p{}
_ = P
S(T)
//S(P) //fail
}
To understand this from the root, you should know that a pointer method and a value method is different from the very base. However, for convenience, like the omit of ;, golang compiler looks for cases using pointer methods without a pointer and change it back.
As explained here: https://tour.golang.org/methods/6
So back to the orignal question: consistency of pointer methods. If you read the faq more carefully, you will find it is the very last part of considering to use a value or pointer methods. And you can find counter-example in standard lib examples, in container/heap :
// A PriorityQueue implements heap.Interface and holds Items.
type PriorityQueue []*Item
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
// We want Pop to give us the highest, not lowest, priority so we use greater than here.
return pq[i].priority > pq[j].priority
}
func (pq PriorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
pq[i].index = i
pq[j].index = j
}
func (pq *PriorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
item.index = -1 // for safety
*pq = old[0 : n-1]
return item
}
// update modifies the priority and value of an Item in the queue.
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
item.value = value
item.priority = priority
heap.Fix(pq, item.index)
}
So, indeed, as the FAQ say, to determine whether to use a pointer methods, take the following consideration in order:
Does the method need to modify the receiver? If yes, use a pointer. If not, there should be a good reason or it makes confusion.
Efficiency. If the receiver is large, a big struct for instance, it will be much cheaper to use a pointer receiver. However, efficiency is not easy to discuss. If you think it is an issue, profile and/or benchmark it before doint so.
Consistency. If some of the methods of the type must have pointer receivers, the rest should too, so the method set is consistent regardless of how the type is used. This, to me, means that if the type shall be used as a pointer (e.g., frequent modify), it should use the method set to mark so. It does not mean one type can only have solely pointer methods or the other way around.
The previous answers here do not address the underlying issue, although the answer from leaf bebop is solid advice.
Given a value, you can in fact invoke either pointer or value receiver methods on it, the compiler will do that for you. However, that does not apply when invoking via interface implementations.
This boils down to this dicussion about interface implementations.
In that discussion the discussion is about implementing interfaces with nil pointers. But the underlying discussion revolves around the same issue: when implementing an interface you must choose the pointer or the value type, and there will be no attempt by the compiler, nor can there be any attempt in golang code, to figure out exactly what type it is, and adjust the interface call accordingly.
So for example, when calling
fmt.Println(object)
you are implementing the arg of type interface{} with object of type X. The fmt code within has no interest in knowing whether the type of object is a pointer type or not. It will not even be able to tell without using reflection. It will simply call String() on whatever type that is.
So if you supplied a value of type X, and there just so happens to be a (*X) String() string method, that does not matter, that method will not be called, it will only type-assert whether that type X implements Stringer, it has no interest if type *X asserts Stringer. Since there is no (X) String() string method, it will move on. It will not attempt to check what X may happen to be, whether it's a pointer type, and if not, whether the associated pointer type implements Stringer, and call that String() method instead.
So this is not really a pointer vs value methods issue, this is an interface implementation issue when implementing interface{} in calls to fmt methods.

Can I Use the Address of a returned value? [duplicate]

What's the cleanest way to handle a case such as this:
func a() string {
/* doesn't matter */
}
b *string = &a()
This generates the error:
cannot take the address of a()
My understanding is that Go automatically promotes a local variable to the heap if its address is taken. Here it's clear that the address of the return value is to be taken. What's an idiomatic way to handle this?
The address operator returns a pointer to something having a "home", e.g. a variable. The value of the expression in your code is "homeless". if you really need a *string, you'll have to do it in 2 steps:
tmp := a(); b := &tmp
Note that while there are completely valid use cases for *string, many times it's a mistake to use them. In Go string is a value type, but a cheap one to pass around (a pointer and an int). String's value is immutable, changing a *string changes where the "home" points to, not the string value, so in most cases *string is not needed at all.
See the relevant section of the Go language spec. & can only be used on:
Something that is addressable: variable, pointer indirection, slice indexing operation, field selector of an addressable struct, array indexing operation of an addressable array; OR
A composite literal
What you have is neither of those, so it doesn't work.
I'm not even sure what it would mean even if you could do it. Taking the address of the result of a function call? Usually, you pass a pointer of something to someone because you want them to be able to assign to the thing pointed to, and see the changes in the original variable. But the result of a function call is temporary; nobody else "sees" it unless you assign it to something first.
If the purpose of creating the pointer is to create something with a dynamic lifetime, similar to new() or taking the address of a composite literal, then you can assign the result of the function call to a variable and take the address of that.
In the end you are proposing that Go should allow you to take the address of any expression, for example:
i,j := 1,2
var p *int = &(i+j)
println(*p)
The current Go compiler prints the error: cannot take the address of i + j
In my opinion, allowing the programmer to take the address of any expression:
Doesn't seem to be very useful (that is: it seems to have very small probability of occurrence in actual Go programs).
It would complicate the compiler and the language spec.
It seems counterproductive to complicate the compiler and the spec for little gain.
I recently was tied up in knots about something similar.
First talking about strings in your example is a distraction, use a struct instead, re-writing it to something like:
func a() MyStruct {
/* doesn't matter */
}
var b *MyStruct = &a()
This won't compile because you can't take the address of a(). So do this:
func a() MyStruct {
/* doesn't matter */
}
tmpA := a()
var b *MyStruct = &tmpA
This will compile, but you've returned a MyStruct on the stack, allocated sufficient space on the heap to store a MyStruct, then copied the contents from the stack to the heap. If you want to avoid this, then write it like this:
func a2() *MyStruct {
/* doesn't matter as long as MyStruct is created on the heap (e.g. use 'new') */
}
var a *MyStruct = a2()
Copying is normally inexpensive, but those structs might be big. Even worse when you want to modify the struct and have it 'stick' you can't be copying then modifying the copies.
Anyway, it gets all the more fun when you're using a return type of interface{}. The interface{} can be the struct or a pointer to a struct. The same copying issue comes up.
You can't get the reference of the result directly when assigning to a new variable, but you have idiomatic way to do this without the use of a temporary variable (it's useless) by simply pre-declaring your "b" pointer - this is the real step you missed:
func a() string {
return "doesn't matter"
}
b := new(string) // b is a pointer to a blank string (the "zeroed" value)
*b = a() // b is now a pointer to the result of `a()`
*b is used to dereference the pointer and directly access the memory area which hold your data (on the heap, of course).
Play with the code: https://play.golang.org/p/VDhycPwRjK9
Yeah, it can be annoying when APIs require the use of *string inputs even though you’ll often want to pass literal strings to them.
For this I make a very tiny function:
// Return pointer version of string
func p(s string) *string {
return &s
}
and then instead of trying to call foo("hi") and getting the dreaded cannot use "hi" (type string) as type *string in argument to foo, I just wrap the argument in a call to to p():
foo(p("hi"))
a() doesn't point to a variable as it is on the stack. You can't point to the stack (why would you ?).
You can do that if you want
va := a()
b := &va
But what your really want to achieve is somewhat unclear.
At the time of writing this, none of the answers really explain the rationale for why this is the case.
Consider the following:
func main() {
m := map[int]int{}
val := 1
m[0] = val
v := &m[0] // won't compile, but let's assume it does
delete(m, 0)
fmt.Println(v)
}
If this code snippet actually compiled, what would v point to!? It's a dangling pointer since the underlying object has been deleted.
Given this, it seems like a reasonable restriction to disallow addressing temporaries
guess you need help from More effective Cpp ;-)
Temp obj and rvalue
“True temporary objects in C++ are invisible - they don't appear in your source code. They arise whenever a non-heap object is created but not named. Such unnamed objects usually arise in one of two situations: when implicit type conversions are applied to make function calls succeed and when functions return objects.”
And from Primer Plus
lvalue is a data object that can be referenced by address through user (named object). Non-lvalues include literal constants (aside from the quoted strings, which are represented by their addresses), expressions with multiple terms, such as (a + b).
In Go lang, string literal will be converted into StrucType object, which will be a non-addressable temp struct object. In this case, string literal cannot be referenced by address in Go.
Well, the last but not the least, one exception in go, you can take the address of the composite literal. OMG, what a mess.

map[T]struct{} and map[T]bool in golang

What's the difference? Is map[T]bool optimized to map[T]struct{}? Which is the best practice in Go?
Perhaps the best reason to use map[T]struct{} is that you don't have to answer the question "what does it mean if the value is false"?
From "The Go Programming Language":
The struct type with no fields is called the empty struct, written
struct{}. It has size zero and carries no information but may be
useful nonetheless. Some Go programmers use it instead of bool as the
value type of a map that represents a set, to emphasize that only the
keys are significant, but the space saving is marginal and the syntax
more cumbersome, so we generally avoid it.
If you use bool testing for presence in the "set" is slightly nicer since you can just say:
if mySet["something"] {
/* .. */
}
Difference is in memory requirements. Under the bonnet empty struct is not a pointer but a special value to save memory.
An empty struct is a struct type like any other. All the properties you are used to with normal structs apply equally to the empty struct. You can declare an array of structs{}s, but they of course consume no storage.
var x [100]struct{}
fmt.Println(unsafe.Sizeof(x)) // prints 0
If empty structs hold no data, it is not possible to determine if two struct{} values are different.
Considering the above statements it means that we may use them as method receivers.
type S struct{}
func (s *S) addr() { fmt.Printf("%p\n", s) }
func main() {
var a, b S
a.addr() // 0x1beeb0
b.addr() // 0x1beeb0
}

Go heap.Interface as a struct

I'm creating a priority queue using Go's heap package. There is an example of one in the documentation.
The queue I'm creating needs to be based around a struct rather than a slice because it requires other properties like a mutex.
type PQueue struct {
queue []*Item
sync.Mutex
}
I implement all the methods that heap.Interface requires.
The issue is that my PQueue.Push method seems not to be permanently adding a value to PQueue.queue.
func (p PQueue) Push(x interface{}) {
p.Lock()
defer p.Unlock()
item := x.(*Item)
item.place = len(p.queue) // the index of an item in the queue
p.queue = append(p.queue, item)
// len(p.queue) does increase
// after the functions exits, the queues length has not increased
}
If I print the length of p.queue at the end of this function, the length has increased. After the functions exits however, it seems the original struct does not get updated.
I think it might be happening because of func (p PQueue) not being a pointer. Why might that be? Is there a way to fix it? If I were to use func (p *PQeueue) Push(x interface{}) instead, I would need to implement my own heap because heap.Interface specifically requires no pointer. Is that my only option?
The problem is that you are appending to a copy of your slice. Thus the change shows within the function, but is lost once you return from the function.
In this blog article from the section Passing slices to functions:
It's important to understand that even though a slice contains a
pointer, it is itself a value. Under the covers, it is a struct value
holding a pointer and a length. It is not a pointer to a struct.
With append you are modifying the slice header. And
Thus if we want to write a function that modifies the header, we must
return it as a result parameter
Or:
Another way to have a function modify the slice header is to pass a
pointer to it.
As a result you need to pass a pointer if you want to modify it with append. Simply change the method to use a pointer receiver. And for that to work you need to call init with a pointer like heap.Init(&pq) as shown in the example that you linked to which does just that and also uses pointer receivers.
From the spec on Method Sets:
The method set of the corresponding pointer type *T is the set of all methods
declared with receiver *T or T (that is, it also contains the method
set of T).
So using a pointer type will work with value and pointer receivers and still implement the interface.
You are right about the problem being related to the receiver of your Push method: the method will receive a copy of the PQueue, so any changes made to the struct will not persist.
Changing the method to use a pointer as a receiver is the correct change, but this also means that PQueue no longer implements heap.Interface. This is due to the fact that Go does not let you take a pointer to the value stored inside an interface variable, so the automatic translation of q.Push() to (&q).Push() does not occur.
This isn't a dead end though, since *PQueue should still implement the heap.Interface. So if you were previously calling heap.Init(q), just change it to heap.Init(&q).
I think it might be happening because of func (p PQueue) not being a pointer
That's right. Quoting Effective Go:
invoking [the method] on a value would cause the method to receive a
copy of the value, so any modifications would be discarded.
You say:
heap.Interface specifically requires no pointer
I'm confused, the example you point to is, in fact, using a pointer:
func (pq *PriorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
Maybe something else is going on?

Does assigning value to interface copy anything?

I've been trying to wrap my head around the concept of interfaces in Go. Reading this and this helped a lot.
The only thing that makes me uncomfortable is the syntax. Have a look at the example below:
package main
import "fmt"
type Interface interface {
String() string
}
type Implementation int
func (v Implementation) String() string {
return fmt.Sprintf("Hello %d", v)
}
func main() {
var i Interface
impl := Implementation(42)
i = impl
fmt.Println(i.String())
}
My issue is with i = impl. Based on the fact that an interface instance actually holds a pointer reference to the actual data, it would feel more natural for me to do i = &impl. Usually assignment of non-pointer when not using & will make a full memory copy of the data, but when assigning to interfaces this seem to side-step this and instead simply (behind the scenes) assign the pointer to the interface value. Am I right? That is, the data for the int(42) will not be copied in memory?
The data for int(42) will be copied. Try this code:
func main() {
var i Interface
impl := Implementation(42)
i = impl
fmt.Println(i.String())
impl = Implementation(91)
fmt.Println(i.String())
}
(Playground link)
You'll find that the second i.String() still shows 42. Perhaps one of the trickier aspects of Go is that method receivers can be pointers as well.
func (v *Implementation) String() string {
return fmt.Sprintf("Hello %d", *v)
}
// ...
i = &impl
Is what you want if you want the interface to hold a pointer to the original value of impl. "Under the hood" an interface is a struct that either holds a pointer to some data, or the data itself (and some type metadata that we can ignore for our purposes). The data itself is stored if its size is less than or equal to one machine word -- whether it be a pointer, struct, or other value.
Otherwise it will be a pointer to some data, but here's the tricky part: if the type implementing the interface is a struct the pointer will be to a copy of the struct, not the struct assigned to the interface variable itself. Or at least semantically the user can think of it as such, optimizations may allow the value to not be copied until the two diverge (e.g. until you call String or reassign impl).
In short: assigning to an interface can semantically be thought of as a copy of the data that implements the interface. If this is a pointer to a type, it copies the pointer, if it's a big struct, it copies the big struct. The particulars of interfaces using pointers under the hood are for reasons of garbage collection and making sure the stack expands by predictable amounts. As far as the developer is concerned, they should be thought of as semantic copies of the specific instance of the implementing type assigned.

Resources