En mi publicación anterior conocimos lo que es un array
y un slice
en el lenguaje de programación Go, en esta ocasión conoceremos lo que es un map
, un tipo de dato bastante interesante y versátil.
Maps
Un vector asociativo (también contenedor asociativo, mapa, mapeador, hash, diccionario, mapa finito, tabla de consulta) es un tipo abstracto de dato formado por una colección de claves únicas y una colección de valores, con una asociación uno a uno.
Fuente Wikipedia
Un map
es, básicamente, el equivalente a los diccionarios o arreglos asociativos en otros lenguajes de programación, es decir, almacenan parejas de clave y valor. Los valores dentro de estos pueden ser obtenidos o actualizados de manera semejante a como lo hacemos en un array
o slice
, solo que el indice no está limitado a un número entero y los valores no se encuentran ordenados. Veamos como declarar un map
.
var mapaUno map[string]int
mapaUno = make(map[string]int)
mapaUno["uno"] = 1
mapaUno["dos"] = 2
fmt.Println("mapaUno:", mapaUno) // mapaUno: map[uno:1 dos:2]
mapaDos := make(map[string]int)
mapaDos["uno"] = 1
mapaDos["dos"] = 2
fmt.Println("mapaDos:", mapaDos) // mapaDos: map[uno:1 dos:2]
mapaTres := map[string]int{"uno": 1, "dos": 2}
fmt.Println("mapaTres:", mapaTres) // mapaTres: map[uno:1 dos:2]
En los tres casos anteriores obtenemos el mismo resultado, un map
que contiene dos parejas clave-valor. Es importante mencionar, que en la primera declaración creamos un mapa con valor nil
; en ese caso, si intentamos agregar un nuevo valor obtendremos un error, por ese motivo asignamos un map
vacío haciendo uso de la función make
. Por lo que notarán que no hay mucha diferencia entre las variables mapaUno
y mapaDos
, simplemente nos ahorramos una linea gracias a la declaración corta. En el caso de mapaTres
usamos una asignación literal, pasando entre llaves los pares clave-valor. Ahora veamos algunas operaciones con mapas.
Agregando valores a un Map
mapa := map[string]int{"uno": 1, "dos": 2}
fmt.Println("mapa:", mapa) // mapa: map[uno:1 dos:2]
mapa["tres"] = 3
mapa["cuatro"] = 4
fmt.Println("mapa:", mapa) // mapa: map[uno:1 dos:2 tres:3 cuatro:4]
fmt.Println("El valor tres es:", mapa["tres"]) // El valor tres es: 3
fmt.Println("El valor cinco es:", mapa["cinco"]) // El valor cinco es: 0
Añadir nuevos valores al arreglo no suponen ninguna dificultad, tampoco acceder a un valor previamente almacenado, por medio de la notación de corchetes, usando la clave correspondiente tenemos acceso al valor. De igual forma, intentar acceder a un elemento por medio de una clave que no se encuentre presente en el mapa retorna el valor cero del tipo declarado en el mapa, siendo int
en este caso, el resultado de llamar al valor con la clave cinco
es 0
.
Modificando valores de un Map
mapa := map[string]int{"uno": 1, "dos": 2, "tres": 3, "cuatro": 4}
fmt.Println("mapa:", mapa) // mapa: map[uno:1 dos:2 tres:3 cuatro:4]
mapa["tres"] = 8
mapa["cuatro"] = 16
fmt.Println("mapa:", mapa) // mapa: map[uno:1 dos:2 tres:8 cuatro:16]
No creo que requiera mayor explicación, con la misma notación de corchetes con la que accedemos y agregamos valores podemos modificar valores. Ahora veamos como borrarlos.
mapa := map[string]int{"uno": 1, "dos": 2, "tres": 3, "cuatro": 4}
fmt.Println("mapa:", mapa) // mapa: map[uno:1 dos:2 tres:3 cuatro:4]
delete(mapa, "tres")
fmt.Println("mapa:", mapa) // mapa: map[uno:1 dos:2 cuatro:4]
La función delete
nos permite fácilmente eliminar elementos de un map
, sólo debemos pasar como primer argumento el map
y como segundo la clave correspondiente.
Más sobre los Maps
Es posible que surgieran algunas preguntas durante la lectura de las secciones anteriores, a mi me surgieron y me tocó investigar un poco, así que se los voy a compartir.
¿Puedo comprobar si un elemento se encuentra en el Mapa antes de acceder a él?
La respuesta es sí. Como dije anteriormente, si intentamos acceder a un valor del mapa con una clave que no esta presente en el mismo obtendremos el valor cero del tipo correspondiente, esto podría dar origen a errores difíciles de detectar dependiendo del caso, por lo que resulta útil poder comprobar si se encuentra o no en mapa antes de realizar alguna operación con él.
mapa := map[string]int{"uno": 1, "dos": 2, "tres": 3, "cuatro": 4}
if el, ok := mapa["cinco"]; ok {
fmt.Println("El valor de cinco es:", el)
}
Debido a que la clave cinco
no se encuentra presente en mapa
, el valor de la variable ok
es false
, por lo tanto, la variable el
(que almacena el valor correspondiente a la clave) no llega a imprimirse.
¿Sólo puedo almacenar valores de un tipo en un Mapa?
Como sabemos, el lenguaje Go es de tipado estático, por lo que la respuesta podría ser no, pero existe una forma, la conocí gracias al profesor Alexys Lozada de la comunidad Go en Español y es mediante el uso de interfaces. Aún no he tocado las interfaces en esta serie de publicaciones, pero prometo hacerlo pronto; por el momento pueden consideralas como otro tipo de dato y observar el siguiente ejemplo.
mapa := make(map[string]interface{})
mapa["primero"] = 4
mapa["segundo"] = false
mapa["tercero"] = "Steemit"
fmt.Println(mapa) // map[segundo:false tercero:Steemit primero:4]
Mapas literales multilinea
Esto no es realmente una duda, más bien algo que me pareció útil porque hasta el momento solo he realizado declaraciones de una linea y puede volverse difícil de leer.
tareasPendientes := map[string]string{
"primero": "Realizar post de punteros en Go",
"segundo": "Continuar el tutorial práctico de Echo",
"tercero": "Realizar post de interfaces en Go",
}
La coma al final del último elemento es obligatoria, a menos que se deje la llave de cierre al mismo nivel del último elemento, pero me gusta más la forma que les dejo en el ejemplo. Son libres de usar la que más les guste.
Recorrer mapas con un ciclo
Como deben saber si han estado siguiendo mis publicaciones anteriores, existen distintas variaciones del ciclo for
, me limitaré a mostrar la manera natural de recorrer un map
, es decir, el for-range.
package main
import (
"fmt"
)
func main() {
tareasPendientes := map[string]string{
"primero": "Realizar post de punteros en Go",
"segundo": "Continuar el tutorial práctico de Echo",
"tercero": "Realizar post de interfaces en Go",
}
for k, v := range tareasPendientes {
fmt.Println(k, "=>", v)
}
}
No les compartiré la salida de ese código, los invito a probarlo ustedes mismos, por tal motivo lo coloqué completo. Si no quieren instalar aún el compilador de Go pueden usar este playground, de cualquier forma, hagan pruebas, realicen modificaciones y no duden en compartir sus experiencias o problemas.
Publicaciones relacionadas
Gracias por leer, espero que este articulo te resultara de provecho. Si así fue, no dudes en dejar un comentario, compartirlo y votar. Te invito a comentar cualquier duda o sugerencia, te aseguro que las leo todas. Así que, por favor, ayúdame a mejorar y continuar compartiendo contenido de calidad. Hasta la próxima.
Hello! Your post has been resteemed and upvoted by @ilovecoding because we love coding! Keep up good work! Consider upvoting this comment to support the @ilovecoding and increase your future rewards! ^_^ Steem On!
Reply !stop to disable the comment. Thanks!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
@orlmicron, I gave you a vote!
If you follow me, I will also follow you in return!
Enjoy some !popcorn courtesy of @nextgencrypto!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
¿Quieres recibir mejores recompensas en tus post de informática, tecnología o programación, ayúdanos delegando algo de SP:
1 SP, 5 SP, 10 SP
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @orlmicron! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
Award for the number of posts published
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOP
Do not miss the last post from @steemitboard:
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @orlmicron! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
You got your First payout
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOP
Do not miss the last post from @steemitboard:
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit