什么是能够包含任何类型的数据结构?

时间:2015-02-28 03:29:38

标签: interface go

参考Go equivalent of a void pointer in C

这是一个演示。

package main

import (
    "fmt"
)

func map_exist(map_val map[string]interface{}, key string) bool {
    _, ok := map_val[key]
    return ok
}

func main() {
    var one map[string][]string
    one["A"] = []string{"a", "b", "c"}
    fmt.Println(map_exist(one, "A"))

    var two map[string]string
    two["B"] = "a"
    fmt.Println(map_exist(two, "B"))
}

运行结果:

  

./ main.go:15:不能在map_exist的参数中使用一个(类型map [string] [] string)作为类型map [string] interface {}

     

./ main.go:19:不能在map_exist的参数中使用两个(类型map [string] string)作为类型map [string] interface {}

我找不到能够包含任何类型的数据结构。

2 个答案:

答案 0 :(得分:2)

Go不支持参数多态。你想要做的只是反射,这种反射比使用_,ok:= m [key]形式更长,更容易出错。通常你会这样写:

if _, ok := m[key]; ok {
    // do something conditionally.
}

答案 1 :(得分:2)

interface{}有点像C void *,但您不能隐含地将map[string]string转换为map[string]interface{} }}。关键是将map对象的声明定义为map[string]interface{}个对象。不幸的是,你无法为这样的地图分配新值,因为Go无法知道为每个实例分配多少内存。

func main() {
    one := map[string]interface{} {
        "A": []string{"a", "b", "c"},
    }
    fmt.Println(map_exist(one, "A"))

    two := map[string]interface{} {
        "B": "a",
    }
    fmt.Println(map_exist(two, "B"))
}

这有效,但它可能对您的预期用例不够有用。

另一种方法是定义通用映射接口,并确保为要支持的类型定义要使用的函数。基本上,您的目标是构建一个非常有用的库,以便您可以合理地将实现接口的工作卸载到库的用户。如果你可以声明一个默认函数或者只是一个宏来阻止复制粘贴会很好,但是我不知道这样的机制。

以下是使用界面的示例:

type GenericMap interface{
    ValueForKey(string) (interface{}, bool)
}

type SliceMap map[string][]string
type StringMap map[string]string
type VoidMap map[string]interface{}

func map_exist(map_val GenericMap, key string) bool {
    _, ok := map_val.ValueForKey(key)
    return ok
}

func (map_val SliceMap) ValueForKey(key string) (interface{}, bool) {
    val, ok := map_val[key]
    return val, ok
}

func (map_val StringMap) ValueForKey(key string) (interface{}, bool) {
    val, ok := map_val[key]
    return val, ok
}

func (map_val VoidMap) ValueForKey(key string) (interface{}, bool) {
    val, ok := map_val[key]
    return val, ok
}

func main() {
    one := SliceMap {
        "A": []string{"a", "b", "c"},
    }
    fmt.Println(map_exist(GenericMap(one), "A"))

    two := StringMap {
        "B": "a",
    }
    fmt.Println(map_exist(GenericMap(two), "B"))
}

最后,Go程序员倾向于选择一个简单,直接的解决方案而不是所有这些误导,所以最好的办法就是使用@Logiraptor提出的构造:

if _, ok := m[key]; ok {
    // You're ok!
}