go: using pointer allows changing the contents of a struct. Why? - pointers

Consider the following example. I don't fully understand what happens "in the background" and seek an explanation. This version seems to make a copy of the struct Foo when I call AddToEntry from the main function. Right? How can I "proof" this in the code?
When go makes a copy of the struct, I am just manipulating the copy of the struct and when I get back to the main function I see the original as before?
When I expect a pointer (see comment in the code), everything is fine, my struct is not copied. How can avoid this kind of "error"? How can I make sure I am not copying the struct? Is there a possible compile time/run time check for that, or do I have be careful?
package main
import (
"fmt"
)
type Foo struct {
Entry []string
}
func MakeFoo() Foo {
a:=Foo{}
a.Entry = append(a.Entry,"first")
return a
}
// if I change (f Foo) to (f *Foo), I get
// the "desired" result
func (f Foo) AddToEntry() {
f.Entry = append(f.Entry,"second")
}
func main() {
f:=MakeFoo()
fmt.Println(f) // {[first]}
f.AddToEntry()
fmt.Println(f) // {[first]}
}

Your method signature is func (f Foo) AddToEntry(). The way methods work, f.AddToEntry() is is the same as:
g := Foo.AddToEntry
g(f)
The receiver is just another parameter. Why is this important? What happens when you pass a struct and modify it in a function? In C, Go, and other pass by value languages, the struct given in the parameter is only a copy. Therefore, you can not modify the original. Only return the new struct.
When you define func (f *Foo) AddToEntry(), you are defining the receiver, the first parameter, as a pointer. Obviously, given a pointer, you can modify the original struct. What is hidden is that you are implicitly referencing when you access a struct in Go. To put it another way, (*ptrFoo).Entry is the same as ptrFoo.Entry in Go.
So the issue here is that for those unaccustomed to go, the syntax is hiding some of what is going on. In C, you would never be able to edit a struct unless you passed a pointer to it. The same happens in Go. You need to use a pointer receiver in order to modify what you are receiving.

Have you read this Go documentation?
Should I define methods on values or pointers?
Methods: Pointers vs. Values
The Go Programming Language Specification

How can I make sure I am not copying the struct? Is there a possible
compile time/run time check for that, or do I have be careful?
The short answer here is that no , you can't do a compile-time or run-time(1) check
for this - you just have to be careful. Once you get a bit familiar with go, this becomes natural.
(1)
Technically your function could query whether the type is a pointer or not with the type switch, but if you remember to do that, you'll also remember to make the parameter a pointer.

Related

When to use pointers when defining structs

Ive noticed in some libraries that when they define structs some values have pointers while others don't. I can't seem to find anywhere explaining when to use pointers and when not to.
Example
type MyStruct struct {
FieldOne *int64
FieldTwo int64
FieldFour *AnotherStruct
FieldFive AnotherStruct
}
What are the benefits of using a pointer ?
From my experience, I will try to not use pointer value in a struct because it may be root cause of panic, if we forgot to check nil before use it. Have three reason when I use a pointer value in a struct:
This field is a big struct so I think it can help to reduce copy costs (It's correct in C/C++, but in go, some case the Benchmark test showed same result).
When I need to check and do some thing if this value is nil (Because of default values in go and the cost to compare with AnotherStruct{}).
When i need "omitempty" (ignore this field if it empty) to convert fields of struct to bson or json ...
I hope 2) and 3) can help to answers for your question. If you have any better idea please share me. Because I also new on go!

If resp is a pointer to a response object, why don't we have to use resp* to access its value?

I recently began studying Golang and the accompanying documentation. In the Golang net/http documentation , the Get method is:
func Get(url string) (resp *Response, err error)
It is my understanding that this method returns a pointer to a response object or an error object (should an error occur). If resp is a pointer to a response object, why can the respvalue be accessed using the following code:
func main() {
resp, err := http.Get("http://google.com")
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
fmt.Println(resp)
}
Should it not be fmt.Println(*resp) instead? There are many other examples like this throughout the documentation. I thought I understood pointers but I am obviously missing something. Any help in clarifying this would certainly be appreciated.
If resp is a pointer to a response object, why can the [object itself] be accessed using [fmt.Println(resp)] ... Should it not be fmt.Println(*resp) instead?
If you send to fmt.Println a pointer to an object, fmt.Println can use the pointer to reach the object itself (i.e., access it—and even modify it, but fmt.Println doesn't modify it).
If you send to fmt.Println a copy of the object, fmt.Println can use the copy of the object, i.e., access it (and cannot modify the original).
So in that sense, giving fmt.Println the pointer value is strictly more powerful than passing a copy of the object, because it can modify the object. The fmt code does not use this power, but it's there in any other place that you might pass the pointer too. But as long as fmt.Println:
notices that this is a pointer, and then
follows the pointer to access the underlying object,
then fmt.Println can behave the same way on both pointer-to-object and copy-of-object.
In fact, the fmt.Print* family of functions do not quite behave the same way with pointer-to-object and copy-of-object:
package main
import (
"fmt"
)
type T struct {
Name string
Value int
}
func main() {
obj := T{Name: "bob", Value: 42}
fmt.Println(&obj, obj)
fmt.Printf("%#v %#v\n", &obj, obj)
}
When this is run (try it on the Go Playground), it prints:
&{bob 42} {bob 42}
&main.T{Name:"bob", Value:42} main.T{Name:"bob", Value:42}
That is, the default formatting, which you get with %v or fmt.Println, prints either:
{bob 42}
(copy of object) or:
&{bob 42}
(pointer to object). The alternative format obtained with %#v adds the type, so that you either get:
main.T{Name:"bob", Value:42}
(copy of object) or:
&main.T{Name:"bob", Value:42}
What we see here is that fmt.Println, which takes an interface{} value, goes through the following process:
Inspect the type of the value. Is it a pointer? If so, remember that it was a pointer. Print <nil> and do not go any further if it's a nil pointer; otherwise, obtain the object to which the pointer points.
Now that it's not a pointer: What type does the value have? If it's a struct type, print out its type name (%#v) or not (%v), prefixed with & if step 1 followed a pointer, and then the open brace and a list of the values of things inside the struct, and then a close brace to end the whole thing.
When using %#v, print the names of the fields and print the values in a format suitable for use as Go source code. Otherwise, just print the contents of strings and ints and so on.
Other pointer types do not always get the same treatment! For instance, add a int variable, set it to some value, and call fmt.Println(&i, i). Note that this time you don't get &42 42 or something like that, but rather 0x40e050 42 or something like that. Try this with fmt.Printf and %#v. So the output depends on the type and the formatting verb.
If you call functions that must modify their objects (such as the scan family in fmt), you must pass a pointer, since they need to have access to the objects to modify them.
Every function that can take values of unconstrained interface{} types (including everything in the Print* and Scan* family here) must document what they do with each actual type. If they say, as the Print* family do, that when given a pointer to a struct type, they follow the pointer (if not nil), that lets you know that you can send the pointer instead of the object.
(Some functions in some libraries are guilty of under-documenting what they do, and you have to experiment. This is not a great situation in general because the results of the experiment might be an accident of the current implementation, rather than a promised behavior that won't change in the future. This is one reason to be chary of using interface{}: it means you have to write a lot of documentation.)

Pointers sent to function

I have following code in main():
msgs, err := ch.Consume(
q.Name, // queue
//..
)
cache := ttlru.New(100, ttlru.WithTTL(5 * time.Minute)) //Cache type
//log.Println(reflect.TypeOf(msgs)) 'chan amqp.Delivery'
go func() {
//here I use `cache` and `msgs` as closures. And it works fine.
}
I decided to create separate function for instead of anonymous.
I declared it as func hitCache(cache *ttlru.Cache, msgs *chan amqp.Delivery) {
I get compile exception:
./go_server.go:61: cannot use cache (type ttlru.Cache) as type *ttlru.Cache in argument to hitCache:
*ttlru.Cache is pointer to interface, not interface
./go_server.go:61: cannot use msgs (type <-chan amqp.Delivery) as type *chan amqp.Delivery in argument to hitCache
Question: How should I pass msg and cache into the new function?
Well, if the receiving variable or a function parameter expects a value
of type *T — that is, "a pointer to T",
and you have a variable of type T, to get a pointer to it,
you have to get the address of that variable.
That's because "a pointer" is a value holding an address.
The address-taking operator in Go is &, so you need something like
hitCache(&cache, &msgs)
But note that some types have so-called "reference semantics".
That is, values of them keep references to some "hidden" data structure.
That means when you copy such values, you're copying references which all reference the same data structure.
In Go, the built-in types maps, slices and channels have reference semantics,
and hence you almost never need to pass around pointers to the values of such types (well, sometimes it can be useful but not now).
Interfaces can be thought of to have reference semantics, too (let's not for now digress into discussing this) because each value of any interface type contains two pointers.
So, in your case it's better to merely not declare the formal parameters of your function as pointers — declare them as "plain" types and be done with it.
All in all, you should definitely complete some basic resource on Go which explains these basic matters in more detail and more extensively.
You're using pointers in the function signature but not passing pointers - which is fine; as noted in the comments, there is no reason to use pointers for interface or channel values. Just change the function signature to:
hitCache(cache ttlru.Cache, msgs chan amqp.Delivery)
And it should work fine.
Pointers to interfaces are nearly never used. You may simplify things and use interfaces of pass by value.

Why is fmt.Println not consistent when printing pointers?

I'm an experienced programmer but have never before touched Go in my life.
I just started playing around with it and I found that fmt.Println() will actually print the values of pointers prefixed by &, which is neat.
However, it doesn't do this with all types. I'm pretty sure it is because the types it does not work with are primitives (or at least, Java would call them that, does Go?).
Does anyone know why this inconsistent behaviour exists in the Go fmt library? I can easily retrieve the value by using *p, but for some reason Println doesn't do this.
Example:
package main
import "fmt"
type X struct {
S string
}
func main() {
x := X{"Hello World"}
fmt.Println(&x) // &{Hello World} <-- displays the pointed-to value prefixed with &
fmt.Println(*(&x)) // {Hello World}
i := int(1)
fmt.Println(&i) // 0x10410028 <-- instead of &1 ?
fmt.Println(*(&i)) // 1
}
The "technical" answer to your question can be found here:
https://golang.org/src/fmt/print.go?#L839
As you can see, when printing pointers to Array, Slice, Struct or Map types, the special rule of printing "&" + value applies, but in all other cases the address is printed.
As for why they decided to only apply the rule for those, it seems the authors considered that for "compound" objects you'd be interested in always seeing the values (even when using a pointer), but for other simple values this was not the case.
You can see that reasoning here, where they added the rule for the Map type which was not there before:
https://github.com/golang/go/commit/a0c5adc35cbfe071786b6115d63abc7ad90578a9#diff-ebda2980233a5fb8194307ce437dd60a
I would guess this had to do with the fact that it is very common to use for example pointers to Struct to pass them around (so many times you'd just forget to de-reference the pointer when wanting to print the value), but no so common to use pointers to int or string to pass those around (so if you were printing the pointer you were probably interested in seeing the actual address).

How to return reference to locally allocated struct/object? AKA error: `foo` does not live long enough

Here's a simplified example of what I'm doing:
struct Foo ...
impl io::Read for Foo ...
fn problem<'a>() -> io::Result<&'a mut io::Read> {
// foo does not live long enough, because it gets allocated on the stack
let mut foo = Foo{ v: 42 };
Ok(&mut foo)
}
Rust playground is here.
Obviously, the problem is that foo is allocated on the stack, so if we return a reference to it, the reference outlives the object.
In C, you'd get around this by using malloc to allocate the object on the heap, and the caller would need to know to call free when appropriate. In a GCed language, this would just work since foo would stick around until there are no references to it. Rust is really clever, and kind of in-between, so I'm not sure what my options are.
I think one option would be to return a managed pointer type. Is Box the most appropriate? (I found a guide to pointers in rust, but it is way outdated.)
The reason I'm returning a reference is that in reality I need to return any of several structs which implement Read. I suppose another option would be to create an enum to wrap each of the possible structs. That would avoid heap allocation, but seems needlessly awkward.
Are there other options I haven't thought of?
Replacing the reference with a Box compiles successfully:
fn problem<'a>() -> io::Result<Box<io::Read>> {
let mut foo = Foo{ v: 42 };
Ok(Box::new(foo))
}
Can you use static type? Looks like in either C or rust, static variable lasts as long as the program does - even if it's a static local.
http://rustbyexample.com/scope/lifetime/static_lifetime.html

Resources