迭代接口 [英] Iterate over an interface
问题描述
我想创建一个函数,该函数可以接受映射或任何其他数组,并遍历它调用每个项目上的函数,该函数知道如何处理遇到的任何类型。
这是我第一次失败的尝试。目前,当我在我的真实使用案例中运行它时,它总是说呃哦!。
$ func DoTheThingToAllTheThings(data_interface interface {} )int {
var numThings int
switch data:= data_interface。(type){
case map [interface {}] interface {}:
numThings = len (数据)
用于索引,item:=范围数据{
DoTheThing(index,item)
}
case [] interface {}:
numThings = len数据)
用于索引,项目:=范围数据{
DoTheThing(索引,项目)
}
默认值:
fmt.Println(呃哦!)
}
return numThings
}
数组或映射可能包含很多不同的东西,因此它不是一种尝试匹配每个可能的输入的选项。
换句话说,有没有办法在Go中迭代数组或映射而不知道它到底是什么?
你可以在这里找到实现: 接近 它使用反射包: http://golang.org/pkg/reflect/ 来查询参数的类型。在 这里有一点代码ta kes是一个结构的反射,然后把它变成另一个正确类型的变量。你不能从一个任意类型转换到另一个类型,使用它必须是合法的,不必使用反射就可以将类型从一个类型转换到另一个类型。 请注意, I want to create a function that takes either a map or an array of whatever and iterates over it calling a function on each item which knows what to do with whatever types it encounters. Here's my first failed attempt. Currently when I run it in my real use case it always says "uh oh!". The array or map could contain lots of different things so it isn't an option to try and match every possible input. Stated otherwise, is there a way to iterate over an array or map in Go without knowing exactly what it is? The function You can find the implementation here: http://golang.org/src/pkg/fmt/print.go?h=printArg#L708 The line near the end of It's using the "reflect" package: http://golang.org/pkg/reflect/ to query the type of the argument. Inside Here's a bit of code that takes the reflection of a structure and then turns it back into another variable of the right type. You can't change from one arbitrary type to another using this, it has to be legal in go to cast the types from one to another without using reflection. Notice that the type of 这篇关于迭代接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
printArg
结尾的行是关键:
return p.printReflectValue(reflect.ValueOf(arg),verb,plus,goSyntax,depth
p.printReflectValue
里面: http://golang.org/src/pkg/fmt/print.go?h=printArg#L862 您将看到两种情况:处理地图和结构,然后通过 printValue
递归来管理内容。
包主
$ b $导入(
fmt
反映
)
类型播放器字符串
类型Board结构{
Tboard [9] string
Player1 Player $ b $ Player2 Player
}
//忽略此功能内容,我从其他地方抓起来。
func makeBoard()* Board {
b:=& Board {tboard:[9] string {}}
for x:= 0; x < LEN(b.Tboard); x ++ {
b.Tboard [x] =X
fmt.Println(b.Tboard [x])
}
b.Player1 =George
b.Player2 =Tim
fmt.Printf(Len:%v \ n,len(b.Tboard))// => 9
fmt.Printf(内容:%v \ n,b)
fmt.Printf(语法:%#v \ n,b)
fmt.Printf(Type:%T \\\
,b)
fmt.Println(Board:,b.Tboard)
return b
}
func main(){
myBoard:= makeBoard()
v:= reflect.ValueOf(* myBoard)// v的类型是Value
t:= v.Type ()
fmt.Printf(Value:%v%T \\\
,v,v)
fmt.Printf(Type:%v%T \\\
, t,t)
//如果t == reflect.TypeOf(* myBoard){
var b2 Board
b2将会是一个开关
= v.Interface()。(Board)//将类型interface {}转换为Board
fmt.Printf(v转换回:%#v \ n,b2)
} else {
fmt.Printf(t is not recognized)
}
}
v
的类型是 main.Board
名称,而不是电路板
。
您想要执行此操作的任何结构必须具有用于反射才能工作的导出类型。func DoTheThingToAllTheThings(data_interface interface{}) int {
var numThings int
switch data := data_interface.(type) {
case map[interface{}]interface{}:
numThings = len(data)
for index, item := range data {
DoTheThing(index, item)
}
case []interface{}:
numThings = len(data)
for index, item := range data {
DoTheThing(index, item)
}
default:
fmt.Println("uh oh!")
}
return numThings
}
fmt.Printf("%v\n", data_interface)
does exactly what you want. It will print the whole map or array passed to it.printArg
is key:return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth
p.printReflectValue
here: http://golang.org/src/pkg/fmt/print.go?h=printArg#L862 You will see the two cases where maps and structures are dealt with. It then uses recursion through printValue
to manage the contents.package main
import (
"fmt"
"reflect"
)
type Player string
type Board struct {
Tboard [9]string
Player1 Player
Player2 Player
}
// ignore this function contents, I grabbed it from elsewhere.
func makeBoard() *Board {
b := &Board{Tboard: [9]string{}}
for x := 0; x < len(b.Tboard); x++ {
b.Tboard[x] = "X"
fmt.Println(b.Tboard[x])
}
b.Player1 = "George"
b.Player2 = "Tim"
fmt.Printf("Len: %v\n", len(b.Tboard)) // => 9
fmt.Printf("Contents: %v\n", b)
fmt.Printf("Syntax: %#v\n", b)
fmt.Printf("Type: %T\n", b)
fmt.Println("Board:", b.Tboard)
return b
}
func main() {
myBoard := makeBoard()
v := reflect.ValueOf(*myBoard) // v is of type Value
t := v.Type()
fmt.Printf("Value: %v %T\n", v, v)
fmt.Printf("Type: %v %T\n", t, t)
// would be a switch
if t == reflect.TypeOf(*myBoard) {
var b2 Board
b2 = v.Interface().(Board) // cast the type interface{} into type Board
fmt.Printf("v converted back to: %#v\n", b2)
} else {
fmt.Printf("t is not recognized")
}
}
v
is main.Board
, the full package name, not Board
.
Any structure you want to do this to, must have an exported type for reflection to work.