Ensuring a parameter must be pointer (or interface, which internally a pointer) - go

Sometimes we make a function that like C#'s out in the parameter, just like json.Unmarshal or any kind of unmarshal function.
How in Go compile time (instead of runtime) we can make sure that the variable that being passed is a pointer or an interface?
In runtime I can do something like this:
func mustStructPtr(f interface{}) {
v := reflect.ValueOf(f)
if v.Kind() != reflect.Ptr {
panic(fmt.Errorf("not a pointer: %T", f))
}
v = v.Elem() // dereference the pointer
if v.Kind() != reflect.Struct { // TODO: non null map or slice also ok
panic(fmt.Errorf("not struct; is %T", f))
}
}
How to enfoce this on compile time in Golang? so something like this are allowed
var myStruct MyStruct
myFunc(&myStruct) // ok, because pointer
myFunc(myStruct) // <-- not ok, because this cannot receive
var x interface{} = &mystruct
myFunc(x) // ok, because interface to pointer
x = myStruct
myFunc(x) // <-- not ok, because interface to non pointer
var y map[string]interface{}
myFunc(y) // ok, because map internally a pointer
var z = []myStruct{}
myFunc(&z) // ok, because a pointer

You can't really ensure that. If you really want a pointer I guess you could make your function generic and have it accept *T, but then you still don't know that T is a struct and it won't work with an interface.
You can catch this with linters (at least for json.Unmarshal) and otherwise, unit testing.

One of the approaches to increase type safety in your case would be to declare a new type and enforce the check on creation.
type PointerOrInterface struct {
val interface{}
}
func NewPointerOrInterface(val interface{}) PointerOrInterface {
// check
return PointerOrInterface{
val: val,
}
}

Related

Go Reflect field name to specific interface

I have a struct type with a number of fields that all implement a Renderer interface. The field types implement the interface with pointer receivers. I would like to have a function that takes the field name and calls the Render method on that field. I am able to locate the field and get lots of information about it, but doing the type assertion seems to be biting me because of the pointer receivers. Here's some code that shows my problem:
package main
import (
"fmt"
"reflect"
)
type Renderer interface {
Render()
}
type First struct {
ExampleField Field
}
type Field []int
func (f *Field) Render() {
fmt.Println("Hello from first")
}
func main() {
f := First{
Field{1, 2, 3},
}
f.ExampleField.Render()
renderField("ExampleField", &f)
renderField2("ExampleField", &f)
}
func renderField(field string, f *First) {
structVal := reflect.ValueOf(*f)
renderType := reflect.TypeOf((*Renderer)(nil)).Elem()
fieldToRender := structVal.FieldByName(field)
fieldPtr := reflect.PtrTo(fieldToRender.Type())
fmt.Printf("Implements? %v\n", fieldPtr.Implements(renderType))
fmt.Printf("Addressable? %v\n", fieldToRender.CanAddr())
fieldInter := fieldToRender.Interface()
if renderer, ok := fieldInter.(Renderer); ok {
// Pointer receiver so this never gets called
fmt.Print("Able to cast")
renderer.Render()
}
}
func renderField2(field string, f *First) {
structVal := reflect.ValueOf(*f)
fieldToRender := structVal.FieldByName(field)
vp := reflect.New(reflect.TypeOf(fieldToRender))
vp.Elem().Set(reflect.ValueOf(fieldToRender))
vpAddr := vp.Elem().Addr()
typeVal := vpAddr.Interface()
fmt.Println(typeVal) // <main.Field Value>⏎
renderer := typeVal.(Renderer)
renderer.Render()
// interface conversion: *reflect.Value is not main.Renderer: missing method Render
}
renderField2 seems to get me close but Addr() gives me a *Reflect.Value and when I call Interface() that seems to be the underlying type instead. If I switch to a non-pointer receiver then the first function works. I found reflect value Interface and pointer receiver which seems to be almost exactly what I'm asking, and the question is answered but if I actually call the isZeroer method presented in the playground link it's always false so it doesn't actually seem to answer the question.
It seems like Addr is the key because it specifically mentions pointer receivers but I'm struggling to coerce it back into an interface.
Use this code:
func renderField(name string, f *First) {
structVal := reflect.ValueOf(f).Elem()
field := structVal.FieldByName(name).Addr().Interface()
if renderer, ok := field.(Renderer); ok {
renderer.Render()
}
}
The key point is to change:
structVal := reflect.ValueOf(*f)
to:
structVal := reflect.ValueOf(f).Elem()
The statement used in the question creates a non-addressable struct value. The fields in a non-addressable struct are also not addressable, therefore it's not possible to access the pointer receiver on the fields.
The statement used in this answer creates an addressable struct value.

Strange behavior for a pointer of an interface

I wrote 3 similar functions to figure out a strange behavior of Go's pointer reflection.
package main
import (
"reflect"
"fmt"
)
var i interface{} = struct {}{} // i is an interface which points to a struct
var ptr *interface{} = &i // ptr is i's pointer
func f(x interface{}) { // print x's underlying value
fmt.Println(reflect.ValueOf(x).Elem())
}
func main1() { // f is asking for interface? OK, I'll use the struct's interface
structValue := reflect.ValueOf(ptr).Elem().Elem().Interface()
f(structValue)
}
func main2() { // Error? Let me try the struct's pointer
structPtr := reflect.ValueOf(ptr).Elem().Interface()
f(structPtr)
}
func main3() { // Why this one could succeed after New() ?
typ := reflect.ValueOf(ptr).Elem().Elem().Type()
newPtr := reflect.New(typ).Elem().Addr().Interface()
f(newPtr)
}
func main() {
//main1() // panic: reflect: call of reflect.Value.Elem on struct Value
//main2() // panic: reflect: call of reflect.Value.Elem on struct Value
main3() // OK. WHY???
}
Only main3 is working, the other 2 would panic. Why?
The key difference of 3 is that it creates a New Value.
As to main2, I think ValueOf().Elem().Interface() has already reconstructed a interface which points at the struct{}{}, just don't understand why it would fail.
The value returned from reflect.ValueOf holds the concrete value stored in the argument. If the argument is nil, the zero reflect.Value is returned.
To put this another way, the reflect.Value and the interface passed to reflect.Value have the same underlying value.
The functions main1 and main2 will work as I think you expect if you f change to:
func f(x interface{}) { // print x's underlying value
fmt.Println(reflect.ValueOf(x))
}
The argument to f in main3 is a *struct{}. The function f dereferences the pointer (with the call to Elem()) and prints the reflect value for the struct{}.
One point that might be confusing is that reflect.ValueOf(ptr).Elem().Elem().Interface() and reflect.ValueOf(ptr).Elem().Interface() return an interface with the same concrete value.
The expression reflect.ValueOf(ptr).Elem() is the reflect value corresponding to i. The call to Interface() on this value returns an interface with the concrete value in i.
The expression reflect.ValueOf(ptr).Elem().Elem() is the reflect value corresponding to i's concrete value. The call to Interface() on this value returns an interface containing that concrete value.

How do I use reflect.DeepEqual() to compare a pointer's value against the zero value of its type?

I need a generic function to check whether something is equal to its zero-value or not.
From this question, I was able to find a function that worked with value types. I modified it to support pointers:
func isZeroOfUnderlyingType(x interface{}) bool {
rawType := reflect.TypeOf(x)
//source is a pointer, convert to its value
if rawType.Kind() == reflect.Ptr {
rawType = rawType.Elem()
}
return reflect.DeepEqual(x, reflect.Zero(rawType).Interface())
}
Unfotunately, this didn't work for me when doing something like this:
type myStruct struct{}
isZeroOfUnderlyingType(myStruct{}) //Returns true (works)
isZeroOfUnderlyingType(&myStruct{}) //Returns false (doesn't) work
This is because &myStruct{} is a pointer and there is no way to dereference an interface{} inside the function. How do I compare the value of that pointer against the zero-value of its type?
reflect.Zero() returns a reflect.Value. reflect.New() returns a pointer to a zero value.
I updated the function to check the case where x is a pointer to something:
func isZeroOfUnderlyingType(x interface{}) bool {
rawType := reflect.TypeOf(x)
if rawType.Kind() == reflect.Ptr {
rawType = rawType.Elem()
return reflect.DeepEqual(x, reflect.New(rawType).Interface())
}
return reflect.DeepEqual(x, reflect.Zero(rawType).Interface())
}

interface{} variable to []interface{}

I have an interface{} variable and I know it's a pointer to slice:
func isPointerToSlice(val interface{}) bool {
value := reflect.ValueOf(val)
return value.Kind() == reflect.Ptr && value.Elem().Kind() == reflect.Slice
}
But I'm finding difficult to type cast it into an []interface{} variable:
if isPointerToSlice(val) {
slice, worked := reflect.ValueOf(val).Elem().Interface().([]interface{})
// 'worked' is false :(
}
This doesn't work. Any idea how can I solve this?
If you just want to convert a slice to []interface{} you can use something like this:
func sliceToIfaceSlice(val interface{}) []interface{} {
rf := reflect.Indirect(reflect.ValueOf(val)) // skip the pointer
if k := rf.Kind(); k != reflect.Slice && k != reflect.Array {
// panic("expected a slice or array")
return nil
}
out := make([]interface{}, rf.Len())
for i := range out {
out[i] = rf.Index(i).Interface()
}
return out
}
playground
You can simply use type assertion to obtain the value stored in an interface, e.g.
if isPointerToSlice(val) {
var result []interface{}
result = *val.(*[]interface{})
fmt.Println(result)
} else {
fmt.Println("Not *[]interface{}")
}
The type of the value stored in the interface as you claim is pointer to []interface{}, which is *[]interface{}. The result of the type assertion will be a pointer, just dereference it to get the slice []interface{}.
Using short variable declaration:
result := *val.(*[]interface{}) // type of result is []interface{}
Try it on the Go Playground.
Also your attempt also works:
slice, worked := reflect.ValueOf(val).Elem().Interface().([]interface{})
fmt.Println(slice, worked)
Here's the edited the Playground example which proves your solution works.
But using reflection is unnecessary (as it can be done with type assertion).
Also note that *[]interface{} and *[]someOtherType are 2 different types and you can't obtain a value of *[]interface{} if there is something else in val.
Icza's answer is great and will work especially if you can't know for sure you are getting an interface slice, however if you don't want to bother with the reflect package at all and want to keep imported code low, you can use type switching to obtain the same functionality using only built-in methods.
Using this method, you can shorten your code to just:
package main
import (
"fmt"
)
func main() {
s := []interface{}{"one", 2}
p := &s
do(p)
}
func do(val interface{}) {
switch val.(type){
case *[]interface{}:
var result []interface{}
result = *val.(*[]interface{})
fmt.Println(result)
}
}
Playground: http://play.golang.org/p/DT_hb8JcVt
The downside is if you don't know the exact type of slice you are receiving beforehand, then this will not work unless you list all possible types for handling and assertion.

golang - Pointer idiosyncrasies

Need help understanding why this breaks. PrintFoo can be called using either pointer or value. Why not NumField?
http://play.golang.org/p/Kw16ReujRx
type A struct {
foo string
}
func (a *A) PrintFoo(){
fmt.Println("Foo value is " + a.foo)
}
func main() {
a := &A{foo: "afoo"}
(*a).PrintFoo() //Works - no problem
a.PrintFoo() //Works - no problem
reflect.TypeOf(*a).NumField() //Works - no problem - Type = main.A
reflect.TypeOf(a).NumField() //BREAKS! - Type = *main.A
}
From the documentation :
// NumField returns the number of fields in the struct v.
// It panics if v's Kind is not Struct.
func (v Value) NumField() int
You are calling it on a pointer, you have to call it on a struct instead, for example :
fmt.Println(reflect.Indirect(reflect.ValueOf(a)).NumField())
fmt.Println(reflect.Indirect(reflect.ValueOf(*a)).NumField())
When you're not sure if your value is a pointer or not, use reflect.Indirect:
Indirect returns the value that v points to. If v is a nil pointer,
Indirect returns a zero Value. If v is not a pointer, Indirect returns
v.
//edit:
NumField gets called on Value, not your actual object, for example of you do:
func main() {
a := &A{foo: "afoo"}
fmt.Printf("%#v\n", reflect.TypeOf(*a))
fmt.Printf("%#v\n", reflect.TypeOf(a))
}
You will get :
//*a
&reflect.rtype{size:0x8, ...... ptrToThis:(*reflect.rtype)(0xec320)}
//a
&reflect.rtype{size:0x4, ...... ptrToThis:(*reflect.rtype)(nil)}
As you can tell, it's a completely different beast.
The first one holds information about the pointer, hence ptrToThis points to the actual struct.
The second holds info about the struct itself.

Resources