Aprendi hoje: iota um enum com instaminas do Golang
Estou estudando golang, e muitas outras coisas junto na verdade, e quando estava vendo esse video, sim é um vídeo de 7 horas, em especial na parte de constanst, aprende sobre essa maravilhasinha do go, iota
.
Se você como eu ja foi forçado programou em C na faculdade, ja deve ter visto algo como isso aqui:
enum week{Dom, Seg, Ter, Qua, Qui, Sex, Sab};
Os famosos enum, presentes em muitas linguagens, muito uteis para associar um número com uma palavra o que fica bem mais fácil de ler no código. Para quem não sabe o enum basicamente associa numeros automaticamente aos items iniciando do zero, no exemplo acima Dom = 0
, Seg = 1
, Ter = 2
, e assim por diante.
As aplicações são das mais variadas desde associar um status a um número que sera salvo no banco de dados, o que vai ocupar bem menos espaço, a tratar opçoes do menu de um programa de linha de comando. O uso é bem recomendado afinal é bem mais legivel setar o status de um cliente como Inadinplente
do que 4
, que não representa droga nenhuma.
Em golang também temos enums, mas temos uma alternativa para esse uso: o iota
!
const (
Dom = iota
Seg = iota
Ter = iota
Qua = iota
Qui = iota
Sex = iota
Sab = iota
)
Com o código acima vamos ter basicamente o mesmo resultado dos enums do C, você tbm não precisa escrever iota
toda vez, abreviando temos:
const (
Dom = iota
Seg
Ter
Qua
Qui
Sex
Sab
)
Mas por que usar iota
? Porque ele é muito mais poderoso que o enum
do C, por exemplo podemos ignorar o primeiro item e assim pularmos o zero:
const (
_ = iota // 0
Dom // 1
Seg // 2
Ter // 3
Qua // 4
Qui // 5
Sex // 6
Sab // 7
)
E além disso podemos aplicar operações aritméticas para o iota!
const (
Dom = iota + 1 // 0 + 1 = 1
Seg // 1 + 1 = 2
Ter // 2 + 1 = 3
Qua // 3 + 1 = 4
Qui // 4 + 1 = 5
Sex // 5 + 1 = 6
Sab // 6 + 1 = 7
)
Com o exemplo acima temos a mesma coisa do anterior, mas qualquer operação aritmética? Sim!
const (
Zero = iota * 2 // 0 * 2 = 0
Dois // 1 * 2 = 2
Quatro // 2 * 2 = 4
Seis // 3 * 2 = 6
)
E você ainda pode mudar a operação no meio do bloco, admito pra isso ainda não achei utilidade:
const (
Zero = iota * 2 // 0 * 2 = 0
Dois // 1 * 2 = 2
Quatro // 2 * 2 = 4
Nove = iota * 3 // 3 * 3
)
E para o gran finale, mascaras de bits! Sim algo bem parecido com o que alguns sistemas usam para permissionamento:
const (
isAdmin = 1 << iota // 001
canSeeMoney // 010
canSeeStudents // 100
)
var permissions byte = canSeeMoney | canSeeStudents // 110
fmt.Printf("Is Admin? %v\n", isAdmin & roles == isAdmin)
Explicando um pouco melhor este uso, que é mais de binario do que iota, o operador <<
vai incrementar n bits para frente, então 0001 << 0 = 0001
, 0001 << 1 = 0010
, 0001 << 2 = 0100
e assim por diante. No nosso exemplo anterior:
const (
isAdmin = 1 << iota // 001 << 0 = 001
canSeeMoney // 001 << 1 = 010
canSeeStudents // 001 << 2 = 100
)
O operador |
vai pegar dois binarios e retornar um binario “unindo” os bits das permissões, no nosso exemplo: 100 | 010 = 110
, ja o operador &
vai nos retornar um binário comparando bit a bit da permisão com as permissoes do usuário, no nosso exemplo: 110 & 001 = 000
, ou seja o usuário não é um admin.
Uma ultima coisa sobre o iota
o seu valor é resetado quando sai do bloco de declaração:
const (
a = iota // 0
b // 1
c // 2
)
const (
d = iota // aqui iota votla ao 0 novamente
e // 1
f // 2
)
Dúvidas, em especial nesse último, por favor deixe nos comentários!