Operadores, expressões e conversão de tipo
Artigo 04 — Operadores, expressões e conversão de tipos
Curso: Dominando Go em 1 Ano Prof. Ricardo Matos Módulo 1 — Fundamentos da Linguagem
Operadores são a gramática das expressões
Se variáveis são os substantivos de um programa, operadores são os verbos. Eles definem o que acontece com os dados — como são combinados, comparados, transformados e manipulados. Go tem um conjunto de operadores enxuto e bem definido, sem surpresas ou comportamentos ambíguos.
Operadores aritméticos
Os operadores aritméticos básicos funcionam como esperado para tipos numéricos:
package main
import "fmt"
func main() {
a := 15
b := 4
fmt.Println(a + b) // 19 — adição
fmt.Println(a - b) // 11 — subtração
fmt.Println(a * b) // 60 — multiplicação
fmt.Println(a / b) // 3 — divisão inteira
fmt.Println(a % b) // 3 — resto da divisão (módulo)
}
Um ponto que merece atenção é a divisão inteira. Quando ambos os operandos são inteiros, o resultado também é inteiro — a parte fracionária é descartada sem arredondamento. Para obter o resultado com casas decimais, ao menos um dos operandos precisa ser float64:
a := 15
b := 4
inteiro := a / b // 3
decimal := float64(a) / float64(b) // 3.75
fmt.Println(inteiro, decimal)
Go não possui operador de exponenciação como **. Para potências, usa-se a função math.Pow:
import "math"
resultado := math.Pow(2, 10) // 1024.0
fmt.Println(resultado)
Operadores de incremento e decremento
Go possui ++ e --, mas com uma diferença importante em relação a C e Java: eles são declarações, não expressões. Isso significa que não retornam valor e só podem ser usados de forma isolada, nunca dentro de uma expressão maior:
x := 10
x++ // válido: x agora é 11
x-- // válido: x agora é 10
// y := x++ — erro de compilação
// if x++ > 5 — erro de compilação
Além disso, Go não possui as formas prefixadas ++x e --x. Apenas o sufixo é permitido.
Operadores de atribuição composta
Go oferece versões combinadas dos operadores aritméticos e bitwise com atribuição:
x := 10
x += 5 // x = x + 5 → 15
x -= 3 // x = x - 3 → 12
x *= 2 // x = x * 2 → 24
x /= 4 // x = x / 4 → 6
x %= 4 // x = x % 4 → 2
fmt.Println(x) // 2
Operadores de comparação
Operadores de comparação sempre retornam um valor bool. São usados principalmente em estruturas de controle:
a := 10
b := 20
fmt.Println(a == b) // false — igualdade
fmt.Println(a != b) // true — diferença
fmt.Println(a < b) // true — menor que
fmt.Println(a > b) // false — maior que
fmt.Println(a <= b) // true — menor ou igual
fmt.Println(a >= b) // false — maior ou igual
Em Go, comparações entre tipos diferentes são proibidas pelo compilador. Não é possível comparar um int com um float64 diretamente — a conversão precisa ser explícita antes.
Operadores lógicos
Usados para combinar expressões booleanas:
t := true
f := false
fmt.Println(t && f) // false — E lógico (ambos precisam ser true)
fmt.Println(t || f) // true — OU lógico (pelo menos um precisa ser true)
fmt.Println(!t) // false — negação
Go utiliza avaliação em curto-circuito. No operador &&, se o primeiro operando for false, o segundo não é avaliado. No operador ||, se o primeiro for true, o segundo é ignorado. Esse comportamento é importante quando o segundo operando é uma chamada de função com efeitos colaterais ou que pode causar pânico.
func perigosa() bool {
fmt.Println("função executada")
return true
}
resultado := false && perigosa()
// "função executada" NÃO é impresso — curto-circuito
fmt.Println(resultado) // false
Operadores bitwise
Para manipulação em nível de bits, Go oferece o conjunto completo de operadores bitwise:
a := 0b1100 // 12 em binário
b := 0b1010 // 10 em binário
fmt.Println(a & b) // 0b1000 = 8 — AND bitwise
fmt.Println(a | b) // 0b1110 = 14 — OR bitwise
fmt.Println(a ^ b) // 0b0110 = 6 — XOR bitwise
fmt.Println(a &^ b) // 0b0100 = 4 — AND NOT (bit clear)
fmt.Println(a << 1) // 0b11000 = 24 — deslocamento à esquerda
fmt.Println(a >> 1) // 0b0110 = 6 — deslocamento à direita
O operador &^ é exclusivo do Go e não tem equivalente direto em C ou Java. Ele limpa os bits do operando esquerdo que estão definidos no operando direito.
Precedência de operadores
Quando múltiplos operadores aparecem em uma expressão, Go segue uma ordem de precedência definida. Do maior para o menor nível:
| Nível | Operadores |
|---|---|
| 5 (maior) | * / % << >> & &^ |
| 4 | + - | ^ |
| 3 | == != < <= > >= |
| 2 | && |
| 1 (menor) | || |
A recomendação prática é usar parênteses sempre que a precedência não for óbvia. Código claro é preferível a código que exige que o leitor memorize tabelas:
// Ambíguo para o leitor:
resultado := 2 + 3*4 - 1
// Explícito e sem dúvida:
resultado := 2 + (3 * 4) - 1
Conversão de tipos em profundidade
Como visto no artigo anterior, Go não realiza conversões implícitas. Toda conversão entre tipos diferentes deve ser escrita explicitamente pelo programador. A sintaxe é sempre Tipo(valor).
Conversões numéricas:
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
fmt.Println(i, f, u) // 42 42 42
Atenção com truncamento. Converter float64 para int descarta a parte decimal sem arredondamento:
x := 3.99
y := int(x)
fmt.Println(y) // 3 — não 4
Conversão entre inteiros de tamanhos diferentes. Converter um valor grande para um tipo menor pode causar overflow silencioso:
var grande int32 = 300
var pequeno int8 = int8(grande)
fmt.Println(pequeno) // 44 — overflow! 300 não cabe em int8
Go não emite erro em tempo de execução para overflow em conversões — o valor simplesmente é truncado. Essa é uma armadilha que exige atenção.
Conversão entre string e slice de bytes:
s := "Olá, Go"
b := []byte(s) // string → []byte
s2 := string(b) // []byte → string
fmt.Println(b) // [79 108 195 161 44 32 71 111]
fmt.Println(s2) // Olá, Go
Essa conversão é muito comum ao trabalhar com I/O, redes e manipulação de texto.
Conversão entre string e slice de runes:
s := "Olá"
r := []rune(s)
fmt.Println(len(s)) // 4 bytes — o 'á' ocupa 2 bytes em UTF-8
fmt.Println(len(r)) // 3 runes — 3 caracteres visuais
Quando a contagem de caracteres visuais importa, sempre converta para []rune antes de usar len.
O pacote strconv: conversões entre string e tipos numéricos
Converter números em strings e vice-versa é uma operação frequente. O pacote strconv da biblioteca padrão é a ferramenta correta para isso — nunca use conversão direta string(numero) com inteiros, pois o resultado é inesperado:
fmt.Println(string(65)) // "A" — não "65"!
O que acontece acima é que Go interpreta 65 como um ponto de código Unicode e retorna o caractere correspondente. Para converter o número 65 na string "65", use strconv:
import (
"fmt"
"strconv"
)
func main() {
// int → string
n := 42
s := strconv.Itoa(n)
fmt.Println(s) // "42"
fmt.Printf("%T\n", s) // string
// string → int
valor, err := strconv.Atoi("123")
if err != nil {
fmt.Println("Erro na conversão:", err)
return
}
fmt.Println(valor + 1) // 124
// float64 → string
f := 3.14159
fs := strconv.FormatFloat(f, 'f', 2, 64)
fmt.Println(fs) // "3.14"
// string → float64
fv, err := strconv.ParseFloat("2.718", 64)
if err == nil {
fmt.Println(fv) // 2.718
}
}
A função strconv.Atoi retorna dois valores: o inteiro convertido e um erro. Esse padrão de retorno duplo é o idioma central do Go para tratamento de falhas e será explorado em profundidade nos próximos módulos.
Expressões e o pacote fmt
O pacote fmt oferece funções para formatar e imprimir expressões com precisão:
nome := "Ricardo"
idade := 35
altura := 1.78
fmt.Printf("Nome: %s\n", nome)
fmt.Printf("Idade: %d\n", idade)
fmt.Printf("Altura: %.2f\n", altura)
fmt.Printf("Tipo de idade: %T\n", idade)
// Formatação para string sem imprimir
s := fmt.Sprintf("Usuário: %s, %d anos", nome, idade)
fmt.Println(s)
Os verbos de formatação mais usados são %d para inteiros, %f para floats, %s para strings, %t para booleanos, %T para o tipo da variável e %v para o valor padrão de qualquer tipo.
Resumo do que foi coberto
Este artigo percorreu o conjunto completo de operadores do Go — aritméticos, lógicos, de comparação, bitwise e de atribuição composta — junto com as regras de precedência. A conversão explícita de tipos foi aprofundada com atenção aos casos armadilhosos como truncamento e overflow. O pacote strconv foi apresentado como a ferramenta correta para conversões entre strings e tipos numéricos.
Referências e leituras complementares
Especificação da linguagem Go — Expressões — Referência formal de todos os operadores e regras de expressão. https://go.dev/ref/spec#Expressions
Especificação da linguagem Go — Conversões — Regras completas de conversão entre tipos. https://go.dev/ref/spec#Conversions
Documentação do pacote strconv — Referência completa de todas as funções de conversão. https://pkg.go.dev/strconv
Documentação do pacote fmt — Referência dos verbos de formatação e funções de impressão. https://pkg.go.dev/fmt
Go by Example: String Formatting — Exemplos práticos dos verbos do pacote fmt. https://gobyexample.com/string-formatting
Documentação do pacote math — Funções matemáticas incluindo Pow, Sqrt, Abs e outras. https://pkg.go.dev/math
Próximo artigo: Artigo 05 — Estruturas de controle: if, for e switch
you asked
Sim