Как создать условные выражения для функций, которые принимают интерфейс {} в go? - PullRequest
0 голосов
/ 08 июля 2019

Я пишу функцию, которая предназначена для приема строк или фрагментов в процессе. Однако, когда я печатаю свои параметры как interface{}, я не могу выполнять действия с этими переменными, даже если они находятся внутри условного выражения, проверяющего тип.

Может ли компилятор сделать вывод, что моя локальная переменная должна иметь тип Slice один раз внутри моего if блока? Как я могу выполнить цикл for над Slice после того, как я точно знаю, что это слайс?

func createFields(keys interface{}, values interface{}) ([]map[string]interface{}, error) {
    fields := make([]map[string]interface{}, 1, 1)
    if reflect.TypeOf(keys).Kind() == reflect.Slice && reflect.TypeOf(values).Kind() == reflect.Slice {
        if len(keys.([]interface{})) != len(values.([]interface{})) {
            return fields, errors.New("The number of keys and values must match")
        }
        // How can I loop over this slice inside the if block?
        for i, key := range keys.([]interface{}) {
            item := map[string]string{
                "fieldID":    keys[i], // ERROR: invalid operation: keys[i] (type interface {} does not support indexing)
                "fieldValue": values[i],
            }
            fields.append(item)// ERROR: fields.append undefined (type []map[string]interface {} has no field or method append)
        }

        return fields, _

    }

    if reflect.TypeOf(keys).Kind() == reflect.String && reflect.Typeof(values).Kind() == reflect.String {
        item := map[string]string{
            "fieldID":    keys,
            "fieldValue": values,
        }
        fields.append(item)
        return fields, _
    }

    return fields, errors.New("Parameter types did not match")
}

1 Ответ

4 голосов
/ 08 июля 2019

Используйте утверждения типа, такие как

keySlice := keys.([]interface{})
valSlice := values.([]interface{})

и работайте с ними с этого момента. Вы даже можете исключить использование reflect, например:

keySlice, keysIsSlice := keys.([]interface{})
valSlice, valuesIsSlice := values.([]interface{})

if (keysIsSlice && valuesIsSlice) {
    // work with keySlice, valSlice
    return
}

keyString, keysIsString := keys.(string)
valString, valuesIsString := values.(string)

if (keysIsString && valuesIsString) {
    // work with keyString, valString
    return
}

return errors.New("types don't match")

Или вы можете структурировать все как переключатели типа:

switch k := keys.(type) {
case []interface{}:
    switch v := values.(type) {
    case []interface{}:
        // work with k and v as slices
    default:
        // mismatch error
    }
case string:
    switch v := values.(type) {
    case string:
        // work with k and v as strings
    default:
        // mismatch error
    }
default:
    // unknown types error
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...