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")
    }

}