1
votes

I have a general enough function for going through a map[string] and getting all keys:

i := 0
keys := make([]string, len(input))
for k := range input {
    keys[i] = k
    i++
}
return keys

My problem is I have two different inputs I want to throw in here, a map[string]MyStruct and map[string][][]float64. Whenever I've tried having the input to the func as map[string]interface{}, go resists all my attempts to try to cast the map[string]MyStruct as a map[string]interface{}. Is there a way I can do this without needing to have two functions, one with map[string]MyStruct as input, and one with map[string][][]float64? The contents of the map[string] don't matter at this point, because I'm just trying to get all the keys of them for use later in the code. This needs to be a function that's called; We're using Sonar, and it's set to refuse code duplication, so I can't have this code snippet duplicated.

1
Can you post the snippet where you try to "cast" it?Z. Kosanovic
"go resists all my attempts to try to cast..." -- Go doesn't support type casting at all. You're no doubt talking about a type conversion.Flimzy
@Z.Kosanovic basically trying things like variableName.(map[string]interface{}) (which doesn't work for obvious reasons) and even converting it to a pointer first, then declaring the pointer as a pointer to a map[string]interface{}. it's not like I can just say, int(variableName) them.SpaceMouse

1 Answers

3
votes

Until next Go version brings us generics there're several ways to cope with it.

  1. Duplicate code

  2. Use code generation - design some template and then go on build will fill it for you.

  3. Use interface{} as an input type of a function and then use reflection to guess which type was given to a function. I'm pretty sure in this case general code will be more complicated than 2 separate functions.

func getKeys(input interface{}) []string {
    switch inp := input.(type) {
    case map[string]MyStruct:
        keys := make([]string, 0, len(inp))
        for k := range inp {
            keys = append(keys, k)
        }
        return keys
    case map[string][]float64:
        ...
    default:
        fmt.Printf("I don't know about type %T!\n", v)
}

You cannot use input type map[string]interface{} to place map[string]string or map[string][]string go won't copy each value to new type. You may take the most general type interface{} and then cast it.