Como se señaló en otras respuestas, la solución general es usar una expresión de índice en una asignación de la forma especial:
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
Esto es lindo y limpio. Sin embargo, tiene algunas restricciones: debe ser una asignación de forma especial. La expresión del lado derecho debe ser solo la expresión del índice del mapa, y la lista de expresiones del lado izquierdo debe contener exactamente 2 operandos, el primero al que se puede asignar el tipo de valor y el segundo al que bool
se puede asignar un valor. El primer valor del resultado de esta forma especial será el valor asociado con la clave, y el segundo valor indicará si realmente hay una entrada en el mapa con la clave dada (si la clave existe en el mapa). La lista de expresiones del lado izquierdo también puede contener el identificador en blanco si uno de los resultados no es necesario.
Es importante saber que si el valor del mapa indexado es nil
o no contiene la clave, la expresión del índice se evalúa como el valor cero del tipo de valor del mapa. Así por ejemplo:
m := map[int]string{}
s := m[1] // s will be the empty string ""
var m2 map[int]float64 // m2 is nil!
f := m2[2] // f will be 0.0
fmt.Printf("%q %f", s, f) // Prints: "" 0.000000
Pruébalo en Go Playground .
Entonces, si sabemos que no usamos el valor cero en nuestro mapa, podemos aprovechar esto.
Por ejemplo, si el tipo de valor es string
, y sabemos que nunca almacenamos entradas en el mapa donde el valor es la cadena vacía (valor cero para el string
tipo), también podemos probar si la clave está en el mapa comparando los valores no especiales forma de (resultado de) la expresión de índice al valor cero:
m := map[int]string{
0: "zero",
1: "one",
}
fmt.Printf("Key 0 exists: %t\nKey 1 exists: %t\nKey 2 exists: %t",
m[0] != "", m[1] != "", m[2] != "")
Salida (pruébalo en Go Playground ):
Key 0 exists: true
Key 1 exists: true
Key 2 exists: false
En la práctica, hay muchos casos en los que no almacenamos el valor de valor cero en el mapa, por lo que puede usarse con bastante frecuencia. Por ejemplo, las interfaces y los tipos de función tienen un valor cero nil
, que a menudo no almacenamos en los mapas. Por lo tanto, se puede probar si una clave está en el mapa comparándola con nil
.
El uso de esta "técnica" también tiene otra ventaja: puede verificar la existencia de varias claves de manera compacta (no puede hacerlo con el formulario especial "coma ok"). Más sobre esto: compruebe si la clave existe en varios mapas en una condición
Obtener el valor cero del tipo de valor cuando se indexa con una clave no existente también nos permite usar mapas con bool
valores convenientemente como conjuntos . Por ejemplo:
set := map[string]bool{
"one": true,
"two": true,
}
fmt.Println("Contains 'one':", set["one"])
if set["two"] {
fmt.Println("'two' is in the set")
}
if !set["three"] {
fmt.Println("'three' is not in the set")
}
Sale (pruébalo en Go Playground ):
Contains 'one': true
'two' is in the set
'three' is not in the set
Ver relacionado: ¿Cómo puedo crear una matriz que contenga cadenas únicas?