func可以采用多种类型

时间:2017-12-27 22:59:55

标签: go types syntax

我正在尝试创建一个辅助函数,它将使用字符串键获取一个映射并返回一个映射键片段。

问题在于我希望函数不关心地图值的类型。

例如:

stringStringMap := map[string]string{
    "one": "first",
    "two": "second"
}

mapKeys(stringStringMap) // ["one", "two"]

stringIntMap := map[string]int{
    "one": 1,
    "two": 2,
}

mapKeys(strinIntMap) // ["one", "two"]

似乎解决这个问题的唯一方法是创建两个类似的帮助器。像这样:

func mapKeys(m map[string]string) []string {
    ...
}

func mapKeys2(m map[string]int) []string {
    ...
}

但这看起来很难看。我正在尝试创建这个辅助函数吗?如果没有,那么写这个时我应该遵循一个很好的约定吗?

3 个答案:

答案 0 :(得分:3)

解决此问题的方法是使用" interface {}"在创建地图时,然后在方法中使用type switch语句,即

func mapKeys(m map[string]interface{}) []string {
    for k,v := range m {
        switch a := v.(type) {
        case int:
          ... do int stuff
        case string:
          ... do string stuff
        }
    }
}

答案 1 :(得分:2)

Go没有用户指定的通用参数类型,因此您所描述的内容必须通过以下方式完成:

  1. 接受您希望支持的不同类型的单独功能,或
  2. 接受空接口(require)并使用reflection
  3. 的函数

    以下是第二种方法的示例实现:

    interface{}

答案 2 :(得分:2)

还有第三个选项尚未提及,那就是使用类型开关。如果您知道要将可管理数量的类型传递给函数,这可能是一个不错的选择。它会像这样工作:

func Keys(m interface{}) ([]string, error) {
    switch t := m.(type) {
    case map[string]string:
        keys := make([]string, 0, len(t))
        for key := range t {
            keys = append(keys, key)
        }
        return keys, nil
    case map[string]int:
        keys := make([]string, 0, len(t))
        for key := range t {
            keys = append(keys, key)
        }
        return keys, nil
    default:
        return nil, fmt.Errorf("unknown map type: %T", m)
    }
}

这仍然会给你一堆看似重复的代码,但至少它只是在一个函数名后面,而且它比反射更有效。