Reputation: 1091
It's hard to explain, but how I can get a pointer of a something that implements some interface?
Consider the code below:
package main
import (
"fmt"
"unsafe"
)
type Interface interface {
Example()
}
type StructThatImplementsInterface struct {
}
func (i *StructThatImplementsInterface) Example() {
}
type StructThatHasInterface struct {
i Interface
}
func main() {
sameInterface := &StructThatImplementsInterface{}
struct1 := StructThatHasInterface{i: sameInterface}
struct2 := StructThatHasInterface{i: sameInterface}
TheProblemIsHere(&struct1)
TheProblemIsHere(&struct2)
}
func TheProblemIsHere(s *StructThatHasInterface) {
fmt.Printf("Pointer by Printf: %p \n", s.i)
fmt.Printf("Pointer by Usafe: %v \n", unsafe.Pointer(&s.i))
}
https://play.golang.org/p/HoC5_BBeswA
The result will be:
Pointer by Printf: 0x40c138
Pointer by Usafe: 0x40c140
Pointer by Printf: 0x40c138
Pointer by Usafe: 0x40c148
Notice that the Printf
gets the same value (because both StructThatHasInterface
uses the same sameInterface
). However, the unsafe.Pointer()
returns distinct values.
How can I get the same result of Printf
without use fmt
, and reflect
if possible?
Upvotes: 1
Views: 957
Reputation: 120951
In the current version of Go, an interface value is two words long. The concrete value or a pointer to the concrete value is stored in the second word. Use the following code to get the second word as a uintptr
:
u := (*[2]uintptr)(unsafe.Pointer(&s.i))[1]
This code is unsafe and is not guaranteed to work in future.
The supported way to get the pointer is:
u := reflect.ValueOf(s.i).Pointer()
Upvotes: 4