I'm trying to create a map of elements. I wanted to use a pointer rather then an integer as a key. The problem is... I keep getting the same pointer. No matter how many times I create it. Why is this? How do I get a real pointer, without using the unsafe package if possible.
package main
import (
"fmt"
)
type Thingy struct{}
var things map[*Thingy]int
func main() {
things = make(map[*Thingy]int)
thing1 := new(Thingy)
tracePointer("thing1", thing1)
things[thing1] = 1
thing2 := new(Thingy)
tracePointer("thing2", thing2)
things[thing2] = 2
thing3 := &Thingy{}
tracePointer("thing3", thing3)
things[thing3] = 3
fmt.Printf("Amount of things: %d\n", len(things))
}
func tracePointer(identifier string, obj interface{}) {
fmt.Printf("%s pointer: %p\n", identifier, obj)
}
Ouput:
thing1 pointer: 0x546570
thing2 pointer: 0x546570
thing3 pointer: 0x546570
Amount of things: 1
struct{} is a special case, it always uses 0 bytes of memory and will always have the same address.
If you just want a dummy pointer, you can use type Thingy byte.
thing1 pointer: 0x10328000
thing2 pointer: 0x10328020
thing3 pointer: 0x10328021
Amount of things: 3
playground
//edit
As James Henstridge pointed out in the comments, struct{}'s address changes if they are inside a bigger struct.
http://play.golang.org/p/51_PhqDNhk
Related
I would like to get rid of the variable temp in the following code:
type myinterface interface {
f1()
}
type a struct {
val int
}
type b struct {
mi *myinterface
}
func (a) f1() {
}
func demo() {
a1 := a{3}
var temp myinterface = a1
b1 := b{&temp}
fmt.Println(b1)
But if I try to write
b1 := b{&myinterface(a1)}
I get the message
cannot take the address of myinterface(a1) ( undefined )
what is the correct way to do this?
Update:
I did not a pointer to an interface, since an interface can hold a struct or a pointer to a struct, as also detailed in this question:
"<type> is pointer to interface, not interface" confusion
Let me know if this is what you are looking for:
https://play.golang.org/p/ZGRyIqN7bPR
Full code:
package main
import (
"fmt"
)
type myinterface interface {
f1()
}
type a struct {
val int
}
type b struct {
mi myinterface
}
func (a) f1() {}
func main() {
fmt.Println("Hello, playground")
a1 := &a{3}
b1 := b{a1}
fmt.Println(b1)
}
You almost never need a pointer to an interface, since interfaces are just pointers themselves.
So just change the struct b to:
type b struct {
mi myinterface
}
myinterface(a1) is a type conversion, it converts a1 to type myinteface.
Type conversion expressions are not addressable, so you cannot take the address of it. What is addressable is listed explicitly in the Spec: Address operators:
The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x [in the expression of &x] may also be a (possibly parenthesized) composite literal.
This related answer lists several options how to obtain the address of such expressions: How do I do a literal *int64 in Go?
For example if you use a composite literal to create a slice of type []myinterface and put a1 in it, you can take the address of its first element (which will be of type *myinterface):
b1 := b{&[]myinterface{a1}[0]}
And it will work (try it on the Go Playground):
a1 := a{3}
b1 := b{&[]myinterface{a1}[0]}
fmt.Println(b1)
But know that using pointers to interfaces is very rarely needed, so is a field of type *myinterface really what you want in the first place?
Interface values can be nil, and also nil values (e.g. nil pointers) can also be wrapped in interfaces, so most likely you don't need a pointer to interface. We would have to know your "wider" goal to tell if this is what you really need.
I'm very new to Go and am trying to set a *int to point to a number, say 12345.
package main
import (
"fmt"
"reflect"
)
func main() {
var guess *int
fmt.Println(reflect.TypeOf(guess))
*guess = 12345
fmt.Println(guess)
}
But it's giving me the following error:
Type: *int
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x483c7d]
goroutine 1 [running]:
main.main()
/home/aaron/projects/gopath/src/github.com/AaronNBrock/go-guess/main.go:16 +0x9d
exit status 2
I see that the error is with the *guess = 12345 since 12345, but I'm not sure what's causing it.
You have a pointer variable which after declaration will be nil.
If you want to set the pointed value, it must point to something. Attempting to dereference a nil pointer is a runtime panic, just what you experienced. You may use the builtin new() function to obtain a pointer to a zero-valued int, and then you can set the pointed value:
var guess *int
guess = new(int)
*guess = 12345
Your modified app:
var guess *int
fmt.Println(guess)
guess = new(int)
*guess = 12345
fmt.Println(guess, *guess)
Output (try it on the Go Playground):
<nil>
0x10414028 12345
Note that you can make this shorter using a short variable declaration like this:
guess := new(int)
*guess = 12345
Another option to make a pointer point to something "useful" is to assign the address of a variable to the pointer variable, like this:
value := 12345 // will be of type int
guess := &value
But this solution modifies the pointer value, not the pointed value. The result is the same though in this simple example.
You could also just assign the address of another variable, and then proceed to change the pointed value:
var value int
guess := &value
*guess = 12345
Also note that since guess points to value, changing the pointed value will change the value of the value variable too. Also if you change the value variable directly, the pointed value by guess also changes: they are one and the same:
var value int
guess := &value
value = 12345
fmt.Println(*guess) // This will also print 12345
Try this one on the Go Playground.
FWIW, if you do this often enough (like setting up data in unit tests) it's useful to have a shorthand, hence:
https://github.com/mwielbut/pointy
val := 42
pointerToVal := &val
// vs.
pointerToVal := pointy.Int(42)
Here's one possible utility function:
func getIntPointer(val int) *int {
return &val
}
Or as an inline anonymous function:
func(val int) *int { return &val }(val)
For example,
var foo *int = func(val int) *int { return &val }(10)
Run on The Go Playground
EDIT: It's probably better to make this a 2-liner:
val := new(int)
*val = 5
Assuming you really want an int pointer and not just an int, then you need a variable to store the int you point to. For example:
var guess *int
a := 12345
guess = &a
Starting from Go 1.18 you can make use of generics
func Pointer[K any](val K) *K {
return &val
}
A tricky way to get int pointer without create new variable.
someIntPtr := &[]int64{10}[0]
Like this, you don't have to use a one line func like func(val int) *int { return &val }(10) or create a variable of int.
I am wondering what is the behavior of a pointer to an element of slice after the slice had been appended to, for example:
package main
import "fmt"
func main() {
my_slice := []int {3}
silly_ptr := &my_slice[0]
// Do we know that silly_ptr points to value equal 3
// all the time? (If we don't explicitly change it).
fmt.Printf("%p\n", silly_ptr)
fmt.Println(*silly_ptr)
for i := 0; i < 10; i++ {
my_slice = append(my_slice, i)
}
silly_ptr_2 := &my_slice[0]
fmt.Printf("%p\n", silly_ptr_2)
fmt.Println(*silly_ptr_2)
}
Produces: (no surprises)
0xc20800a200
3
0xc20805a000
3
I know that when appending to dynamic array, at certain points we have repopulate the entire array, and therefore memory address of the original array elements is not reliable. To the best of my knowledge similar code is valid in c++, but silly_ptr could be pointing to anything. rust does not allow mutating a vector if it is being borrowed, so the above logic would not compile.
But what about Go? I know that by escape analysis it is valid to return a pointer to a local variable, the variable would be just created on the heap for you. My intuition tells me that the same logic applies in the above case. The memory location where silly_ptr is pointing to will not be repopulated, and hence will always store 3 (if we don't explictly change it). Is this right?
No, it will not always store 3.
Go has memory management. As long as there is an active pointer to an underlying array for a slice, the underlying array is pinned, it will not be garbage collected. If you have a pointer to an element of an underlying array, you can change the value of the element. For example,
package main
import (
"fmt"
)
func pin() *int {
s := []int{3}
fmt.Println(&s[0])
a := &s[0]
s = append(s, 7)
fmt.Println(&s[0])
return a
}
func main() {
a := pin()
fmt.Println(a, *a)
*a = 42
fmt.Println(a, *a)
}
Output:
0xc82000a340
0xc82000a360
0xc82000a340 3
0xc82000a340 42
A slice descriptor contains a pointer to an underlying array so you can see something similar with a slice. For example,
package main
import (
"fmt"
)
func pin() []int {
s := []int{3}
fmt.Println(&s[0])
d := s
s = append(s, 7)
fmt.Println(&s[0])
return d
}
func main() {
d := pin()
fmt.Println(&d[0], d)
d[0] = 42
fmt.Println(&d[0], d)
}
Output:
0xc82000a340
0xc82000a360
0xc82000a340 [3]
0xc82000a340 [42]
I want to pass struct's pointer to function that expect interface{}. Then get (through reflection) the pointer to the struct's member and then modify it using this pointer. I've read a much of Q&A and tried much of variations, but still I can get it work.
Let's consider example below:
type Robot struct {
Id int
}
f := func(i interface {}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
ptr := v.Addr().Pointer()
*ptr = 100
//^ it needs to me for functions expecting the pointer: Scan(&pointerToValue)
}
robot := &Robot{}
f(robot)
println(robot.Id) //I want to get here 100
I think the problem in poor understanding what actually do Addr() and Pointer() methods of reflect package..
Here's a working version of function f:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
ptr := v.Addr().Interface().(*int)
*ptr = 100
}
playground example
The conversion to integer pointer goes as follows:
v is a reflect.Value representing the int field.
v.Addr() is a relfect.Value representing a pointer to the int field.
v.Addr().Interface() is an interface{} containing the int pointer.
v.Addr().Interface().(*int) type asserts the interface{} to a *int
You can set the field directly without getting a pointer:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
v.SetInt(100)
}
playground example
If you are passing the value along to something expecting interface{} (like the db/sql Scan methods), then you can remove the type assertion:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
scan(v.Addr().Interface())
}
playground example
It seems golang does not have the pointer operator -> as C and C++ have. Now let's say I have a function looks something like this: myfun(myparam *MyType), inside the function, if I want to access the member variables of MyType, I have to do (*myparam).MyMemberVariable. It seems to be a lot easier to do myparam->MyMemberVariable in C and C++.
I'm quite new to go. Not sure if I'm missing something, or this is not the right way to go?
Thanks.
In Go, both -> and . are represented by .
The compiler knows the types, and can dereference if necessary.
package main
import "fmt"
type A struct {
X int
}
func main() {
a0, a1 := A{42}, &A{27}
fmt.Println(a0.X, a1.X)
}
You can do myparam.MyMemberValue, pointers are automatically dereferenced
Go spec:
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 shorthand for (*x.A).f.
Hummm, this automatic dereferencing can be very confusing (for old programmers like me)
If you learn programmation with GOLANG, no problem, it is practical.
If you pass from C to GOLANG, this will seem strange, you will probably prefer (at the beginning at least) to keep the "(*my_var).my_field" expression instead of "my_var.myfield"
If you pass from GOLANG to C, you will get many compilation errors.
Goes uses -> for passing data by using channels.
package main
import "fmt"
type Person struct {
Name string
}
func (p *Person) printName() {
p.Name = "brian"
}
func main() {
// obj
brian := Person{""}
// prints obj default value
fmt.Println("No pointer", brian.Name)
// it access the method with the pointer
brian.printName()
// prints the result
fmt.Println("With a pointer", brian.Name)
}