Pointer address of a struct - go

Consider this code :
package main
import "fmt"
type S struct {
Val int
}
func main() {
e1 := S{Val: 1}
fmt.Printf("%p\n", &e1)
fmt.Printf("%p\n", &e1.Val)
}
After running it, we'll get something like that:
0xc00001c030
0xc00001c030
What confuses me is why pointer's address of the struct and it's member are the same?
Link to Go Playground: https://go.dev/play/p/Wl4tnD9TFmA

Struct is memory area with all fields put there one by one (if alignment present, then they could be with gaps). Same as array. So first element of struct obviously should have same address as struct itself.

Related

golang struct creation return different memory addresses

I'm having trouble understanding why golang returns a different memory address on what appears to be the same struct (maybe it's not, perhaps it copies with the same values to another memory address?).
Here's the code
package main
import (
"fmt"
)
type Creature struct {
Name string
isAlive bool
}
func foo() Creature {
myCreature := Creature{Name: "dino", isAlive: true}
fmt.Printf("%p\n", &myCreature)
fmt.Println(myCreature)
return myCreature
}
func main() {
myCreat := foo()
fmt.Printf("%p\n", &myCreat)
fmt.Println(myCreat)
}
The output of the code is the following
0xc000004090
{dino true}
0xc000004078
{dino true}
As you can see, the memory addresses are different. Why?
Should I instead return a memory address?
I'm having trouble understanding why golang returns a different memory address on what appears to be the same struct (maybe it's not, perhaps it copies with the same values to another memory address?).
You didn't return a memory address, you returned a struct.
As you can see, the memory addresses are different.
Because you returned a struct and it was copied to a new one.
Why? Should I instead return a memory address?
Yes, if you want a pointer then return that.
package main
import (
"fmt"
)
type Creature struct {
Name string
isAlive bool
}
func foo() *Creature {
myCreature := Creature{Name: "dino", isAlive: true}
fmt.Printf("%p\n", &myCreature)
fmt.Println(myCreature)
return &myCreature
}
func main() {
myCreat := foo()
fmt.Printf("%p\n", myCreat)
fmt.Println(*myCreat)
}
Playground
The rule in Go is that you only use pointers when you actually need them, when you have to modify a struct's values or something. You should not use pointers because you think it might be more efficient. The memory optimiser can do its work more efficiently if you don't force it to do things one way or another.
See https://medium.com/#vCabbage/go-are-pointers-a-performance-optimization-a95840d3ef85, https://betterprogramming.pub/why-you-should-avoid-pointers-in-go-36724365a2a7, and many more articles.

Pointer newbie - Correct me

I am still learning go and need a hand to clear my head.
Following program output Power value as 1 in each Println. I was expecting 1 as first output and 2 as second output.
My assumption was the Change func overwrite the address of s with anew address and this change will reflect back to the caller (main func). In such case, the original address would be pointing to newly created address when it call the second Println.
My assumption is wrong but I can't figure out why.
package main
import (
"fmt"
)
type Pod struct{
Power int
}
func main() {
pod := &Pod{1}
fmt.Println(pod.Power)
Change(pod)
fmt.Println(pod.Power)
}
func Change(s *Pod) {
s = &Pod{2}
}
Code
To explore further on what happens under cover, I did tried to print addresses this time and it looks like below;
import (
"fmt"
)
type Pod struct{
Power int
}
func main() {
pod := &Pod{ 1}
fmt.Println(&pod) //0xc04202c020
Change(pod)
fmt.Println(&pod) //0xc04202c020
}
func Change(s *Pod) {
fmt.Println(&s) //0xc04202c030 ( I was expecting 0xc04202c020 here)
s = &Pod{ 2}
fmt.Println(&s) //0xc04202c030
}
It's because when you pass arguments to functions etc, they are always passed by value.
In other words, even though you are accepting a pointer in the function parameter, the address of the struct will be copied.
Then when you assign to s to try and change the address it only changes that local copy, not the one outside the function.
To change the address from within the function you would need to pass in a pointer pointer, then assign to the dereferenced s, for example:
package main
import (
"fmt"
)
type Pod struct {
Power int
}
func main() {
pod := &Pod{1}
fmt.Println(pod.Power)
Change(&pod)
fmt.Println(pod.Power)
}
func Change(s **Pod) {
*s = &Pod{2}
}
In this case a copy of an address is still being passed into the function, but because it's a pointer to a pointer it means that when you dereference s as *s you will get the address of the struct outside of the function. This means if you assign to *s you can change the address of the pointer outside the function.
Of course, like Andy Schweig says, you probably wouldn't really want to do that though, and would probably just change individual fields as needed with the normal pointer version of the function.
package main
import (
"fmt"
)
type Pod struct {
Power int
}
func main() {
pod := &Pod{1}
fmt.Println(pod.Power)
Change(pod)
fmt.Println(pod.Power)
}
func Change(s *Pod) {
s.Power = 2
}
This works because when you type s.Power = 2 Go will actually do something like (*s).Power = 2 for you. So it automatically dereferences s for you which gives you the actual Pod struct to work with.
You can't do *s = &Pod{2} in this normal pointer example because in that case *s will actually equal type Pod, not *Pod.
Because of that if you want to use the &Pod{2} syntax to assign an address you need to pass a pointer to the pointer. In the case of s **Pod the dereferenced *s will point to the address of the Pod instead of the actual Pod, so *s will be of type *Pod which allows you to assign &Pod{2}.
Having said all of that, a **Pod is only required if you want to assign an address with the &Pod{2} syntax.
If you don't need to use the &Pod{2} syntax you can just dereference s and assign with a normal Pod{2}.
package main
import (
"fmt"
)
type Pod struct {
Power int
}
func main() {
pod := &Pod{1}
fmt.Println(pod.Power)
Change(pod)
fmt.Println(pod.Power)
}
func Change(s *Pod) {
*s = Pod{2}
}
This also works, because now s is a copy of an address, and when you dereference you get to the value outside the function which is type Pod, not *Pod.
That means you can just assign to it by removing the &.
Basically if you use & it means you want to assign an address rather than the actual value.
I hope this explanation isn't too confusing. I explained using a **Pod because I thought you wanted to use the &Pod{2} syntax rather than Pod{2}, but if that's not the case then my s.Power = 2 or *s = Pod{2} examples may make more sense.
Changing the value of a parameter to a function inside the function never has an effect on the parameter passed by the caller. All parameters are passed by value. If you want to change the value of Power inside the object pointed to by s (pod in the caller), use s.Power = 2. If you actually want to set the pointer variable in the caller to a different Pod object, you need to declare the parameter to Change as s **pos, change the assignment in the function to *s = &Pod{2}, and call Change(&pod). That's probably not what you want to do, though.

Golang Non-Struct Type Pointer Receiver

I created a custom type based on the Golang net.IP type. What surprised me is that a method declared with a pointer receiver to my custom type can't modify the value to which the receiver points.
The u variable in this code snippet remains nil after calling u.defaultIP(). The IP can be modified if I changed my custom type to a struct with an IP field and the method is defined with a pointer receiver to the struct. What am I missing? Executable example can be found here.
type userIP net.IP
func main() {
var u *userIP
u.defaultIP()
fmt.Printf("%v\n", u)
}
func (u *userIP) defaultIP() {
defaultIP := userIP("127.0.0.1")
u = &defaultIP
}
You need to dereference the u before setting it's value.
From your example, change
defaultIP := userIP("127.0.0.1")
u = &defaultIP
to
*u = userIP("127.0.0.1")
For your example updated and working: https://play.golang.org/p/ycCLT0ed9F
TL;DR: The pointer receiver needs to be dereferenced before it's value can be set. This applies to both struct and non-struct types. In the case of struct types, the dereferencing is automatically done by the selector expression.
After digging around a bit further, I think this behaviour is caused by the fact that the pointer receiver is not the same pointer calling the method.
Running this code snippet shows that the u pointer in the main() function is different from that in the defaultIP() method. Essentially, I end up only modifying the u pointer in the defaultIP() method. Executable example can be found here.
func main() {
var u *userIP
u.defaultIP()
fmt.Printf("main(): address of pointer is %v\n", &u)
fmt.Printf("main(): user IP address is %v\n", u)
}
type userIP net.IP
func (u *userIP) defaultIP() {
defaultIP := userIP("127.0.0.1")
u = &defaultIP
fmt.Printf("defaultIP(): address of pointer is %v\n", &u)
fmt.Printf("defaultIP(): user IP address is %s\n", *u)
}
The correct way to do this is as pointed in Tom's answer i.e. dereference u in the defaultIP() method.
What puzzled me earlier was why would this example work if I wrapped the IP as a field in the struct? Running the code snippet shows that the two u pointers are indeed different, but the ip field is modified. Executable example can be found here.
func main() {
u := &userInfo{}
u.defaultIP()
fmt.Printf("main(): address of pointer is %v\n", &u)
fmt.Printf("main(): user IP address is %s\n", u.ip)
}
type userInfo struct{
ip net.IP
}
func (u *userInfo) defaultIP() {
u.ip = net.ParseIP("127.0.0.1")
fmt.Printf("defaultIP(): address of pointer is %v\n", &u)
fmt.Printf("defaultIP(): user IP address is %s\n", u.ip)
}
Turns out that this is caused by the selector expression (x.y). To quote the doc,
Selectors automatically dereference pointers to structs. If x is a pointer to a struct, x.y is shorthand for (x).y; if the field y is also a pointer to a struct, x.y.z is shorthand for ((*x).y).z, and so on. If x contains an anonymous field of type *A, where A is also a struct type, x.f is a shortcut for (*x.A).f.
So in my case, the u.ip expression dereferences u before modifying the ip field, which essentially translates to(*u).ip.
Two Options:
1- With dereferencing: like this working code and using net.ParseIP("127.0.0.1")
(The Go Playground):
package main
import (
"fmt"
"net"
)
type userIP net.IP
func main() {
var u userIP
u.defaultIP()
fmt.Println(u)
}
func (u *userIP) defaultIP() {
*u = userIP(net.ParseIP("127.0.0.1"))
}
output:
[0 0 0 0 0 0 0 0 0 0 255 255 127 0 0 1]
2- Without dereferencing (The Go Playground):
package main
import (
"fmt"
"net"
)
type userIP net.IP
func main() {
u := make(userIP, 4)
u.defaultIP()
fmt.Printf("%v\n", u)
}
func (u userIP) defaultIP() {
u[0], u[1], u[2], u[3] = 127, 0, 0, 1
}
And note that net.IP is []byte, see net.IP Docs:
An IP is a single IP address, a slice of bytes. Functions in this
package accept either 4-byte (IPv4) or 16-byte (IPv6) slices as input.

What's the difference between new(Struct) and &Struct{} in Go?

They seem to be the same:
package main
import "fmt"
type S struct {
i int
}
func main() {
var s1 *S = new(S)
fmt.Println(s1)
var s2 *S = &S{}
fmt.Println(s2) // Prints the same thing.
}
Update:
Hm. I just realized that there's no obvious way to initialize S.i using new. Is there a way to do that? new(S{i:1}) does not seem to work :/
From Effective Go:
As a limiting case, if a composite literal contains no fields at all, it creates a zero value for the type. The expressions new(File) and &File{} are equivalent.
Not only do they give the same resulting value, but if we allocate something both ways and look at their values...
// Adapted from http://tour.golang.org/#30
package main
import "fmt"
type Vertex struct {
X, Y int
}
func main() {
v := &Vertex{}
v2 := new(Vertex)
fmt.Printf("%p %p", v, v2)
}
...we'll see that they are in fact allocated in consecutive memory slots. Typical output: 0x10328100 0x10328108. I'm not sure if this is an implementation detail or part of the specification, but it does demonstrate that they're both being allocated from the same pool.
Play around with the code here.
As for initializing with new, according to the language spec: The built-in function new takes a type T and returns a value of type *T. The memory [pointed to] is initialized as described in the section on initial values. Because functions in go can't be overloaded, and this isn't a variadic function, there's no way to pass in any initialization data. Instead, go will initialize it with whatever version of 0 makes sense for the type and any member fields, as appropriate.
Case 1: package main
import (
"fmt"
)
type Drink struct {
Name string
Flavour string
}
func main() {
a := new(Drink)
a.Name = "Maaza"
a.Flavour = "Mango"
b := a
fmt.Println(&a)
fmt.Println(&b)
b.Name = "Frooti"
fmt.Println(a.Name)
}//This will output Frooti for a.Name, even though the addresses for a and b are different.
Case 2:
package main
import (
"fmt"
)
type Drink struct {
Name string
Flavour string
}
func main() {
a := Drink{
Name: "Maaza",
Flavour: "Mango",
}
b := a
fmt.Println(&a)
fmt.Println(&b)
b.Name = "Froti"
fmt.Println(a.Name)
}//This will output Maaza for a.Name. To get Frooti in this case assign b:=&a.

Using reflect, how do you set the value of a struct field?

having a rough time working with struct fields using reflect package. in particular, have not figured out how to set the field value.
type t struct { fi int; fs string }
var r t = t{ 123, "jblow" }
var i64 int64 = 456
getting Name of field i - this seems to work
var field = reflect.TypeOf(r).Field(i).Name
getting value of field i as a) interface{}, b) int - this seems to work
var iface interface{} = reflect.ValueOf(r).Field(i).Interface()
var i int = int(reflect.ValueOf(r).Field(i).Int())
setting value of field i - try one - panic
reflect.ValueOf(r).Field(i).SetInt( i64 )
panic: reflect.Value·SetInt using value obtained using unexported field
assuming it did not like field names "id" and "name", so renamed to "Id" and "Name"
a) is this assumption correct?
b) if correct, thought not necessary since in same file / package
setting value of field i - try two (with field names capitalized ) - panic
reflect.ValueOf(r).Field(i).SetInt( 465 )
reflect.ValueOf(r).Field(i).SetInt( i64 )
panic: reflect.Value·SetInt using unaddressable value
Instructions below by #peterSO are thorough and high quality
Four. this works:
reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )
he documents as well that the field names must be exportable (begin with capital letter)
The Go json package marshals and unmarshals JSON from and to Go structures.
Here's a step-by-step example which sets the value of a struct field while carefully avoiding errors.
The Go reflect package has a CanAddr function.
func (v Value) CanAddr() bool
CanAddr returns true if the value's
address can be obtained with Addr.
Such values are called addressable. A
value is addressable if it is an
element of a slice, an element of an
addressable array, a field of an
addressable struct, or the result of
dereferencing a pointer. If CanAddr
returns false, calling Addr will
panic.
The Go reflect package has a CanSet function, which, if true, implies that CanAddr is also true.
func (v Value) CanSet() bool
CanSet returns true if the value of v
can be changed. A Value can be changed
only if it is addressable and was not
obtained by the use of unexported
struct fields. If CanSet returns
false, calling Set or any
type-specific setter (e.g., SetBool,
SetInt64) will panic.
We need to make sure we can Set the struct field. For example,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
// N at start
fmt.Println(n.N)
// pointer to struct - addressable
ps := reflect.ValueOf(&n)
// struct
s := ps.Elem()
if s.Kind() == reflect.Struct {
// exported field
f := s.FieldByName("N")
if f.IsValid() {
// A Value can be changed only if it is
// addressable and was not obtained by
// the use of unexported struct fields.
if f.CanSet() {
// change value of N
if f.Kind() == reflect.Int {
x := int64(7)
if !f.OverflowInt(x) {
f.SetInt(x)
}
}
}
}
}
// N at end
fmt.Println(n.N)
}
Output:
42
7
If we can be certain that all the error checks are unnecessary, the example simplifies to,
package main
import (
"fmt"
"reflect"
)
func main() {
type t struct {
N int
}
var n = t{42}
fmt.Println(n.N)
reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7)
fmt.Println(n.N)
}
BTW, Go is available as open source code. A good way to learn about reflection is to see how the core Go developers use it. For example, the Go fmt and json packages. The package documentation has links to the source code files under the heading Package files.
This seems to work:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
Number int
Text string
}
func main() {
foo := Foo{123, "Hello"}
fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
reflect.ValueOf(&foo).Elem().Field(0).SetInt(321)
fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
}
Prints:
123
321

Resources