String method of reflect.Value does not work as expected - reflection

I'm trying to retrieve the string value from a reflect.Value,
I expect value.String() to be okok but I got <interface {} Value> instead.
Did I miss something?
package main
import (
"fmt"
"reflect"
)
func dump(args *[]interface{}) {
value := reflect.ValueOf(*args).Index(0)
fmt.Println(value.String())
if value.String() != "okok" {
fmt.Println("miss")
}
}
func main () {
var args []interface{}
args = append(args, "okok")
dump(&args)
}

The documentation for Value.String explains the behavior:
Unlike the other getters, it does not panic if v's Kind is not String.
Instead, it returns a string of the form "<T value>" where T is v's
type.
String is just an implementation of the fmt.Stringer interface.
If you want the value itself, you can use the Interface function on reflect.Value and then do a type assertion to get the string. Example:
package main
import (
"fmt"
"reflect"
)
func dump(args *[]interface{}) {
value := reflect.ValueOf(*args).Index(0)
str := value.Interface().(string)
fmt.Println(str)
if str != "okok" {
fmt.Println("miss")
}
}
func main() {
var args []interface{}
args = append(args, "okok")
dump(&args)
}
Playground link

Related

Indirect of interface type in Go

I'm trying to create a function that will create a new instance of an interface, and assign that instance to a variable that has the type of the interface. Here is a simple example program (which does not compile):
package main
import (
"fmt"
)
type Foo interface {
Foo(int) int
}
type Foo_impl struct {}
func (f *Foo_impl) Foo(x int) int {
return x * 2
}
func main() {
var x *Foo_impl
constructFoo(x)
fmt.Println("Hello, playground")
}
func constructFoo(x Foo) {
*x = Foo_impl{} // Blows up here - invalid indirect of x (type Foo)
}
Is it possible via reflection to indirect an interface variable, and assign to the underlying value? If I were not using interfaces, I would do something like this,
func main() {
var x int
foo(&x)
fmt.Printf("%d\n", x)
}
func foo(x *int) {
*x = 4
}
And as expected, this will print out 4. The issue is that interface variables cannot be indirected in the normal way. Is there a way around this?
But why can't you be more idiomatic and do
func constructFoo() Foo {
return &Foo_impl{}
}
then, in main:
func main() {
fmt.Println(constructFoo().Foo(10))
}
?
Also, there is accept interfaces, return structs approach which may be interesting for you.
Hope this helps a bit.
I was able to write a function that did what I want
package main
import (
"fmt"
"reflect"
)
type Y interface {
SetX(int)
}
type X struct {
test int
}
func (x *X) SetX(param int) {
x.test = param
}
func main() {
var x *X
y := foo(&x)
y.SetX(12)
fmt.Printf("%+v", x)
}
func foo(x interface{}) Y {
t := reflect.TypeOf(x)
pointerType := t.Elem()
realType := pointerType.Elem()
pointer := reflect.New(realType)
reflect.Indirect(reflect.ValueOf(x)).Set(pointer)
return pointer.Interface().(Y)
}
The foo function can initialize any double pointer to a type that implements Y, and it returns the new instance as a Y.
Implementing an interface will help you to pass mock structs to your function and then using type assertion you can get the value of struct. Basically interface is the only way in which you can wrap your any type and pass it to the function and then using type assertions you can get the underlying value.
package main
import (
"fmt"
)
type Foo interface {
Foo(int) int
}
type Foo_impl struct {}
func (f *Foo_impl) Foo(x int) int {
return x * 2
}
func main() {
var x *Foo_impl
constructFoo(x)
}
func constructFoo(x interface{}) {
fmt.Println(x.(interface{}).(*Foo_impl).Foo(10)) // dereference the type to call the function on pointer receiver
}
Also It is required to dereference the value of type struct passed to the constructor to call the method using pointer receiver.
Check working code on Go Playground
In Golang Type assertions is defined as:
For an expression x of interface type and a type T, the primary
expression
x.(T)
asserts that x is not nil and that the value stored in x is of type T.
The notation x.(T) is called a type assertion.
More precisely, if T is not an interface type, x.(T) asserts that the
dynamic type of x is identical to the type T. In this case, T must
implement the (interface) type of x; otherwise the type assertion is
invalid since it is not possible for x to store a value of type T. If
T is an interface type, x.(T) asserts that the dynamic type of x
implements the interface T.
In Go, if we have a type
type Foo_impl struct {}
We usually using
func NewFoo_impl() *Foo_impl
to create this instance of this structure(if need)
There is no instance of the interface, we just say a type implement an interface or not.
So your code can be
var x Foo
x = NewFoo_impl()
// or x = &Foo_impl{}
About indirect the interface type, it's not hard to understand by knowing it just like void* in C.
Dereference it won't return the type you want, in fact, the compiler also doesn't know how to deal with it. It became an incomplete type, so Go's decision is disallowing it.
Here is a solution for your requirements, however a pointer of the type that is being passed to you constructor method can not be nil, one way to address it is to use default instance.
package main
import (
"fmt"
)
var defaultFooImpl = &Foo_impl{}
type Foo interface {
Foo(int) int
}
type Foo_impl struct {
id int
}
func (f *Foo_impl) Foo(x int) int {
return x * 2
}
func main() {
var x *Foo_impl = defaultFooImpl
constructFoo(x)
fmt.Println("Hello, playground %v", x)
}
func constructFoo(x Foo) {
switch value :=x.(type) {
case *Foo_impl:
*value = Foo_impl{2}
}
}
Yet another approach with varadic function that accepts multiple nil pointers to Foo,
package main
import (
"fmt"
)
type Foo interface {
Foo(int) int
}
type Foo_impl struct {
id int
}
func (f *Foo_impl) Foo(x int) int {
return x * 2
}
func main() {
var x *Foo_impl
var x1 = []Foo{x}
constructFoo(x1...)
fmt.Println("Hello, playground %v", x1[0])
}
func constructFoo(x ...Foo) {
for i, foo := range x {
switch (foo).(type) {
case *Foo_impl:
x[i] = &Foo_impl{2}
}
}
}

Golang: Assigning a value to struct member that is a pointer

I'm trying to assign a value to a struct member that is a pointer, but it gives "panic: runtime error: invalid memory address or nil pointer dereference" at runtime...
package main
import (
"fmt"
"strconv"
)
// Test
type stctTest struct {
blTest *bool
}
func main() {
var strctTest stctTest
*strctTest.blTest = false
fmt.Println("Test is " + strconv.FormatBool(*strctTest.blTest))
}
The runtime error seems to come from the assignment of the value with *strctTest.blTest = false , but why? How do I set it to false?
Why is it an error? Because a pointer only points. It doesn't create anything to point AT. You need to do that.
How to set it to false? This all depends on WHY you made it a pointer.
Is every copy of this supposed to point to the same bool? Then it should be allocated some space in a creation function.
func NewStruct() *strctTest {
bl := true
return &strctTest{
blTest: &bl,
}
}
Is the user supposed to point it at a boolean of his own? Then it should be set manually when creating the object.
func main() {
myBool := false
stctTest := strctTest{
blTest: &myBool
}
fmt.Println("Test is " + strconv.FormatBool(*strctTest.blTest))
}
Another way you can think of it is the zero value of a boolean is false.
This is not as clear but another way to do it.
https://play.golang.org/p/REbnJumcFi
I would recommend a New() func that returns a reference to a initialized struct type.
You could also do something like:
package main
import (
"fmt"
"strconv"
)
// Test
type stctTest struct {
blTest *bool
}
func main() {
strctTest := stctTest{
blTest: &[]bool{true}[0],
}
fmt.Println("Test is " + strconv.FormatBool(*strctTest.blTest))
}
https://play.golang.org/p/OWSosQhrUql
Following up on JTs Answer, I also would recommend using the new function as such:
package main
import (
"fmt"
"strconv"
)
// Test
type stctTest struct {
blTest *bool
}
func main() {
strctTest := &stctTest{
blTest: new(bool),
}
*strctTest.blTest = true
fmt.Println("Test is " + strconv.FormatBool(*strctTest.blTest))
}
After initializing the memory with new(), you can directly assign a value to the de-referenced pointer. This way you do not need to use another variable to get the address from.
https://go.dev/play/p/BmekoTalQVh

How to get the address of a function in go?

Is it possible to get the address of a function reference in Go?
Something like
func myFunction() {
}
// ...
unsafe.Pointer(&myFunction)
Just that is does not work that way. My guess it's not possible, but I did not found any proof yet.
Edit: Background
The background of my question comes from dealing with CGO and C Function pointers.
This works:
/*
void go_myFunction();
typedef void (*myFunction_f)();
myFunction_f pMyFunction;
*/
import "C"
//export go_myFunction
func go_myFunction() {
// ...
}
func SetupFp() {
C.pMyFunction = (*[0]byte)(unsafe.Pointer(C.go_myFunction))
}
I'm also aware that the documentation states that passing a pointer to a go function does not work. But the above code seems no to be that far from it. I was just wondering if one could somehow skip the export step.
function type in Go is not addressable and not comparable because:
Function pointers denote the code of the function. And the code of an anonymous function created by function literal is only stored once in memory, no matter how many times the code that returns the anonymous function value runs.
Original answer
If you need to compare addresses of a functions you can do it with reflect.Pointer. But any way this operation is more senseless than impossible because:
If v's Kind is Func, the returned pointer is an underlying code pointer, but not necessarily enough to identify a single function uniquely. The only guarantee is that the result is zero if and only if v is a nil func Value.
You may get the address of a Go function like this:
package main
import (
"fmt"
"reflect"
)
func HelloWorld() {
fmt.Println("Hello, world!")
}
func main() {
var ptr uintptr = reflect.ValueOf(HelloWorld).Pointer()
fmt.Printf("0x%x", ptr)
}
You can get address of function use function GetFuncAddr:
package main
import (
"fmt"
"unsafe"
"reflect"
)
func HelloWorld() {
fmt.Println("Hello, world!")
}
func GetFuncAddr(i interface{}) uintptr {
type IHeader struct {
typ uintptr
word uintptr
}
return (*IHeader)(unsafe.Pointer(&i)).word
}
func main() {
tmp := HelloWorld
ptr1 := *(*uintptr)(unsafe.Pointer(&tmp)) //Way 1
ptr2 := GetFuncAddr(HelloWorld) //Way 2
fmt.Printf("0x%x = 0x%x", ptr1, ptr2)
//Thits is not are functon addrress!!!
BadPTR1 := reflect.ValueOf(HelloWorld).Pointer()
BadPTR2 := **(**uintptr)(unsafe.Pointer(&tmp)) //dereferenced pointer
fmt.Printf("\nBAD: 0x%x = 0x%x", BadPTR1 , BadPTR2 )
}

How to extract the interface type name and package using reflection?

I need to know the type name and its path using reflection. type Type has a Name() and PkgPath() method but both of them return empty if the type is an interface.
However if I reflect a function and extract the type information of its arguments I get the correct type information. Should I assume it's a bug in the former case? Shouldn't TypeOf return the same type information regardless the context(e.g. type function parameter or type of a value) ?
I'm aware of type assertion but I don't always have a value to do the assertion so I need to work with reflect.Type information.
package main
import (
"fmt"
"reflect"
"golang.org/x/net/context"
)
func main() {
c := reflect.TypeOf(withValue(""))
fn := func(context.Context){}
fc := reflect.TypeOf(fn).In(0)
fmt.Println(isContext(c), isContext(fc), c, fc)
}
func isContext(r reflect.Type) bool {
return r.PkgPath() == "golang.org/x/net/context" && r.Name() == "Context"
}
func withValue(v interface{}) context.Context {
return context.WithValue(context.TODO(), "mykey", v)
}
Prints
false true *context.valueCtx context.Context
Here is some working code: https://play.golang.org/p/ET8FlguA_C
package main
import (
"fmt"
"reflect"
)
type MyInterface interface {
MyMethod()
}
type MyStruct struct{}
func (ms *MyStruct) MyMethod() {}
func main() {
var structVar MyInterface = &MyStruct{}
c := reflect.TypeOf(structVar)
fn := func(MyInterface) {}
fc := reflect.TypeOf(fn).In(0)
fmt.Println(isMyInterface(c), isMyInterface(fc), c, fc)
// OP expects : "true true main.MyInterface main.MyInterface"
}
func isMyInterface(r reflect.Type) bool {
// TypeOf trick found at https://groups.google.com/forum/#!topic/golang-nuts/qgJy_H2GysY
return r.Implements(reflect.TypeOf((*MyInterface)(nil)).Elem())
}
Here is my answer before I found an actual solution with reflect.
I'm gonna let it here because I think it still has some interesting parts.
First things first: for c, r.PkgPath() and r.Name() are empty because the underlying type is a pointer (*context.valueCtx).
To fix that, you can use c := reflect.Indirect(reflect.ValueOf(withValue(""))).Type()
But that does not make isContext(c) true, because you then have r.PkgPath() == "golang.org/x/net/context" && r.Name() == "valueCtx".
The best way to check if a var implements an interface is to drop the reflection and use a type assertion like this:
https://play.golang.org/p/td1YaHHej9
package main
import "fmt"
type MyInterface interface {
MyMethod()
}
type MyStruct struct{}
func (ms *MyStruct) MyMethod() {}
func main() {
var structVar MyInterface = &MyStruct{}
fmt.Println(isMyInterface(structVar))
}
func isMyInterface(object interface{}) bool {
_, ok := object.(MyInterface)
return ok
}
Your code works as you expect with the function parameter because there is no underlying value, so reflect uses the interface type. But for any concrete var, it will use the actual type of the value.
There are two kinds of Interface in golang, aka, eface and iface. And the eface is an empty interface, which can simply represented as interface {}. The iface is kind of interface which has at least one method, such as:
type MyInterface interface {
Greeting() string
}
In golang implementation, both eface and iface are two-word long struct. The eface holds the data and the data type, the iface holds the data, the interfacetype and the data type. When an iface assigned to an eface, the interfacetype information is ignored. Only the data and the data type passed to the eface.
So, reflect.TypeOf(i interface{}) 's parameter is and eface, no interfacetype information (aka context.Context in your case). So you can't get the original interfacetype.

Discover the return type of the current function in go

I have a function that is being generated using reflection and reflect.MakeFunc, so I don't actually have the return type until runtime.
Inside the template function that MakeFunc is using, is there a way to determine the return type of the concrete function being templated?
Essentially, is there a way to determine the return type iof the currently executing function at runtime?
I know about the Out method:
fn.Type().Out(0)
And I can find the return type of a function easily enough?
But is there a way to find the return type of the currently executing function (as opposed to an explicit passed function reference).
You should check fn.Type().Out(0).Kind(), for example:
func main() {
fnTmpl := func(in []reflect.Value) []reflect.Value {
return []reflect.Value{in[0]}
}
makeFn := func(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
fn.Set(reflect.MakeFunc(fn.Type(), fnTmpl))
}
var nFn func(int) int
makeFn(&nFn)
kind := reflect.TypeOf(nFn).Out(0).Kind()
switch kind {
case reflect.Int:
fmt.Println("int")
}
}
In the case you are talking about, the return type of the currently executing function is always []reflect.Type (because that is what a function passed to reflect.MakeFunc must return). What you really want is the return type of the reflect.makeFuncStub function that called your function.
There is no way to get that (except perhaps some strange inspection of the call stack), but you can make an enhanced version of MakeFunc that provides the information:
package main
import (
"fmt"
"reflect"
)
// MakeFunc is like reflect.MakeFunc, but fn has an extra argument, retType, which
// is passed the desired return type.
func MakeFunc(typ reflect.Type, fn func(args []reflect.Value, retType reflect.Type) (results []reflect.Value)) reflect.Value {
if n := typ.NumOut(); n != 1 {
panic("wrong number of return values")
}
rt := typ.Out(0)
return reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
return fn(args, rt)
})
}
func makeReturnOne(fptr interface{}) {
fn := reflect.ValueOf(fptr).Elem()
fn.Set(MakeFunc(fn.Type(), returnOne))
}
func returnOne(args []reflect.Value, retType reflect.Type) []reflect.Value {
ret := reflect.New(retType).Elem()
switch retType.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
ret.SetInt(1)
case reflect.Float32, reflect.Float64:
ret.SetFloat(1.0)
default:
panic("returnOne only supports int and float types")
}
r := ret.Interface()
fmt.Printf("returning %v as %T\n", r, r)
return []reflect.Value{ret}
}
func main() {
var r1f func() float64
var r1i func() int
makeReturnOne(&r1f)
makeReturnOne(&r1i)
fmt.Println(r1f())
fmt.Println(r1i())
}
I might have misinterpreted what you are trying to achieve, but why not just take the kind of the value you are returning? Modifying OneOfOne's example as follows:
fnTmpl := func(in []reflect.Value) (res []reflect.Value) {
res = []reflect.Value{in[0]}
fmt.Println("Returned:", res[0].Kind())
return res
}
Playground: http://play.golang.org/p/EujmxyGRrI

Resources