迭代一个接口 [英] Iterate over an interface

查看:27
本文介绍了迭代一个接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个函数,它接受一个映射或一个数组,并迭代它,在每个项目上调用一个函数,该函数知道如何处理遇到的任何类型.

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!".

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
}

数组或映射可能包含许多不同的内容,因此尝试匹配所有可能的输入并不是一种选择.

The array or map could contain lots of different things so it isn't an option to try and match every possible input.

另外说明,有没有办法在不确切知道它是什么的情况下在 Go 中迭代数组或映射?

推荐答案

fmt.Printf("%v ", data_interface) 函数完全符合您的要求.它将打印传递给它的整个地图或数组.

The function fmt.Printf("%v ", data_interface) does exactly what you want. It will print the whole map or array passed to it.

你可以在这里找到实现:http://golang.org/src/pkg/fmt/print.go?h=printArg#L708

You can find the implementation here: http://golang.org/src/pkg/fmt/print.go?h=printArg#L708

靠近printArg结尾的那一行是关键:

The line near the end of printArg is key:

return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth

它正在使用reflect"包:http://golang.org/pkg/reflect/ 查询参数的类型.在 p.printReflectValue 里面:http://golang.org/src/pkg/fmt/print.go?h=printArg#L862 您将看到处理地图和结构的两种情况.然后通过printValue使用递归来管理内容.

It's using the "reflect" package: http://golang.org/pkg/reflect/ to query the type of the argument. Inside 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.

这里有一些代码,它获取结构的反射,然后将其转换回正确类型的另一个变量.你不能使用 this 从一种任意类型更改为另一种类型,在不使用反射的情况下将类型从一种类型转换为另一种类型必须是合法的.

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.

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
", len(b.Tboard)) // => 9

    fmt.Printf("Contents: %v
", b)
    fmt.Printf("Syntax: %#v
", b)
    fmt.Printf("Type: %T
", 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
", v, v)
    fmt.Printf("Type:  %v %T
", 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
", b2)
    } else {
        fmt.Printf("t is not recognized")
    }

}

注意v的类型是main.Board,完整的包名,而不是Board.您想要执行此操作的任何结构都必须具有导出类型才能使反射工作.

Notice that the type of 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.

这篇关于迭代一个接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆