In Go, I was confused about why the memory address for variables like int can be obtained but not for structs. As an example:
package main
import "fmt"
func main() {
stud1 := stud{"name1", "school1"}
a:=10
fmt.Println("&a is:", &a)
fmt.Println("&stud1 is:",&stud1)
}
output is:
&a is: 0x20818a220
&stud1 is: &{name1 school1}
Why is &a giving the memory address, however &stud1 not giving the exact memory location. I don't have any intention of using the memory address but just was curious about the different behavior.
the fmt package uses reflection to print out values, and there is a specific case to print a pointer to a struct as &{Field Value}.
If you want to see the memory address, use the pointer formatting verb %p.
fmt.Printf("&stud is: %p\n", &stud)
Related
I want to get the memory location address of the map in Go but it returns a concatenated ampersand and the map output.
Here is the example code:
package main
import "fmt"
var name = map[string]string{
"name": "John",
"lastname": "Doe",
}
func main() {
fmt.Println(&name)
}
what it prints is:
&map[lastname:Doe name:John]
I know that maps are copied by references and there is no need to get the address, but how could I retrieve the address?
Println will use the default format based on type, and you already saw what that default format is. You can use Printf to print the pointer:
func main() {
fmt.Printf("%p\n", &name)
}
Well, in Go you can get a memory location pointer of a string variable using the built-in & operator because strings in Go are represented as a pointer to a contiguous block of memory that contains the string's characters. Therefore, you can use the & operator to get a pointer to this memory location.
On the other hand, maps in Go are more complex data structures than strings, and they are represented by a pointer to a runtime structure that contains the map's metadata and the pointer to the underlying data. The exact structure of this runtime map object is subject to change in different versions of the Go runtime. Therefore, the pointer to a map object is not guaranteed to be compatible with other types and may not be used safely without casting or using the unsafe package.
There are two ways to reach the address:
First solution as Burak mentioned is using a format specifier which is helpful if printing the pointer is intended. And the second one is to using unsafe package:
package main
import (
"fmt"
"unsafe"
)
var name = map[string]string{
"name": "John",
"lastname": "Doe",
}
func main() {
ptr := unsafe.Pointer(&name)
fmt.Println(ptr)
}
The unsafe package provides low-level facilities to access and manipulate memory directly, which allows you to work around the type system and access memory locations that are not normally accessible. However, this comes at the cost of safety and portability, so it should be used with care and only when absolutely necessary.
In the following code I have created two functions someFunction1 and someFunction2:
package main
import (
"fmt"
)
func someFunction1() {}
func someFunction2() {}
func main() {
fmt.Println(someFunction1) // 0x7de480
fmt.Println(someFunction2) // 0x7de4a0
}
By printing them I got two hexadecimal values 0x7de480 and 0x7de4a0. My question is simple, what do these values mean?
These hexadecimal values are the memory addresses of the two functions someFunction1 and someFunction2. They indicate the location of the functions in the computer's memory. This means that someFunction1 is stored at memory address 0x7de480 and someFunction2 is stored at memory address 0x7de4a0.
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.
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.
I'm quite confusing about the struct in Go.
This is the code: http://play.golang.org/p/b1NEh7JZoK
Why I could't get the address of a variable to a struct?
If I have two int variables, one stores value, one stores address(pointer), like this : http://play.golang.org/p/XhvKX-ifdn
I can get the actual address of these two variables, but why struct can't?
fmt.Println prints things in a more readable format. If you want to actually see the addresses, use fmt.Printf with %p verb:
fmt.Printf("%p\n", &a) // 0x10328000
fmt.Printf("%p -> %p\n", &b, b) // 0x1030e0c0 -> 0x10328000
Playground.