Go: Variáveis e tipos de dados em Go
Última atualização: 2026-08-26
As variáveis são a base de um programa — o Go utiliza uma sintaxe minimalista para tornar as declarações de variáveis claras e seguras.
A filosofia de design por trás do sistema de tipos do Go: Explícito em vez de implícito. Isso significa que toda 変数 possui um tipo bem definido, permitindo que o compilador detecte mais de 90% dos erros em tempo de compilação. Nesta lição, você aprenderá toda a 構文 para declarar variáveis no Go.
1. Você aprenderá
- As duas formas de declarar variáveis:
vare:= - Os 14 tipos de dados básicos em Go
- O mecanismo exclusivo de “valor zero” do Go
constDeclarações de constantes eiotaenums- Conversão explícita de tipos (o Go não permite conversões implícitas)
- Saída formatada como
fmt.Printf/fmt.Sprintf - Exemplos completos de formulários de cadastro de usuários
2. A história real de um engenheiro full-stack
(1) Problema: Depuração tarde da noite causada pela tipagem dinâmica
Alice é uma engenheira que mudou do Python para o Go. Ela ingressou recentemente na empresa e assumiu a responsabilidade por um módulo de registro de usuários:
“O gerente de produto disse: ‘Após o lançamento, os dados dos usuários estavam uma bagunça. Algumas pessoas inseriram 1º de janeiro de 2024 como data de nascimento, outras inseriram “ontem” e outras ainda inseriram
null— metade dos dados no banco de dados não pôde ser analisada.’”
Ela deu uma olhada no código e descobriu que a tipagem dinâmica do Python era a culpada:
# Python: variable types can change at any time
birthday = "1990-01-01"
birthday = 1990 # integer suddenly valid
birthday = None # None also valid
birthday = ["today"] # list also valid!
A mesma variável pode ser uma string, um inteiro, None ou uma lista em diferentes partes do código — não há nenhum mecanismo para evitar essa confusão.
(2) Solução em Go
Alice reescreveu o modelo de usuário em Go:
// user.go
package main
import "fmt"
type User struct {
Name string // string
Age int // integer
Height float64 // float
IsActive bool // boolean
Birthday string // ISO 8601 date string
}
func main() {
user := User{
Name: "Alice",
Age: 28,
Height: 165.5,
IsActive: true,
Birthday: "1996-05-12",
}
// Want to change `Age` to a string? You'll get a compile-time error!
// user.Age = "twenty-eight" // ❌ cannot use "twenty-eight" as int
fmt.Printf("User: %s, Age: %d, Height: %.1fcm\n",
user.Name, user.Age, user.Height)
}
Resultado:
User: Alice, Age: 28, Height: 165.5cm
(3) Benefícios: Detecta 90% dos erros durante a compilação
| Dimensão | Python (tipagem dinâmica) | Go (tipagem estática e forte) |
|---|---|---|
| Verificação de tipos em tempo de compilação | ❌ Nenhuma | ✅ Rigorosa |
| Erro de tipo em tempo de execução | Frequente | Raro |
| Autocompletar do IDE | Fraco | Forte |
| Segurança da refatoração | Baixa | Alta |
| Armadilha de valor nulo (Nenhum/nulo) | Comum | Proteção contra o mecanismo de valor zero |
3. Declaração de variáveis: var e :=
O Go oferece duas maneiras de declarar variáveis: a var palavra-chave (padrão) e a := declaração abreviada (forma abreviada).
(1) Declaração da palavra-chave var (método padrão)
var pode ser usado dentro de funções ou no nível do pacote, e há três maneiras de escrevê-lo:
// Method 1: Declare a variable with an explicit type
var name string = "Alice"
// Method 2: Declare a variable and omit the type (the type is inferred from the value)
var name = "Alice"
// Method 3: Declare only; initialize to zero value
var name string // name = ""
(2) ▶ Exemplo: Comparação entre três formas de escrever var
package main
import "fmt"
func main() {
// Method 1: Explicit Type + Initialization
var userName string = "Alice"
var userAge int = 28
// Method 2: Type Inference
var userEmail = "alice@example.com"
// Method 3: Declare only; rely on the default value
var userBio string // ""
fmt.Println(userName, userAge, userEmail, userBio)
}
Saída:
Alice 28 alice@example.com
(3) := Declaração curta (a mais comum)
:= é um sintaxe simplificada em Go; só pode ser usado dentro de funções e infere automaticamente o tipo:
package main
import "fmt"
func main() {
// Short declaration: variable_name := value
name := "Alice" // inferred as string
age := 28 // inferred as int
height := 165.5 // inferred as float64
isActive := true // inferred as bool
fmt.Printf("%s is %d years old, height %.1f, active: %v\n",
name, age, height, isActive)
}
Saída:
Alice is 28 years old, height 165.5, active: true
(4) var vs := — qual devo escolher?
| Cenário | Abordagem recomendada | Motivo |
|---|---|---|
| Variáveis no nível do pacote | var |
:= Não podem ser usadas fora de funções |
| Variáveis locais dentro de uma função | := |
Conciso; economiza 4 caracteres |
| Deve ter valor zero | var x int |
:= Deve ser inicializado ao mesmo tempo |
| Requer uma conversão de tipo explícita | var x int = int(3.14) |
A conversão de tipo está claramente visível |
| Declarações em lote | var (...) |
:= não suporta declarações em lote |
4. Tipos de dados básicos do Go
O Go possui 14 tipos de dados básicos, que são divididos em quatro categorias principais com base em sua finalidade.
(1) Tipos inteiros
graph TB
A[Integer Types] --> B[Signed int]
A --> C[Unsigned uint]
A --> D[Byte type]
A --> E[Special rune]
B --> B1[int<br/>at least 32 bits]
B --> B2[int8 / int16 / int32 / int64]
C --> C1[uint<br/>at least 32 bits]
C --> C2[uint8 / uint16 / uint32 / uint64]
D --> D1[byte = uint8<br/>emphasizes byte]
E --> E1[rune = int32<br/>emphasizes Unicode code point]
| Tipo | Tamanho | Faixa | Aplicações típicas |
|---|---|---|---|
int |
32 ou 64 bits (dependendo da plataforma) | -2^31 a 2^31-1 ou maior | Tipo inteiro padrão |
int8 |
8 bits | -128 a 127 | Números inteiros de intervalo pequeno |
int32 |
32 bits | -2^31 a 2^31-1 | Tamanho fixo multiplataforma |
int64 |
64 bits | -2^63 a 2^63-1 | Números inteiros grandes, carimbos de data/hora |
uint |
32 ou 64 bits | 0 a 2^32-1 ou maior | Sem sinal por padrão |
byte |
8 bits | 0–255 | byte, caractere ASCII |
rune |
32 bits | ponto de código Unicode | caractere Unicode único |
(2) ▶ Exemplo: A diferença entre int e int64
package main
import (
"fmt"
"unsafe"
)
func main() {
var a int = 100
var b int64 = 200
fmt.Printf("a (int) size: %d bytes\n", unsafe.Sizeof(a))
fmt.Printf("b (int64) size: %d bytes\n", unsafe.Sizeof(b))
// You cannot directly add `int` and `int64`!
// sum := a + b // ❌ mismatched types int and int64
// An explicit conversion is required
sum := a + int(b)
fmt.Println("sum:", sum)
}
Saída (em plataformas de 64 bits):
a (int) size: 8 bytes
b (int64) size: 8 bytes
sum: 300
(3) Tipos de ponto flutuante
| Tipo | Tamanho | Precisão | Aplicações típicas |
|---|---|---|---|
float32 |
32 bits | ~7 dígitos significativos | Computação científica, gráficos |
float64 |
64 bits | ~15 dígitos significativos | Tipo padrão de ponto flutuante |
(4) Tipo booleano
var isActive bool = true
var hasPermission bool // zero value = false
(5) Tipo String
var greeting string = "Hello, Go!"
var emptyString string // zero value = "" (empty string)
var multiLine string = `Line 1
Line 2
Line 3` // backticks support multi-line strings
(6) Tabela de referência rápida para 14 tipos
| Categoria | Tipo | Valor zero |
|---|---|---|
| Número inteiro | int / int8 / int16 / int32 / int64 |
0 |
| Inteiros sem sinal | uint / uint8 / uint16 / uint32 / uint64 |
0 |
| Byte/Caractere | byte (=uint8) / rune (=int32) |
0 |
| Ponto flutuante | float32 / float64 |
0,0 |
| Booleano | bool |
falso |
| String | string |
"" |
5. O mecanismo exclusivo de valor zero do Go
Não há variáveis “não inicializadas” em Go — toda variável possui um valor padrão razoável no momento em que é declarada.
(1) ▶ Exemplo: Valores zero de todos os tipos
package main
import "fmt"
func main() {
var i int
var f float64
var b bool
var s string
var p *int // pointer zero value is nil
fmt.Printf("int: %d\n", i)
fmt.Printf("float64: %f\n", f)
fmt.Printf("bool: %v\n", b)
fmt.Printf("string: %q\n", s) // %q shows quoted string, empty string shows ""
fmt.Printf("pointer: %v\n", p)
}
Saída:
int: 0
float64: 0.000000
bool: false
string: ""
pointer: <nil>
(2) Valores zero em comparação com outras linguagens
| Tipo | Valor zero | Java | Python | C/C++ |
|---|---|---|---|---|
| Inteiro | 0 | 0 | Não existe | Indefinido (valor inválido) |
| Ponto flutuante | 0,0 | 0,0 | Não existe | Indefinido |
| Booleano | falso | falso | Falso | Indefinido |
| String | "" | nulo | "" | Indefinido |
| Ponteiro | nil | null | None | NULL (mas sujeito a ponteiros inválidos) |
6. const Constantes e iota Enumerações
(1) Use const para declarar constantes
As constantes são determinadas em tempo de compilação, não podem ser modificadas e devem ser de tipos básicos:
const Pi = 3.14159
const AppName = "web-tutorial"
const MaxConnections = 1000
(2) Enumeração Iota: a elegante forma de enumeração do Go
iota é um contador constante no Go que começa em 0 e incrementa automaticamente em 1 a cada linha:
package main
import "fmt"
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
func main() {
fmt.Printf("Sunday=%d Monday=%d Saturday=%d\n", Sunday, Monday, Saturday)
}
Saída:
Sunday=0 Monday=1 Saturday=6
(3) ▶ Exemplo: Incremento personalizado de iota (códigos de status HTTP)
package main
import "fmt"
const (
StatusOK = iota * 100 // 0
StatusRedirect // 100
StatusClientError // 200
StatusServerError // 300
)
func main() {
fmt.Printf("OK=%d Redirect=%d ClientError=%d ServerError=%d\n",
StatusOK, StatusRedirect, StatusClientError, StatusServerError)
}
Saída:
OK=0 Redirect=100 ClientError=200 ServerError=300
(4) Uso avançado do iota: máscaras de bits (permissões de arquivo)
package main
import "fmt"
const (
ReadPermission = 1 << iota // 1 << 0 = 1
WritePermission // 1 << 1 = 2
ExecutePermission // 1 << 2 = 4
)
func main() {
// Permission Combination: Read + Write = 1 | 2 = 3
rw := ReadPermission | WritePermission
fmt.Printf("Read=%d Write=%d Execute=%d RW=%d\n",
ReadPermission, WritePermission, ExecutePermission, rw)
}
Saída:
Read=1 Write=2 Execute=4 RW=3
iota é a única sintaxe no Go que se aproxima de uma “enum”, mas não é tão rígida quanto os tipos enum no Python ou no Java. Se você precisar de maior segurança de tipos em um ambiente de produção, pode definir seus próprios tipos.
7. Conversão explícita de tipos
O Go não permite conversões implícitas de tipo — todas as conversões devem ser declaradas explicitamente. Isso reflete o princípio do Go de “explícito em vez de implícito”.
(1) Conversão de tipos numéricos
package main
import "fmt"
func main() {
var i int = 42
var f float64 = float64(i) // int → float64
var u uint = uint(f) // float64 → uint
fmt.Printf("i=%d f=%v u=%d\n", i, f, u)
// Truncation example: Converting a float to an int results in the loss of the decimal part
var pi float64 = 3.14159
var truncated = int(pi)
fmt.Printf("pi=%.5f truncated=%d\n", pi, truncated)
}
Saída:
i=42 f=42 u=42
pi=3.14159 truncated=3
(2) Conversão de strings: o pacote strconv
package main
import (
"fmt"
"strconv"
)
func main() {
// String → Number
n, err := strconv.Atoi("123")
fmt.Printf("n=%d err=%v\n", n, err)
// Number → String
s := strconv.Itoa(456)
fmt.Printf("s=%s (type: %T)\n", s, s)
// String → float
f, _ := strconv.ParseFloat("3.14", 64)
fmt.Printf("f=%f\n", f)
// float → string (specified precision)
fmt.Println(strconv.FormatFloat(3.14159, 'f', 2, 64)) // "3.14"
}
Saída:
n=123 err=<nil>
s=456 (type: string)
f=3.140000
3.14
(3) Conversão implícita x conversão explícita
| Cenário | Java/C++ | Go |
|---|---|---|
int + float |
Convertido automaticamente para float | Erro de compilação; deve ser explícito |
int32 + int64 |
Convertido automaticamente para int64 | Erro de compilação |
int para string |
Implícito | Requer strconv.Itoa() |
8. fmt: Formatar a saída
(1) Verbos comuns de formatação
| Verbo | Significado | Tipos aplicáveis |
|---|---|---|
%d |
Inteiro decimal | int, int8/16/32/64 |
%f |
Número de ponto flutuante | float32, float64 |
%s |
string | string |
%v |
Formato padrão para qualquer tipo | Qualquer tipo |
%T |
Tipo | Qualquer tipo |
%t |
Booleano | bool |
%q |
String entre aspas | string, runa |
%x |
Hexadecimal | int, []byte |
%p |
Endereço do ponteiro | ponteiro |
%% |
Símbolo de porcentagem literal | — |
(2) ▶ Exemplo: Demonstração completa do fmt.Printf
package main
import "fmt"
func main() {
name := "Alice"
age := 28
height := 165.5
isActive := true
hobbies := []string{"coding", "reading", "hiking"}
fmt.Printf("Name: %s\n", name) // %s string
fmt.Printf("Age: %d\n", age) // %d integer
fmt.Printf("Height: %.1f cm\n", height) // %.1f float with 1 decimal
fmt.Printf("Active: %t\n", isActive) // %t boolean
fmt.Printf("Hobbies: %v\n", hobbies) // %v default format
fmt.Printf("Name type: %T\n", name) // %T type
fmt.Printf("100%% complete!\n") // %% literal %
// %v Advanced usage: %+v displays the field name (struct), %#v displays Go syntax
fmt.Printf("hobbies: %#v\n", hobbies)
}
Saída:
Name: Alice
Age: 28
Height: 165.5 cm
Active: true
Hobbies: [coding reading hiking]
Name type: string
100% complete!
hobbies: []string{"coding", "reading", "hiking"}
(3) A diferença entre Print, Println e Printf
| Função | Terminação de saída | Casos de uso |
|---|---|---|
fmt.Print() |
Sem quebra de linha | Saída contínua |
fmt.Println() |
Quebras de linha automáticas + separadas por espaço | Depuração simples |
fmt.Printf() |
Não insere uma nova linha; requer \n |
Saída formatada |
fmt.Sprintf() |
Retorna uma string; não exibe | Concatena strings |
9. Exemplo completo: Formulário de cadastro do usuário
Reúna todos os conceitos-chave desta lição e crie um coletor de dados para registro de usuários:
// main.go
package main
import (
"fmt"
"strconv"
)
// Defining User Role Enumerations Using Iota
const (
RoleGuest = iota // 0 Guest
RoleUser // 1 Regular User
RoleAdmin // 2 Admin
RoleSuperAdmin // 3 Super Admin
)
func main() {
// 1. Use the := short declaration for user information
name := "Alice"
age := 28
height := 165.5
isActive := true
role := RoleUser
// 2. Explicit Type Conversion
ageAsFloat := float64(age)
heightAsString := strconv.FormatFloat(height, 'f', 1, 64)
// 3. const Constants
const MaxLoginAttempts = 5
// 4. fmt: Formatted Output
fmt.Println("========================================")
fmt.Println(" User Registration Form")
fmt.Println("========================================")
fmt.Printf("Name: %s\n", name)
fmt.Printf("Age: %d (%.0f years old)\n", age, ageAsFloat)
fmt.Printf("Height: %s cm\n", heightAsString)
fmt.Printf("Active: %t\n", isActive)
fmt.Printf("Role: %d (User)\n", role)
fmt.Printf("Max Attempts: %d\n", MaxLoginAttempts)
fmt.Printf("Type Check: name is %T, age is %T\n", name, age)
fmt.Println("========================================")
// 5. Demonstration of Zero Values for Variables
var uninitializedAge int
fmt.Printf("\nUninitialized age (zero value): %d\n", uninitializedAge)
}
Resultado esperado:
========================================
User Registration Form
========================================
Name: Alice
Age: 28 (28 years old)
Height: 165.5 cm
Active: true
Role: 1 (User)
Max Attempts: 5
Type Check: name is string, age is int
========================================
Uninitialized age (zero value): 0
strconv.Atoi("abc") retornará um erro, que não deve ser ignorado. Sintaxe correta: n, err := strconv.Atoi("abc"); if err != nil { ... }. A lição 8 aborda mais detalhadamente o tratamento de erros.
❓ Perguntas Frequentes
P: O que é melhor,
varou:=? R: Recomendamos usar:=dentro de funções — é conciso e garante a inicialização; variáveis no nível do pacote devem usarvar. O bytecode gerado por ambos é exatamente o mesmo; trata-se apenas de sintaxe simplificada.
P: O tamanho do
intdo Go varia entre plataformas de 32 bits e 64 bits. Que problemas isso pode causar? R: Ele tem 8 bytes em plataformas de 64 bits e 4 bytes em plataformas de 32 bits. Se você precisar serializar seus dados (por exemplo, para JSON ou um banco de dados), recomenda-se especificar explicitamenteint32ouint64para evitar problemas de compatibilidade entre plataformas.
P: O Go não possui uma palavra-chave
enum. Como se cria uma enumeração? R: Useconst + iota. Embora não seja tão rigorosa quanto aenum classdo Java, é suficiente. Se você precisar de segurança de tipos, pode usar um tipo personalizado comotype Role intjunto com um conjunto de constantes.
P: O valor de
iotacomeça em 0. Ele pode começar em 1? R: Sim. Use_ = iotapara pular o 0, ouiota + 1:const (A = iota + 1; B; C), o que resulta em A=1, B=2, C=3. Isso é comumente usado em cenários em que os valores precisam começar em 1, como códigos de status HTTP e meses.
P: Por que o Go não suporta conversão implícita de tipos? R: A equipe do Go acredita que “explícito é melhor do que implícito”. As conversões implícitas são a causa principal de muitos bugs em Java e C++ (como a perda de precisão ao misturar operações
intelong). A conversão rigorosa de tipos do Go torna o código mais legível e resulta em menos bugs.
P: Como se faz a conversão entre
stringe[]byte? R:[]byte(s)converte uma string em uma fatia de bytes (copiando os dados);string(b)converte uma fatia de bytes em uma string. Essas funções são comumente utilizadas em cenários de E/S de rede e criptografia. Observação:[]byteé adequado para modificação, enquantostringé adequado para uso somente leitura.
P: Posso usar caracteres chineses nos nomes das variáveis? R: Tecnicamente, sim (o Go suporta identificadores Unicode), mas isso é fortemente desaconselhado. Nomes de variáveis em chinês dificultam a colaboração entre equipes internacionais no código, e algumas ferramentas (como linters e IDEs) podem não reconhecê-los. Sempre use convenções de nomenclatura em inglês (camelCase ou sublinhados).
P: É possível obter o endereço de uma constante? R: Não. As constantes são definidas em tempo de compilação e não possuem um endereço de memória em tempo de execução.
&Piresultará em um erro de compilação.
📖 Resumo
- No Go, as variáveis podem ser declaradas usando
varou:=. Recomenda-se o uso de:=dentro de funções, enquantovaré obrigatório no nível do pacote. - 14 tipos básicos divididos em 4 categorias: inteiros (int/int8–64), números de ponto flutuante (float32/64), booleanos e cadeias de caracteres
- O mecanismo de valor zero é um recurso de segurança do Go: toda variável possui um valor padrão razoável, o que elimina ponteiros inválidos.
constdeclara constantes;iotaoferece uma maneira elegante de enumerar (códigos de status HTTP, máscaras de bits)- O Go proíbe conversões implícitas de tipo; elas devem ser explícitas (
int(x)/strconv.Itoa()) fmt.Printfutiliza especificadores de formato (%d,%f,%s,%v,%T,%q,%t) para controlar a saída- A linguagem Go, estática e fortemente tipada, detecta 90% dos erros na fase de compilação, tornando-se a pedra angular do desenvolvimento colaborativo de software
📝 Exercícios
-
Exercício básico (Dificuldade ⭐): Declare 5 variáveis (nome/idade/altura/éEstudante/média) usando as sintaxes
vare:=e imprima seus valores e tipos. -
Exercício avançado (Dificuldade ⭐⭐): Use
iotapara definir quatro constantes de códigos de status HTTP (200/404/500/503) e escreva uma funçãohandleRequest(code int)que retorne o texto correspondente (por exemplo, “OK”, “Não encontrado”, “Erro interno do servidor” ou “Serviço indisponível”) com base no código de status. -
Problema de desafio (Dificuldade ⭐⭐⭐): Escreva um conversor de unidades: receba como entrada uma temperatura em Fahrenheit e retorne a temperatura em Celsius (fórmula: C = (F - 32) × 5/9). Requisitos: (1) Use
fmt.Scanfpara ler a entrada; (2) Usestrconv.ParseFloatpara a conversão de tipos; (3) Trate entradas inválidas (retorne um erro).