How to return an array of unknown type in Golang?

Viewed 910

So I have a method which needs to return an array but I don't know what type of array to return. This type of array to return is down to the methods logic.

My method looks like this...

func (c Case) GetFrdValues(frdFieldKey string) (interface{}, error) {
    for _, singleFrd := range c.CaseDetails.GetCase().GetFrds() {
        if singleFrd.GetIdentifier().GetFieldKey() == frdFieldKey {
            switch singleFrd.GetValue().WhichType() {
            case casespb.Value_StringValue_case:
                return []string{singleFrd.GetValue().GetStringValue()}, nil
            case casespb.Value_NumberValue_case:
                return [1]float64{singleFrd.GetValue().GetNumberValue()}, nil
            case casespb.Value_BoolValue_case:
                return [1]bool{singleFrd.GetValue().GetBoolValue()}, nil
            case casespb.Value_NullValue_case:
                return []string{}, nil
            case casespb.Value_ListValue_case:
                return GetValuesFromFrdListValue(singleFrd.GetValue().GetListValue())
            default:
                return []string{}, nil
            }
        }
    }
    return []string{}, fmt.Errorf("Frd Value contains unsupported value type %v", frdFieldKey)
}

This works fine as it does still return an array of the values I want.

However I need to manipulate the returned array in a separate method. But cannot range over list (variable of type interface{}).

Therefore the returned value needs be like [] interface{}. However if I have it like that then I receive the error on my various return statements about.

cannot use ([]string literal) (value of type []string) as []interface{} value in return statement.

I can't find anything on stack overflow or the web about this, so any help would be greatly appreciated!

1 Answers

You can use reflection to loop over an array of unknown type. Here is a simplified example that simply prints out the elements of an array.

https://play.golang.org/p/5umonjVp90D

package main

import (
    "fmt"
    "reflect"
)

func main() {
    doSomething([]string{"a", "b", "c"})
    doSomething([]int{1, 2, 3})
}

func doSomething(item interface{}) {
    reflectType := reflect.TypeOf(item)
    if reflectType.Kind() == reflect.Ptr {
        reflectType = reflectType.Elem()
    }

    if reflectType.Kind() != reflect.Slice {
        fmt.Println("received item is not a slice")
        return
    }

    val := reflect.ValueOf(item)

    itemLength := val.Len()
    for i := 0; i < itemLength; i++ {
        fmt.Println(val.Index(i))
    }
}

Related