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

Interface go中能够包含任何类型的数据结构是什么?,interface,go,Interface,Go,参考文献 这是一个演示 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{&qu

参考文献

这是一个演示

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:无法使用一个(类型映射[string][]string)作为映射_存在的参数中的类型映射[string]接口{}

./main.go:19:无法使用两个(类型映射[string]string)作为映射_存在的参数中的类型映射[string]接口{}


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

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

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

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

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

确实,
interface{}
有点像C的
void*
,但是您不能隐式地将
map[string]字符串
转换为
map[string]interface{}
。关键是在声明中将
map
对象定义为
map[string]接口{}
对象。不幸的是,您无法为这样的映射分配新的值,因为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!
}

确实,
interface{}
有点像C的
void*
,但是您不能隐式地将
map[string]字符串
转换为
map[string]interface{}
。关键是在声明中将
map
对象定义为
map[string]接口{}
对象。不幸的是,您无法为这样的映射分配新的值,因为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!
}