Creating Slice from Reflected Type
Asked Answered
A

2

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?

Adon answered 7/8, 2016 at 21:54 Comment(1)
This is acutally more along the lines of what I was looking for. #25385140Adon
B
16

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

Berniecebernier answered 7/8, 2016 at 22:23 Comment(2)
However, elemSlice is still of the type reflect.Value How to get this to the actual slice type it is ?Pelf
elemSlice.Interface().([]TestStruct)Hostage
R
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}]
}
Ruby answered 7/8, 2016 at 22:24 Comment(1)
So for #3, you still need to write out the actual word "TestStruct".Langur

© 2022 - 2024 — McMap. All rights reserved.