13. Go to go: maps en Golang

Publicado por

Continuamos con una de las últimas estructuras de datos que nos proporciona Golang nativamente, los maps (mapas o planos). Un map nos permite almacenar información de forma similar a como lo hacíamos con los arreglos o los slices pero con la particularidad de que cada elemento de un map tiene asociada una llave única.

Si alguna vez has trabajado con hash table/hash map en Java, hashes en Perl o cualquier otro lenguaje de programación, un map en Go sigue una filosofía de trabajo similar a estos, por tanto no te resultará complicado comprender su uso.

Conceptos generales

Los maps son unas de las estructuras más utilizadas en Golang gracias a que es muy sencillo utilizarlos y son poderosos métodos de gestión de elementos de conjuntos. A continuación se presenta la sintaxis de la declaración de un map:

Mapa = "map" "[" TipoLlave "]" TipoElemento
TipoLlave = Tipo

  • Más información al respecto aquí.

 

En el siguiente ejemplo declaro un map que almacenará días de la semana donde la llave única será un número entero (correspondiente al orden de los días) y el elemento principal (el que no es la llave única) será una cadena de texto:

var diasSemana map[int]string

El map anterior ha sido declarado, pero no ha sido inicializado, si quisiéramos añadir algún elemento, ocurriría un error ya que el elemento sigue siendo nulo (apuntando a nil). Para inicializar el map utilizamos make:

diasSemana = make(map[int]string)

Para insertar elementos en el map anterior (uno a uno):

diasSemana[1] = "Domingo"
diasSemana[2] = "Lunes"
diasSemana[3] = "Martes"
diasSemana[4] = "Miércoles"
diasSemana[5] = "Jueves"
diasSemana[6] = "Viernes"
diasSemana[7] = "Sábado"

Si queremos recorrer todos los elementos, podemos hacer lo siguiente:

for dia := range diasSemana {
  fmt.Println("El día", dia, "de la semana es", diasSemana[dia])
}

Salida:
golang-map-03

Para buscar un elemento es necesario utilizar una asignación doble en donde la primera variable almacenará el resultado de la consulta y la segunda variable (generalmente llamada ok<) será inicializada con un valor bool true si el elemento existe:

string_dia, ok := diasSemana[8]

if(ok){
  fmt.Println("El elemento sí existe y almacena:", string_dia)
}else{
  fmt.Println("El elemento no existe")
}

Para consultar el tamaño de un map se utiliza la función len() como lo hacíamos con slices:

len(diasSemana)

La función delete() permite eliminar elementos de un map a través de la llave única de estos:

delete(diasSemana, 2) //Elimina el elemento con la llave 2

Ejemplo:

package main

import "fmt"

func main(){
  var diasSemana map[int]string
  diasSemana = make(map[int]string)

  diasSemana[1] = "Domingo"
  diasSemana[2] = "Lunes"
  diasSemana[3] = "Martes"
  diasSemana[4] = "Miércoles"
  diasSemana[5] = "Jueves"
  diasSemana[6] = "Viernes"
  diasSemana[7] = "Sábado"

  //Busca elemento con llave 8
  string_dia, encontrado := diasSemana[8]

  if(encontrado){
    fmt.Println("El día 2 es", string_dia)
  }else{
    fmt.Println("El día 2 no fue encontrado")
  }

  //Eliminar el elemento con llave 2
  delete(diasSemana, 2)

  fmt.Println("Tamaño del map:", len(diasSemana))
}

Salida:
golang-map-02

Nota: Golang no considera un error de compilación el tratar de añadir un elemento nuevo con una llave que ya existe en el map, en su lugar simplemente reemplaza el elemento antiguo con la información del nuevo.

maps y structs

Es posible declarar un map que almacene elementos de tipo struct y de ese modo guardar grandes cantidades de struct sin necesidad de programar estructuras dinámicas (las cuales serán tratadas en temas posteriores). El siguiente ejemplo muestra cómo podemos hacerlo:

package main

import "fmt"

//Registro de materias
type Materia struct{
  nombre string
  creditos int
}

func main(){
  //Mapa con registros inicializado al declarar
  var materias = map[string]Materia{
    "COMP": Materia{
      "Compiladores", 12,
    },
    "GO": Materia{
      "Golang", 8,
    },
    "INPROG": Materia{
      "Introducción Programación", 6,
    },
  }

  //Imprime materias
  for materia := range materias{
    fmt.Println("Código:", materia, "| Nombre:", materias[materia].nombre,
      "| Créditos:", materias[materia].creditos)
  }
  fmt.Printf("\n\n")

  //Añade un elemento nuevo
  materias["POO"] = Materia{"Programación Orientada a Objetos", 7,}

  //Imprime materias
  for materia := range materias{
    fmt.Println("Código:", materia, "| Nombre:", materias[materia].nombre,
      "| Créditos:", materias[materia].creditos)
  }
  fmt.Printf("\n\n")

  //Busca materia con llave única "COMP"
  mat, ok := materias["COMP"]

  if(ok){
    fmt.Println("Nombre materia:", mat.nombre, "| Créditos:", mat.creditos)
  }else{
    fmt.Println("La materia no existe")
  }
}

Salida:
golang-map-01

Finalizando…

En esta entrada aprendimos a utilizar maps en Go, recuerda siempre practicar para dominar los temas que estudiamos. Sin más que agregar, hasta la próxima, see ya!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *