Como utilizar generics em structs

A partir da versão 1.18 do Go, FINALMENTE temos o generics disponível para utilização. Em outros posts, que vou deixar aqui em baixo, já abordamos como utilizar generics em funções, como utilizar a contraint comparable e fizemos um pequeno benchmark para ver a diferença com funções comuns.

Essa semana enquanto fuçava no código fonte do Go, descobri que também podemos utilizar essa maravilha em structs.

Para demonstrar como utiliza-lo, vamos criar uma struct para fazer cache das structs PessoaFisica e PessoaJuridica.

Antes de continuar, vamos criar as structs que serão armazenadas em cache.

type Pessoa struct {
    Nome      string
    Documento string
}

type PessoaFisica struct {
    Pessoa
    Idade uint8
}

type PessoaJuridica struct {
    Pessoa
    RazaoSocial string
}

Agora que definimos as structs onde os dados serão armazenados, vamos criar uma struct genérica que possa ser usada para fazer cache tanto de PessoaFisica quanto de PessoaJuridica.

type Cache[V PessoaFisica | PessoaJuridica] struct {
    data map[string]V
}

Tendo definido nosso atributo data como privado, vamos implementar dois métodos para que possamos manipular os dados do nosso cache.

O primeiro método será responsável por adicionar novos itens ou substituir itens já armazenados no cache.

func (c *Cache[V]) Set(key string, value V) {
    if c.data == nil {
        c.data = make(map[string]V)
    }

    c.data[key] = value
}

Já o segundo será responsável por retornar um dado armazenado no cache.

func (c *Cache[V]) Get(key string) (v V) {
    if c.data == nil {
        return
    }
    if v, ok := c.data[key]; ok {
        return v
    }

    return
}

Notem que em ambos os métodos precisamos passar o Cache[V] ao invés do Cache, como fazemos normalmente.

Para testar, vamos implementar a função main com:

  • Um cache para PessoaFisica e outro para PessoaJuridica;
  • Um dado de PessoaFisica e outro de PessoaJuridica;
  • Armazenar os dados em seus respectivos caches;
  • Retornar os dados armazenados.
func main() {
    pf := PessoaFisica{
        Pessoa{"Tiago", "000.000.000-00"},
        32,
    }

    cachepf := Cache[PessoaFisica]{}
    cachepf.Set(pf.Documento, pf)

    pj := PessoaJuridica{
        Pessoa{"Aprenda Golang LTDA", "00.000.000/0000-00"},
        "Aprenda Golang",
    }

    cachepj := Cache[PessoaJuridica]{}
    cachepj.Set(pj.Documento, pj)

    fmt.Println(cachepf.Get("000.000.000-00"))
    fmt.Println(cachepf.Get("000.000.110-00"))
    
    fmt.Println("-------")
    
    fmt.Println(cachepj.Get("00.000.000/0000-00"))
    fmt.Println(cachepj.Get("00.000.000/0000-01"))
}

Como podemos ver no código acima, ao iniciar a struct é preciso passar qual será seu tipo.

Para testar é só executar um go run main.go. O resultado deve ser algo similar a isso:

{{Tiago 000.000.000-00} 32}
{{ } 0}
-------
{{Aprenda Golang LTDA 00.000.000/0000-00} Aprenda Golang}
{{ } }

Deixem suas dúvidas nos comentários.

Até a próxima!


Subscreva

Fique por dentro de tudo o que acontece no mundo Go.

Deixe uma resposta