Check if struct implements a given interface - reflection

I need to walk through all the field of a struct type and check if they implements a given interface.
type Model interface {...}
func HasModels(m Model) {
s := reflect.ValueOf(m).Elem()
t := s.Type()
modelType := reflect.TypeOf((*Model)(nil)).Elem()
for i := 0; i < s.NumField(); i++ {
f := t.Field(i)
fmt.Printf("%d: %s %s -> %s\n", i, f.Name, f.Type, f.Type.Implements(modelType))
}
}
Then, if a call HasModels with a struct like so :
type Company struct {...}
type User struct {
...
Company Company
}
HasModels(&User{})
With Company and User both implementing Model; I get f.Type.Implements(ModelType) returning false for the Company field of the User struct.
This is unexpected, so, what Am I doing wrong here ?

You've unfortunately left out the essential parts (please always post complete programs), so I can only guess that the problem is in a method defined on a pointer receiver, in which case the behavior of your code is expected. Check this example and its output:
package main
import (
"fmt"
"reflect"
)
type Model interface {
m()
}
func HasModels(m Model) {
s := reflect.ValueOf(m).Elem()
t := s.Type()
modelType := reflect.TypeOf((*Model)(nil)).Elem()
for i := 0; i < s.NumField(); i++ {
f := t.Field(i)
fmt.Printf("%d: %s %s -> %t\n", i, f.Name, f.Type, f.Type.Implements(modelType))
}
}
type Company struct{}
func (Company) m() {}
type Department struct{}
func (*Department) m() {}
type User struct {
CompanyA Company
CompanyB *Company
DepartmentA Department
DepartmentB *Department
}
func (User) m() {}
func main() {
HasModels(&User{})
}
Playground
Output:
0: CompanyA main.Company -> true
1: CompanyB *main.Company -> true
2: DepartmentA main.Department -> false
3: DepartmentB *main.Department -> true

There's an easier way of doing this that doesn't need reflect. For example:
type middlewarer interface {Middleware() negroni.Handler}
for _, controller := range ctrls {
if m, ok := interface{}(controller).(middlewarer); ok {
n.Use(m.Middleware())
}
}
calls the Middleware() method only in those slice elements that implement the middlewarer interface.

If the variable is not an interface, make it one.
foo := interface{}(yourVar)
Then you can check if it implements the interface you're interested in.
bar, ok := foo.(yourInterface)
if !ok {
// handle the case where it doesn't match the interface
}
bar.methodOnYourInterface()
Here's a playground link for a more fleshed out example

Related

Check if underlying type is a struct with reflect

Given this struct
type A struct {
b *B
c string
d string
}
I want to check with reflect which fields have a struct behind the pointer type, so specifically I want to create a condition that would only be true when iterating over field b. From what I've tried using the reflect documentation I always end up with an invalid Value kind which doesn't allow me to go further as every subsequent method panics.
package main
import (
"fmt"
"reflect"
)
type A struct {
b *B
c string
d string
}
type B struct {
}
func main() {
val := reflect.ValueOf(A{})
for i := 0; i < val.Type().NumField(); i++ {
if val.Field(i).Kind() == reflect.Ptr {
fmt.Println(reflect.Indirect(val.Field(i)).Kind())
}
fmt.Println(val.Field(i).Kind())
}
}
https://play.golang.org/p/oRry3ZubRxI
You get invalid value, because the val.b pointer field is nil, and you can't dereference a nil pointer. If you want your code to work, you have to initialize it with a valid pointer:
val := reflect.ValueOf(A{b: &B{}})
With this change it works and outputs (try it on the Go Playground):
struct
ptr
string
If you want it to work without having to initialize the pointer, then you have to work on the types and not values:
val := reflect.ValueOf(A{})
t := val.Type()
for i := 0; i < t.NumField(); i++ {
if ft := t.Field(i).Type; ft.Kind() == reflect.Ptr {
fmt.Println(ft.Elem().Kind())
}
fmt.Println(t.Field(i).Type.Kind())
}
This outputs the same, try this one on the Go Playground.

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}
}
}
}

How to set an interface{} parameter by reference?

I have a function that has a parameter with the type interface{}. This parameter represents my template data. So on each page it stores different data types (mostly structs). I want to append some data to this parameter's data, but it's an interface{} type and I can't do it.
This is what I tried:
func LoadTemplate(templateData interface) {
appendCustomData(&templateData)
... //other functionality that is not relevant
}
func appendCustomData(dst interface{}) {
// ValueOf to enter reflect-land
dstPtrValue := reflect.ValueOf(dst)
// need the type to create a value
dstPtrType := dstPtrValue.Type()
// *T -> T, crashes if not a ptr
dstType := dstPtrType.Elem()
// the *dst in *dst = zero
dstValue := reflect.Indirect(dstPtrValue)
// the zero in *dst = zero
zeroValue := reflect.Zero(dstType)
// the = in *dst = 0
v := reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS")
if v.IsValid() {
v = reflect.ValueOf("new header css value")
}
reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS").Set(reflect.ValueOf(v))
//dstValue.Set(zeroValue)
fmt.Println("new dstValue: ", dstValue)
}
I can successfully get the "HeaderCSS" value. But I can't replace it with another value. What am I doing wrong?
My templateData looks like this:
I have a generic struct:
type TemplateData struct {
FooterJS template.HTML
HeaderJS template.HTML
HeaderCSS template.HTML
//and some more
}
and I have another struct, such as:
type pageStruct struct {
TemplateData //extends the previous struct
Form template.HTML
// and some other maps/string
}
I send this second struct as templateData argument.
Right now I get this error:
"reflect.Value.Set using unaddressable value" at the line: reflect.ValueOf(dst).Elem().Elem().FieldByName("HeaderCSS").Set(reflect.ValueOf(v))
The code from above is inspired from this answer: https://stackoverflow.com/a/26824071/1564840
I want to be able to append/edit values from this interface. Any idea how can I do it? Thanks.
Don't pass a pointer to interface. Instead the interface{} value should contain the pointer. And simply just hand over this interface{} value:
func LoadTemplate(templateData interface) {
appendCustomData(templateData)
... //other functionality that is not relevant
}
Even if you can't use a more concrete type than interface{} (because you must allow multiple types), you can still use type assertion, it will be "super" easy:
func appendCustomData(d interface{}) {
if ps, ok := d.(*pageStruct); ok {
ps.TemplateData.HeaderCSS += "+new"
}
}
Try this one on the Go Playground.
If you must or want to use reflection, this is how appendCustomData() can be implemented:
type Data struct {
Name string
Age int
Marks []int
}
func appendCustomData(d interface{}) {
v := reflect.ValueOf(d).Elem()
if f := v.FieldByName("Name"); f.IsValid() {
f.SetString(f.Interface().(string) + "2")
}
if f := v.FieldByName("Age"); f.IsValid() {
f.SetInt(f.Int() + 2)
}
if f := v.FieldByName("Marks"); f.IsValid() {
f.Set(reflect.ValueOf(append(f.Interface().([]int), 2)))
}
if f := v.FieldByName("Invalid"); f.IsValid() {
f.Set(reflect.ValueOf(append(f.Interface().([]int), 2)))
}
}
Testing it:
d := &Data{
Name: "Bob",
Age: 22,
Marks: []int{5, 4, 3},
}
fmt.Printf("%+v\n", d)
appendCustomData(d)
fmt.Printf("%+v\n", d)
Output (try it on the Go Playground):
&{Name:Bob Age:22 Marks:[5 4 3]}
&{Name:Bob2 Age:24 Marks:[5 4 3 2]}
Update:
To answer your edited question: there is no difference when the value passed is a struct that embeds another struct. But the value wrapped in the interface{} still must be a pointer.
Example appendCustomData() that appends content to pageStruct.TemplateData.HeaderCSS:
func appendCustomData(d interface{}) {
v := reflect.ValueOf(d).Elem()
if f := v.FieldByName("TemplateData"); f.IsValid() {
if f = f.FieldByName("HeaderCSS"); f.IsValid() {
f.Set(reflect.ValueOf(f.Interface().(template.HTML) + "+new"))
}
}
}
Testing it:
ps := &pageStruct{
TemplateData: TemplateData{
HeaderCSS: template.HTML("old"),
},
}
fmt.Printf("%+v\n", ps)
appendCustomData(ps)
fmt.Printf("%+v\n", ps)
Output (try it on the Go Playground):
&{TemplateData:{FooterJS: HeaderJS: HeaderCSS:old} Form:}
&{TemplateData:{FooterJS: HeaderJS: HeaderCSS:old+new} Form:}

Pass by reference nested structures through reflection

type Client struct {
Id int
Age int
PrimaryContact Contact
Name string
}
type Contact struct {
Id int
ClientId int
IsPrimary bool
Email string
}
The above is a sample code; what I am trying to achieve is the following:
- loop through all Client struct fields using reflection
- for each "primitive" field set a default value using reflection
- for each struct field use recursion to apply the above steps
The issue is that when PrimaryContact field is introspected and when I am trying to set a value for any of its fields I end up with the following panic:
reflect.Value.Set using unaddressable value
The reason if I am not mistaken is that PrimaryContact is passed by value and not by reference so when I would call Set method on any of its fields it would change fields values on the copy and not on the actual argument. How can I overcome this issue? How I could pass PrimaryContact field to my method by reference using reflection?
I saw it as a fun exercise to practice reflection.
Two pointers though:
In order to set field values of a struct, you must pass it as a pointer
To get the pointer value of a struct field, use Value.Addr()
Working solution:
package main
import (
"fmt"
"reflect"
"errors"
)
type Client struct {
Id int
Age int
PrimaryContact Contact
Name string
}
type Contact struct {
Id int
ClientId int
IsPrimary bool
Email string
}
func SetDefault(s interface{}) error {
return setDefaultValue(reflect.ValueOf(s))
}
func setDefaultValue(v reflect.Value) error {
if v.Kind() != reflect.Ptr {
return errors.New("Not a pointer value")
}
v = reflect.Indirect(v)
switch v.Kind() {
case reflect.Int:
v.SetInt(42)
case reflect.String:
v.SetString("Foo")
case reflect.Bool:
v.SetBool(true)
case reflect.Struct:
// Iterate over the struct fields
for i := 0; i < v.NumField(); i++ {
err := setDefaultValue(v.Field(i).Addr())
if err != nil {
return err
}
}
default:
return errors.New("Unsupported kind: " + v.Kind().String())
}
return nil
}
func main() {
a := Client{}
err := SetDefault(&a)
if err != nil {
fmt.Println("Error: ", err)
} else {
fmt.Printf("%+v\n", a)
}
}
Output:
{Id:42 Age:42 PrimaryContact:{Id:42 ClientId:42 IsPrimary:true Email:Foo} Name:Foo}
Playground: http://play.golang.org/p/-Mpnb7o4vl
I think you just need to use value.Addr(), which gives you a reference to the Contact. Full example is here.
func main() {
x := Client{PrimaryContact:Contact{}}
v := reflect.ValueOf(&x)
fmt.Println("v type:", v.Type(), ", kind:", v.Kind())
f := v.Elem().FieldByName("PrimaryContact")
fmt.Println("f type:", f.Type(), ", kind:", f.Kind())
p := f.Addr()
fmt.Println("p type:", p.Type(), ", kind:", p.Kind())
p.Elem().FieldByName("Id").SetInt(1)
fmt.Println("Contact Id:", x.PrimaryContact.Id)
}`
Output:
v type: *main.Client , kind: ptr
f type: main.Contact , kind: struct
p type: *main.Contact , kind: ptr
Contact Id: 1

function for converting a struct to map in Golang

I want to convert a struct to map in Golang. It would also be nice if I could use the JSON tags as keys in the created map (otherwise defaulting to field name).
Edit Dec 14, 2020
Since structs repo was archived, you can use mapstructure instead.
Edit TL;DR version, Jun 15, 2015
If you want the fast solution for converting a structure to map, see the accepted answer, upvote it and use that package.
Happy coding! :)
Original Post
So far I have this function, I am using the reflect package but I don't understand well how to use the package, please bear with me.
func ConvertToMap(model interface{}) bson.M {
ret := bson.M{}
modelReflect := reflect.ValueOf(model)
if modelReflect.Kind() == reflect.Ptr {
modelReflect = modelReflect.Elem()
}
modelRefType := modelReflect.Type()
fieldsCount := modelReflect.NumField()
var fieldData interface{}
for i := 0; i < fieldsCount; i++ {
field := modelReflect.Field(i)
switch field.Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
fieldData = ConvertToMap(field.Interface())
default:
fieldData = field.Interface()
}
ret[modelRefType.Field(i).Name] = fieldData
}
return ret
}
Also I looked at JSON package source code, because it should contain my needed implementation (or parts of it) but don't understand too much.
I also had need for something like this. I was using an internal package which was converting a struct to a map. I decided to open source it with other struct based high level functions. Have a look:
https://github.com/fatih/structs
It has support for:
Convert struct to a map
Extract the fields of a struct to a []string
Extract the values of a struct to a []values
Check if a struct is initialized or not
Check if a passed interface is a struct or a pointer to struct
You can see some examples here: http://godoc.org/github.com/fatih/structs#pkg-examples
For example converting a struct to a map is a simple:
type Server struct {
Name string
ID int32
Enabled bool
}
s := &Server{
Name: "gopher",
ID: 123456,
Enabled: true,
}
// => {"Name":"gopher", "ID":123456, "Enabled":true}
m := structs.Map(s)
The structs package has support for anonymous (embedded) fields and nested structs. The package provides to filter certain fields via field tags.
From struct to map[string]interface{}
package main
import (
"fmt"
"encoding/json"
)
type MyData struct {
One int
Two string
Three int
}
func main() {
in := &MyData{One: 1, Two: "second"}
var inInterface map[string]interface{}
inrec, _ := json.Marshal(in)
json.Unmarshal(inrec, &inInterface)
// iterate through inrecs
for field, val := range inInterface {
fmt.Println("KV Pair: ", field, val)
}
}
go playground here
Here is a function I've written in the past to convert a struct to a map, using tags as keys
// ToMap converts a struct to a map using the struct's tags.
//
// ToMap uses tags on struct fields to decide which fields to add to the
// returned map.
func ToMap(in interface{}, tag string) (map[string]interface{}, error){
out := make(map[string]interface{})
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
// we only accept structs
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("ToMap only accepts structs; got %T", v)
}
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
// gets us a StructField
fi := typ.Field(i)
if tagv := fi.Tag.Get(tag); tagv != "" {
// set key of map to value in struct field
out[tagv] = v.Field(i).Interface()
}
}
return out, nil
}
Runnable example here.
Note, if you have multiple fields with the same tag value, then you will obviously not be able to store them all within a map. It might be prudent to return an error if that happens.
I like the importable package for the accepted answer, but it does not translate my json aliases. Most of my projects have a helper function/class that I import.
Here is a function that solves my specific problem.
// Converts a struct to a map while maintaining the json alias as keys
func StructToMap(obj interface{}) (newMap map[string]interface{}, err error) {
data, err := json.Marshal(obj) // Convert to a json string
if err != nil {
return
}
err = json.Unmarshal(data, &newMap) // Convert to a map
return
}
And in the main, this is how it would be called...
package main
import (
"fmt"
"encoding/json"
"github.com/fatih/structs"
)
type MyStructObject struct {
Email string `json:"email_address"`
}
func main() {
obj := &MyStructObject{Email: "test#test.com"}
// My solution
fmt.Println(StructToMap(obj)) // prints {"email_address": "test#test.com"}
// The currently accepted solution
fmt.Println(structs.Map(obj)) // prints {"Email": "test#test.com"}
}
package main
import (
"fmt"
"reflect"
)
type bill struct {
N1 int
N2 string
n3 string
}
func main() {
a := bill{4, "dhfthf", "fdgdf"}
v := reflect.ValueOf(a)
values := make(map[string]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
if v.Field(i).CanInterface() {
values[v.Type().Field(i).Name] = v.Field(i).Interface()
} else {
fmt.Printf("sorry you have a unexported field (lower case) value you are trying to sneak past. I will not allow it: %v\n", v.Type().Field(i).Name)
}
}
fmt.Println(values)
passObject(&values)
}
func passObject(v1 *map[string]interface{}) {
fmt.Println("yoyo")
}
I'm a bit late but I needed this kind of feature so I wrote this. Can resolve nested structs. By default, uses field names but can also use custom tags. A side effect is that if you set the tagTitle const to json, you could use the json tags you already have.
package main
import (
"fmt"
"reflect"
)
func StructToMap(val interface{}) map[string]interface{} {
//The name of the tag you will use for fields of struct
const tagTitle = "kelvin"
var data map[string]interface{} = make(map[string]interface{})
varType := reflect.TypeOf(val)
if varType.Kind() != reflect.Struct {
// Provided value is not an interface, do what you will with that here
fmt.Println("Not a struct")
return nil
}
value := reflect.ValueOf(val)
for i := 0; i < varType.NumField(); i++ {
if !value.Field(i).CanInterface() {
//Skip unexported fields
continue
}
tag, ok := varType.Field(i).Tag.Lookup(tagTitle)
var fieldName string
if ok && len(tag) > 0 {
fieldName = tag
} else {
fieldName = varType.Field(i).Name
}
if varType.Field(i).Type.Kind() != reflect.Struct {
data[fieldName] = value.Field(i).Interface()
} else {
data[fieldName] = StructToMap(value.Field(i).Interface())
}
}
return data
}
map := Structpb.AsMap()
// map is the map[string]interface{}

Resources