如何将多维切片[] interface {}转换为切片[] string?

时间:2019-01-22 04:23:30

标签: go slice converters

示例来源:

// source multidimensional slice
var source = []interface{}{
    "value1",
    "value2",
    1234,
    1234.1234,
    []int{222, 333},
    []float32{444.444, 555.555},
    []interface{}{555, "value4", []int{777, 888}}
}

目标:

// target []string
var target = []string{
    "value1",
    "value2",
    "1234",
    "1234.1234",
    "222",
    "333",
    "444.444",
    "555.555",
    "555",
    "value4",
    "777",
    "888"
}

我写了转换函数。但是在我看来,这很麻烦,并且无法涵盖所有​​可能的选择。你能告诉我,请问还有更优雅的决定吗?

// convert multidimensional slice []interface{} to slice []string
func convert(raw interface{}) (result []string) {
    switch raw.(type) {
    case []string:
        result = append(result, raw.([]string) ...)
    case []int:
        for _, elem := range raw.([]int) {
            result = append(result, convert(elem) ...)
        }
    case string, int, int8, int16, int32, int64, float32, float64, complex64, complex128:
        result = append(result, fmt.Sprintf("%v", raw))
    case []float32:
        for _, elem := range raw.([]float32) {
            result = append(result, convert(elem) ...)
        }
    case []rune:
        for _, elem := range raw.([]rune) {
            result = append(result, convert(elem) ...)
        }
    case []int8:
        for _, elem := range raw.([]int8) {
            result = append(result, convert(elem) ...)
        }
    case []int16:
        for _, elem := range raw.([]int16) {
            result = append(result, convert(elem) ...)
        }
    case []int64:
        for _, elem := range raw.([]int64) {
            result = append(result, convert(elem) ...)
        }
    case []float64:
        for _, elem := range raw.([]float64) {
            result = append(result, convert(elem) ...)
        }
    case []complex64:
        for _, elem := range raw.([]complex64) {
            result = append(result, convert(elem) ...)
        }
    case []complex128:
        for _, elem := range raw.([]complex128) {
            result = append(result, convert(elem) ...)
        }
    case []interface{}:
        for _, elem := range raw.([]interface{}) {
            result = append(result, convert(elem) ...)
        }
    case [][]interface{}:
        for _, elem := range raw.([][]interface{}) {
            result = append(result, convert(elem) ...)
        }
    default:
        fmt.Println(fmt.Sprintf("Unknown type %v", raw))
        os.Exit(1)
    }
    return result
}

1 个答案:

答案 0 :(得分:2)

使用反射包在几行代码中处理所有类型的切片:

func convert(dst []string, v reflect.Value) []string {
    // Drill down to the concrete value
    for v.Kind() == reflect.Interface {
        v = v.Elem()
    }

    if v.Kind() == reflect.Slice {
        // Convert each element of the slice.
        for i := 0; i < v.Len(); i++ {
            dst = convert(dst, v.Index(i))
        }
    } else {
        // Convert value to string and append to result.
        dst = append(dst, fmt.Sprint(v.Interface()))
    }
    return dst
}

这样称呼它:

stringSlice := convert(nil, reflect.ValueOf(source))

Run it on the Playground