6

I am trying to create a slice from a reflect.Type. This is what I have so far.

package main

import (
    "fmt"
    "reflect"
)

type TestStruct struct {
    TestStr string
}

func main() {
    elemType := reflect.TypeOf(TestStruct{})

    elemSlice := reflect.New(reflect.SliceOf(elemType)).Interface()

    elemSlice = append(elemSlice, TestStruct{"Testing"})

    fmt.Printf("%+v\n", elemSlice)

}

However I get the following error and I'm not sure how to get around it without hardcoding a conversion to []TestStruct.

prog.go:17: first argument to append must be slice; have interface {}

Is there anyway to treat the returned interface as a slice without having to hardcode the conversion from interface{} to []TestStruct?

moesef
  • 4,641
  • 16
  • 51
  • 68
  • This is acutally more along the lines of what I was looking for. http://stackoverflow.com/questions/25384640/why-golang-reflect-makeslice-returns-un-addressable-value – moesef Aug 07 '16 at 23:12

2 Answers2

14

No, what you describe is not possible. Not type asserting the result of .Interface() limits what you can do. Your best chance is to continue to work with the reflect.Value value:

package main

import (
    "fmt"
    "reflect"
)

type TestStruct struct {
    TestStr string
}

func main() {
    elemType := reflect.TypeOf(TestStruct{})

    elemSlice := reflect.MakeSlice(reflect.SliceOf(elemType), 0, 10)

    elemSlice = reflect.Append(elemSlice, reflect.ValueOf(TestStruct{"Testing"}))

    fmt.Printf("%+v\n", elemSlice)

}

https://play.golang.org/p/WkGPjv0m_P

6

1- Using reflect.MakeSlice(reflect.SliceOf(elemType), 0, 10) and
reflect.Append(elemSlice, reflect.ValueOf(TestStruct{"Testing"})),
Like this working sample code:

package main

import "fmt"
import "reflect"

func main() {
    elemType := reflect.TypeOf(TestStruct{})
    elemSlice := reflect.MakeSlice(reflect.SliceOf(elemType), 0, 10)
    elemSlice = reflect.Append(elemSlice, reflect.ValueOf(TestStruct{"Testing"}))
    fmt.Println(elemSlice) // [{Testing}]

}

type TestStruct struct {
    TestStr string
}

2- Using reflect.New(reflect.SliceOf(elemType)).Elem() and
elemSlice = reflect.Append(elemSlice, reflect.ValueOf(TestStruct{"Testing"}))
Like this working sample code:

package main

import "fmt"
import "reflect"

type TestStruct struct {
    TestStr string
}

func main() {
    elemType := reflect.TypeOf(TestStruct{})
    elemSlice := reflect.New(reflect.SliceOf(elemType)).Elem()
    elemSlice = reflect.Append(elemSlice, reflect.ValueOf(TestStruct{"Testing"}))

    fmt.Printf("%+v\n", elemSlice) // [{TestStr:Testing}]
    fmt.Println(elemSlice)         // [{Testing}]
}

Output:

[{TestStr:Testing}]
[{Testing}]

3- If you need append, the only way is using s := elemSlice.([]TestStruct), like this working sample code:

package main

import "fmt"
import "reflect"

type TestStruct struct {
    TestStr string
}

func main() {
    elemType := reflect.TypeOf(TestStruct{})
    elemSlice := reflect.New(reflect.SliceOf(elemType)).Elem().Interface()

    s := elemSlice.([]TestStruct)
    s = append(s, TestStruct{"Testing"})

    fmt.Printf("%+v\n", elemSlice) // []
    fmt.Println(s)                 // [{Testing}]
}