Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I store reference to the result of an operation in Go?

Okay it's hard to describe it in words but let's say I have a map that stores int pointers, and want to store the result of an operation as another key in my hash:

m := make(map[string]*int)

m["d"] = &(*m["x"] + *m["y"])

This doesn't work and gives me the error: cannot take the address of *m["x"] & *m["y"]

Thoughts?

like image 533
Reza S Avatar asked Dec 10 '15 08:12

Reza S


1 Answers

A pointer is a memory address. For example a variable has an address in memory.

The result of an operation like 3 + 4 does not have an address because there is no specific memory allocated for it. The result may just live in processor registers.

You have to allocate memory whose address you can put into the map. The easiest and most straightforward is to create a local variable for it.

See this example:

x, y := 1, 2
m := map[string]*int{"x": &x, "y": &y}

d := *m["x"] + *m["y"]
m["d"] = &d

fmt.Println(m["d"], *m["d"])

Output (try it on the Go Playground):

0x10438300 3

Note: If the code above is in a function, the address of the local variable (d) that we just put into the map will continue to live even if we return from the function (that is if the map is returned or created outside - e.g. a global variable). In Go it is perfectly safe to take and return the address of a local variable. The compiler will analyze the code and if the address (pointer) escapes the function, it will automatically be allocated on the heap (and not on the stack). For details see FAQ: How do I know whether a variable is allocated on the heap or the stack?

Note #2: There are other ways to create a pointer to a value (as detailed in this answer: How do I do a literal *int64 in Go?), but they are just "tricks" and are not nicer or more efficient. Using a local variable is the cleanest and recommended way.

For example this also works without creating a local variable, but it's obviously not intuitive at all:

m["d"] = &[]int{*m["x"] + *m["y"]}[0]

Output is the same. Try it on the Go Playground.

like image 170
icza Avatar answered Oct 29 '22 03:10

icza