Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go:一个使用不同类型值的映射的函数_Go - Fatal编程技术网

Go:一个使用不同类型值的映射的函数

Go:一个使用不同类型值的映射的函数,go,Go,在我的代码中,我需要一个函数,该函数将从映射返回键的有序切片 m1 := make(map[string]string) m2 := make(map[string]int) 现在我需要调用一个传递两种类型映射的函数: keys1 := sortedKeys(m1) keys2 := sortedKeys(m1) 问题:我必须编写两个函数,因为该函数应该使用两种不同类型的映射。同时,函数体在两种情况下都是相同的 问题:如何对两个映射使用单个实现?或者有没有其他优雅的方法来解决这个问题 我的第

在我的代码中,我需要一个函数,该函数将从映射返回键的有序切片

m1 := make(map[string]string)
m2 := make(map[string]int)
现在我需要调用一个传递两种类型映射的函数:

keys1 := sortedKeys(m1)
keys2 := sortedKeys(m1)
问题:我必须编写两个函数,因为该函数应该使用两种不同类型的映射。同时,函数体在两种情况下都是相同的

问题:如何对两个映射使用单个实现?或者有没有其他优雅的方法来解决这个问题

我的第一个想法是使用
map[string]interface{}
作为参数类型,但不能将
map[string]string
map[string]int
分配给它

我的代码:

func sortedKeys(m map[string]string) []string {
    var keys []string
    for key := range m {
        keys = append(keys, key)
    }
    sort.Strings(keys)
    return keys
}

我必须重复相同的代码,但是对于
map[string]int

您可以使用接口{}和反射来实现这一点

您可以为同一个函数编写两个函数,但它是不可伸缩的,例如,您现在支持字符串和int,但希望将来支持int64、float64、bool或struct。使用map[string]接口{}和反射实现一个公共函数是一个不错的选择

建议代码:

package main

import (
    "fmt"
    "reflect"
)

func main() {
    m1 := make(map[string]string)
    m2 := make(map[string]int)

    m1["a"] = "b"
    m1["b"] = "c"

    m2["a"] = 1
    m2["b"] = 2

    fmt.Println(sortedKeys(m1))
    fmt.Println(sortedKeys(m2))
}

// Returns slice of values in the type which is sent to it
func sortedKeys(m interface{}) interface{} {

    if m == nil {
       return nil
    }

    if reflect.TypeOf(m).Kind() != reflect.Map {
        return nil
    }

    mapIter := reflect.ValueOf(m).MapRange()
    mapVal := reflect.ValueOf(m).Interface()

    typ := reflect.TypeOf(mapVal).Elem()
    outputSlice := reflect.MakeSlice(reflect.SliceOf(typ), 0, 0)


    for mapIter.Next() {
       outputSlice = reflect.Append(outputSlice, mapIter.Value())
    }


    return outputSlice.Interface()


}

输出:

[丙]

[12]


编写两个函数。其实很简单。您甚至可以编写三个函数。在开始第四版之前:考虑切换到反射。@ SashaShpota也许会很棒,但这是不可能的。本质上,您似乎在问是否可以只指定“类型的一半”,例如
map[string]
,或
map[string]
,然后编写一个接受此类类型的函数,然后能够向其传递类型值,如
map[string]string
map[string]int
。在Go中,这根本不可能,要么编写两个函数,要么使用
接口{}
和反射。@mkopriva谢谢!“不可能”也是一个有效的答案:)我问这个问题是因为我在围棋方面没有经验,正在寻找更好的解决方案。“但仍然是8行代码”。那是个笑话,对吗?8行琐碎的代码实际上什么都不是。只需写两次就可以了。这在Go中是不可能的,因为Go不支持泛型。重复8行代码被认为是可以接受的。@shasha Spota:你能告诉我这个解决方案是否对你有效吗?如果是,你能接受这一正确答案吗。非常感谢。