我在操场上有一些代码:sample code
我将一个二维字符串切片传递给一个函数测试,它可以接受可变参数,在test()中我可以得到第一个参数的底层类型,但是如何将它转换回它的底层类型呢?因为我必须迭代它的基础类型
我不喜欢硬编码:
if reflect.TypeOf(args[0]).String() == "[][]string" {
val := args[0].([][]string)
}
问题是,如果我知道它的类型字符串是“[] [] string”或其他东西,我该如何将其转换为类型?
我在这里发布完整代码,并添加一些评论:
package main
import (
"reflect"
"fmt"
)
func test(args ...interface{}) {
fmt.Println("type", reflect.TypeOf(args[0]))
// here will be a compile error, because args[0]'type now is interface{},
// not a slice, though it's underlying type is slice
for i, v := range args[0] {
}
// so, how could I convert args[0] to [][]string when I get its type
// string "[][]string" ?
// I know use type assertion is possible, but you must guess the possible
// type the args[0] will be.
// is there a way to do it from a type's string representation to the
// actual type?
// so I can write code like this:
// val := args[0].(reflect.TypeOf(args[0]).String()), which is very general
}
func main() {
arr := [][]string{{"asd", "sd", "rt"}, {"34","gf","gf"}}
test(arr)
}
答案 0 :(得分:3)
我不完全确定你想要达到的目标。
如果您传递[][]string
作为第一个参数,为了迭代它,您必须执行type assertion
或type switch
:
switch val := args[0].(type) {
case [][]string:
// Do what you want with val which is of type [][]string
}
您可以在Go规范中详细了解类型开关:http://golang.org/ref/spec#Switch_statements
如果您尝试将[] []字符串切片保持不变为test
:
test(arr...) // Attempt to pass the array unchanged.
这会失败。这是由于[] []字符串无法分配给[] interface {}。 Go规范声明:
如果最终参数可分配给切片类型[] T,则可能是 如果参数是,则传递未更改为... T参数的值 后跟....在这种情况下,不会创建新切片。
答案 1 :(得分:3)
ANisus的另一个变体回答:
package main
import "fmt"
func main() {
var x interface{} = [][]string{{"Hello"}, {"World", "!"}}
if y, ok := x.([][]string); ok {
fmt.Printf("%v", y)
}
}
http://play.golang.org/p/tGYbhzuUnr
否则,请使用反射包:
import (
"fmt"
"reflect"
)
func process(i interface{}) {
fmt.Printf("Processing %v\n", i)
if reflect.TypeOf(i).Kind() == reflect.Slice {
v := reflect.ValueOf(i)
for i := 0; i < v.Len(); i++ {
process(v.Index(i).Interface())
}
}
}
func main() {
var x = [][]string{{"Hello"}, {"World", "!"}}
var y = []int{2,3,5,7,9}
var z = 'H'
process(x)
process(y)
process(z)
}
答案 2 :(得分:1)
不能对类型断言使用动态值,所以
foo.(reflect.TypeOf(bar))
或类似的东西不起作用。这是因为类型不是一等公民 并且不能存储在变量中。
你总是要明确地写出你想要接口值的类型 通过使用类型断言或类型开关。