首页 > golang []interface{} 的数组如何转换为 []string 的数组

golang []interface{} 的数组如何转换为 []string 的数组

package main
import (
    "fmt"
    "strings"
)

func getName(params ...interface{}) {
    aa := strings.Join([]string(params), '_')
    fmt.Println(aa)
}

func main() {
    getName("redis", "100","master")
}

看上面的代码,我想把传入的参数 params 用 "_" 连接,但是将 params 转成 []string 类型时失败了,请指教。

假如

假如 getName("redis", "100","master") 改为
 getName("redis", 100,"master")

编译没错误,但是运行时报错

panic: interface conversion: interface is int, not string

不太确定 type assertion 行不行。 params.([]string)


package main
import (
    "fmt"
    "strings"
)

func getName(params ...interface{}) {
    
    strArray := make([]string, len(params))
    for i, arg := range params { strArray[i] = arg.(string) }
    aa := strings.Join(strArray, "_")
    fmt.Println(aa)
}

func main() {
    getName("redis", "100","master")
}

interface slice 与 万能类型 empty interface 是不一样的,可以直接将任何类型的值传给万能类型,但是不能将任何类型的 slice 直接传给 interface slice,因为 interface slice 并不是万能类型,只是里面装的东西是万能类型,所以反过来你也不能直接将 interface slice 强制转换成特定类型的 slice

package main

import (
    "fmt"
    "strings"
)

func getName(params ...interface{}) {
    var paramSlice []string
    for _, param := range params {
        paramSlice = append(paramSlice, param.(string))
    }
    aa := strings.Join(paramSlice, "_") // Join 方法第2个参数是 string 而不是 rune
    fmt.Println(aa)
}

func main() {
    getName("redis", "100", "master")
}

万能类型(interface{})很神奇,就像 C 里面的 void*,但是C本身是一门不安全的语言,可以直接操纵原始的二进制位,所以 void* 是有必要的,但是这个东西对于强类型的Go是非常有害的和不安全的,它让你失去了静态强类型所带来的好处,很多本该在编译期就检查出来的类型问题,变成了运行时错误,我用过一些数据库方面的第三方库,就因为其内部使用了大量 interface{} 导致程序跑起来时不时有运行时类型错误非常头疼,另外大量使用 type assertion 代码是非常丑陋的。所以一定要尽量避免使用这个类型,这也是我泡 #go-nuts 频道时里面的大神给的建议

另附 golang wiki 上面对这个问题的解释 https://github.com/golang/go/wiki/InterfaceSlice golang wiki 是个好东西,有时间建议把内容都过一遍,可以让你少踩好多坑


package main

import (
    "fmt"
    "strconv"
    "strings"
)

func getName(params ...interface{}) {
    var paramSlice []string
    for _, param := range params {
        switch v := param.(type) {
        case string:
            paramSlice = append(paramSlice, v)
        case int:
            strV := strconv.FormatInt(int64(v), 10)
            paramSlice = append(paramSlice, strV)
        default:
            panic("params type not supported")
        }

    }

    res := strings.Join(paramSlice, "_")
    fmt.Println(res)
}

func main() {
    getName("redis", 100, "master")
}
【热门文章】
【热门文章】