Types 在接口上迭代
我想创建一个函数,它接受一个映射或一个数组,并对每个项调用一个函数,该函数知道如何处理遇到的任何类型 这是我第一次失败的尝试。目前,当我在我的实际用例中运行它时,它总是说“啊哦!” 数组或映射可能包含许多不同的内容,因此无法尝试匹配所有可能的输入Types 在接口上迭代,types,go,Types,Go,我想创建一个函数,它接受一个映射或一个数组,并对每个项调用一个函数,该函数知道如何处理遇到的任何类型 这是我第一次失败的尝试。目前,当我在我的实际用例中运行它时,它总是说“啊哦!” 数组或映射可能包含许多不同的内容,因此无法尝试匹配所有可能的输入 否则,是否有一种方法可以在Go中迭代数组或映射,而不知道它是什么?为了让您的示例发挥作用,您需要构建一个接口{}(或映射)数组,以便检测正确的类型: // This won't work, as the .(type) would be []S som
否则,是否有一种方法可以在Go中迭代数组或映射,而不知道它是什么?为了让您的示例发挥作用,您需要构建一个
接口{}
(或映射)数组,以便检测正确的类型:
// This won't work, as the .(type) would be []S
someS := []S{S{}}
DoTheThingToAllTheThings(someS)
// This will: it will go in case []interface{}:
someSI := make([]interface{}, len(someS))
for i, s := range someS {
someSI[i] = s
}
DoTheThingToAllTheThings(someSI)
见a
但这意味着您仍然可以在DoTheThing
函数中使用接口{}
。这里没有真正的泛型,正如我在“.”中提到的那样。函数
fmt.Printf(“%v\n”,数据\u接口)
正是您想要的。它将打印传递给它的整个地图或数组
您可以在此处找到实现:
printArg
末尾附近的行是键:
return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth
它使用“reflect”包:查询参数的类型。在p.printReflectValue
中,您将看到处理贴图和结构的两种情况。然后,它通过printValue
使用递归来管理内容
下面是一段代码,它获取结构的反射,然后将其转换回另一个正确类型的变量。您不能使用此选项从一个任意类型更改为另一个,在go中,在不使用反射的情况下从一个类型转换为另一个类型是合法的
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")
}
}
主程序包
进口(
“fmt”
“反映”
)
输入播放器字符串
类型板结构{
Tboard[9]字符串
玩家1玩家
玩家2玩家
}
//忽略此函数内容,我从其他地方获取了它。
func makeBoard()*板{
b:=&Board{Tboard:[9]字符串{}
对于x:=0;x9
fmt.Printf(“内容:%v\n”,b)
fmt.Printf(“语法:%#v\n”,b)
fmt.Printf(“类型:%T\n”,b)
fmt.Println(“板:,b.T板)
返回b
}
func main(){
myBoard:=makeBoard()
v:=reflect.ValueOf(*myBoard)//v的类型为Value
t:=v.Type()
fmt.Printf(“值:%v%T\n”,v,v)
fmt.Printf(“类型:%v%T\n”,T,T)
//这将是一个转变
如果t==reflect.TypeOf(*myBoard){
var b2板
b2=v.Interface()(Board)//将类型接口{}转换为类型Board
fmt.Printf(“v转换回:%#v\n”,b2)
}否则{
fmt.Printf(“未识别t”)
}
}
请注意,v
的类型是main.Board
,是完整的包名,而不是Board
。
任何要对其执行此操作的结构都必须具有导出类型,以便反射正常工作。太好了,这解决了我的大部分问题。现在我可以将一个
reflect.Value
传递到DoTheThing
函数中。但是在DoTheThing
中,我将如何将传递的reflect.Value
转换回它所期望的底层*MyRandompledStructType
?下面基于reflect
的解决方案将起作用,但是,如果可能的话,惯用的做法就是在调用站点写出循环。请注意:这是我在堆栈溢出问题上的第11000个答案(在72个月内),在事件发生后不到4个月。在那之前。。。
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")
}
}