Проверьте, существует ли ключ в нескольких картах в одном условии

Мне нужно проверить, существует ли тот же ключ на двух картах:

if v1, ok1 := map1["aaa"]; ok1 {
 ...
}
if v2, ok2 := map2["aaa"]; ok2 {
 ...
}

Можно ли объединить эти два условия в один? Мне удалось сделать что-то вроде этого:

v1, ok1 := map1["aaa"]
v2, ok2 := map2["aaa"]
if ok1 && ok2 {
 ...
}

но мне любопытно, можно ли это сделать (назначение и проверка) в одном условии if.

Ответ 1

Нет, это невозможно. Spec: Индексные выражения:

Индексное выражение на карте a типа map[K]V, используемое в assignment или инициализации специальной формы

v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]

дает дополнительное нетипизированное логическое значение. Значение ok равно true, если ключ x присутствует на карте, а false в противном случае.

Таким образом, вы можете использовать специальную форму v, ok := m[k], только если ничего не назначено.

Однако, если вы не используете нулевое значение для типа значения карты, вы можете выполнить проверку, используя простой кортеж-назначение; не используя специальную форму, кроме 2 простых индексных выражений.

Например, если ваш тип значения представляет собой некоторый тип интерфейса (например, interface{}), и вы знаете, что не используете значение nil, вы можете сделать следующее:

if v1, v2 := m1["aaa"], m2["aaa"]; v1 != nil && v2 != nil {
    fmt.Printf("Both map contains key '%s': %v, %v\n", "aaa", v1, v2)
}

Конечно, с помощью вспомогательной функции вы можете сделать это за один шаг:

func idx(m1, m2 map[string]interface{}, k string) (
    v1, v2 interface{}, ok1, ok2 bool) {

    v1, ok1 = m1[k]
    v2, ok2 = m2[k]
    return
}

Используя его:

if v1, v2, ok1, ok2 := idx(m1, m2, "aaa"); ok1 && ok2 {
    fmt.Printf("Both map contains key '%s': %v, %v\n", "aaa", v1, v2)
}

Попробуйте примеры на Go Playground.

Ответ 2

вы также можете использовать переменный параметр (три точки) для проверки нескольких ключей:

// check map 1 and map2 is null or not
func checkMap(m1, m2 map[string]interface{}, keys ...string) []bool {
    var isExist []bool

    for key := range keys {
        //checking value from map 1
        _, ok := m1[keys[key]]
        if ok {
            isExist = append(isExist, true) // append for the first time to avoid panic
        } else {
            isExist = append(isExist, false) // append for the first time to avoid panic
        }

        // checking value from map2
        _, ok = m2[keys[key]]
        if ok {
            isExist[key] = true
        } else {
            isExist[key] = false
        }
    }

    return isExist
}

И тогда вы можете проверить свои ключи таким образом:

result := checkMap(myMap, myMap2, "a", "b", "c", "d", "e", "f", "g")
fmt.Printf("result = %+v\n", result) // print the result

if result[0] {
    fmt.Println("key a exist in both map")
}

if result[1] {
    fmt.Println("key b exist in both map")
}