Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create slice of struct using reflection?

Tags:

reflection

go

I need to create a slice of struct from its interface with reflection.

I used Reflection because do not see any other solution without using it.

Briefly, the function receives variadic values of Interface.

Then, with reflection creates slice and passes it into another function.

Reflection asks to type assertion

SliceVal.Interface().(SomeStructType)

But, I cannot use it.

Code in playground http://play.golang.org/p/EcQUfIlkTe

The code:

package main

import (
    "fmt"
    "reflect"
)

type Model interface {
    Hi()
}

type Order struct {
    H string
}

func (o Order) Hi() {
    fmt.Println("hello")
}

func Full(m []Order) []Order{
    o := append(m, Order{H:"Bonjour"}
    return o
}

func MakeSlices(models ...Model) {
    for _, m := range models {
        v := reflect.ValueOf(m)
        fmt.Println(v.Type())
        sliceType := reflect.SliceOf(v.Type())
        emptySlice := reflect.MakeSlice(sliceType, 1, 1)
        Full(emptySlice.Interface())
    }
}
func main() {
    MakeSlices(Order{})
}
like image 610
maksadbek Avatar asked Mar 10 '15 10:03

maksadbek


1 Answers

You're almost there. The problem is that you don't need to type-assert to the struct type, but to the slice type.

So instead of

SliceVal.Interface().(SomeStructType)

You should do:

SliceVal.Interface().([]SomeStructType)

And in your concrete example - just changing the following line makes your code work:

Full(emptySlice.Interface().([]Order))

Now, if you have many possible models you can do the following:

switch s := emptySlice.Interface().(type) {
case []Order:
    Full(s)
case []SomeOtherModel:
    FullForOtherModel(s)
// etc
}
like image 142
Not_a_Golfer Avatar answered Sep 23 '22 17:09

Not_a_Golfer