Aprendendo Go: Maps

Aprendendo Go: Maps

Maps são uma estrutura de dados nativa em Go, conveniente e poderosa com o objetivo de associar valores de um tipo (chaves) a (valores) de outro tipo.

Esse artigo foi baseado no documento, gratuito e disponível em Effective Go

Podendo a chave dessa estrutura ser representada por qualquer tipo em que seja possível utilizar o operador de igualdade, por exemplo,

  • integer

  • floating

  • string

  • interfaces

  • structs

  • arrays

Slices não podem ser utilizados como chaves em maps porque o operador de igualdade não implementa o seu tipo em particular.

Assim como os slices, maps guarda referência para uma estrutura de dados subjacente, logo, caso maps seja passado por uma função e seja modificado, essas mudanças estarão visíveis para quem chamou a função.

Maps podem ser construídos em uma composição literal, com separação por virgula para os pares de chave e valor, logo, se torna fácil construí-los na inicialização

var timeZone = map[string]int{
    "UTC":  0*60*60,
    "EST": -5*60*60,
    "CST": -6*60*60,
    "MST": -7*60*60,
    "PST": -8*60*60,
}

Atribuir e buscar valores é praticamente a mesma coisa do que com arrays e slices com exceção de que o indíce não precisa ser um inteiro.

offset := timeZone["EST"]

Ao tentar buscar um valor dentro de um map em que a chave não esteja presente o retorno será um valor "zerado" correspondendo ao tipo em que as entradas foram definidas. Por exemplo, se um mapa contém integers a busca não existente retornará 0. Exemplo, defina o map com um valor true para atribuir valor ao conjunto, depois teste com um caso de indexação.

attended := map[string]bool{
    "Ann": true,
    "Joe": true,
    ...
}

if attended[person] {
    fmt.Println(person, "was at the meeting")
}

Algumas vezes você vai precisar diferenciar uma entrada errada de um valor zero. Existe uma entrada para UTC ou esse zero é porque não está no map? Para isso você pode definir uma forma com atribuição múltipla.

var seconds int
var ok bool
seconds, ok = timeZone[tz]

, nesse exemplo, se tz está contido os seconds serão atribuídos corretamente e o ok será verdadeiro. Caso contrário, seconds será zero e o falor será falso, para essa atribuição chamamos de comma ok idiom. Aqui está a função que coloca os dois juntos em um bom alerta de erro:

func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    }
    log.Println("unknown time zone:", tz)
    return 0
}

Para testar a presença no map sem precisar saber qual valor em questão, você pode simplesmente usar o operador vazio, identificado com _ no lugar de uma variável.

_, present := timeZone[tz]

Para deletar um dado de um map, utilize a função nativa delete, os argumentos a se passar são o próprio map e a key (ou chave) para ser deletada.

delete(timeZone, "PDT")