Seu Primeiro Programa em Go: Um Guia Visual e Prático
Escreva, compile e rode o seu primeiro programa em Go e entenda cada linha: package main, import, func main, fmt.Println e Printf, go run vs. go build, os erros rígidos do compilador, gofmt, leitura do teclado, códigos de saída, compilação cruzada, medições reais e exercícios.

Nesta página
O Go (muitas vezes chamado de Golang) foi criado no Google para ser simples, rápido de compilar e agradável de usar em projetos grandes. Ele move o Docker, o Kubernetes e boa parte da nuvem. E o Olá, Mundo dele tem só sete linhas.
Neste guia você vai escrever, rodar e compilar o seu primeiro programa em Go e depois desmontá-lo linha por linha. Você vai imprimir textos e números, conhecer o compilador famoso por ser rígido (ele se recusa a compilar código com um import que não é usado!), deixar o gofmt formatar o seu código, ler dados do teclado e gerar programas para outros sistemas operacionais com um único comando. Exercícios fecham o artigo.
Todas as saídas e medições abaixo vêm de execuções reais com o Go 1.22 no Windows. As mensagens do compilador são em inglês; vamos traduzindo as importantes.
Preparando tudo
Baixe o Go em go.dev/dl (há instaladores para Windows, macOS e Linux; no Linux, veja também como instalar o Go no Linux) e confira num terminal:
$ go version
go version go1.22.5 windows/amd64O código Go vive em módulos: uma pasta com um arquivo go.mod que dá nome ao projeto. Crie uma pasta e um módulo para o seu primeiro programa:
1$ mkdir ola
2$ cd ola
3$ go mod init ola
4go: creating new go.mod: module olaOlá, Mundo!
Crie um arquivo chamado ola.go nessa pasta:
1package main
2
3import "fmt"
4
5func main() {
6 fmt.Println("Olá, Mundo!")
7}Rode:
$ go run .
Olá, Mundo!O go run . compila o programa da pasta atual e o roda na hora. Parabéns, você é um programador de Go! Agora vamos ver o que cada linha faz.

package main: todo arquivo Go começa dizendo a qual pacote pertence. O pacote chamadomainé especial: é ele que vira um programa executável.import "fmt": traz o pacotefmt(de format, formatar), da biblioteca padrão do Go, que cuida da impressão.func main(): declara uma função chamadamain. Como em C e C++, todo programa em Go começa nela.funcé a palavra-chave das funções, e o corpo vai entre{e}.fmt.Println("Olá, Mundo!"): chama a funçãoPrintlndo pacotefmt. Ela imprime os argumentos e pula uma linha (oln, de line).- Sem ponto e vírgula: o Go coloca um automaticamente no fim de cada linha. Já falamos disso.
Repare que main aparece em dois lugares: o pacote main e a função main. Um programa executável em Go precisa dos dois.
go run vs. go build
O go run é prático enquanto você escreve o código, mas ele compila o programa numa pasta temporária toda vez. O go build gera um executável que fica:
$ go build
$ ./ola
Olá, Mundo!No Windows, o go build cria o ola.exe (rode com .\ola.exe no PowerShell). Esse único arquivo é o programa inteiro: o computador que o roda não precisa ter o Go instalado.

Medimos os dois neste computador:
| O quê | Tempo |
|---|---|
Primeiro go build (cache de build vazio) | 8.719 ms |
| Build de novo (cache cheio) | 1.070 ms |
go run . | 1.506 ms |
Rodar o ola.exe já compilado | 25 ms |
O primeiro build é o lento porque o Go também compila os pacotes da biblioteca padrão que o seu programa usa e os guarda no cache. Depois disso, os builds levam cerca de um segundo, e o programa pronto começa em poucas dezenas de milissegundos. (O antivírus do Windows deixa cada passo mais lento aqui; no Linux, os mesmos passos costumam ser mais rápidos.)
Qual é o tamanho do programa?

Cerca de 1,9 MB para um Olá, Mundo. Parece muito, mas os programas em Go são ligados estaticamente: o runtime do Go, o coletor de lixo e todos os pacotes que você usa ficam dentro desse único arquivo. Copie-o para outro computador com o mesmo sistema operacional e ele simplesmente roda.
Imprimindo: Println, Print e Printf
O pacote fmt tem três funções de impressão que você vai usar o tempo todo:
1package main
2
3import "fmt"
4
5func main() {
6 fmt.Println("Olá,", "Gopher!", 2024)
7 fmt.Print("Sem pular linha. ")
8 fmt.Print("Mesma linha.\n")
9 fmt.Printf("%s tem %d anos e %.2f m de altura\n", "Ada", 36, 1.65)
10 fmt.Printf("%v %v %v\n", 42, "texto", true)
11 fmt.Printf("%T %T %T\n", 42, "texto", 3.14)
12 fmt.Println(7/2, 7.0/2, 7%2)
13}1Olá, Gopher! 2024
2Sem pular linha. Mesma linha.
3Ada tem 36 anos e 1.65 m de altura
442 texto true
5int string float64
63 3.5 1Printlnimprime os argumentos separados por espaços e pula uma linha.Printnão pula linha (use\n, a sequência de escape de nova linha, quando quiser).Printf(print formatted, imprimir formatado) preenche verbos num modelo:%spara string,%dpara número inteiro,%.2fpara decimal com 2 casas,%vpara qualquer valor no formato padrão e%Tpara o tipo de um valor.
A última linha é clássica: dividir dois números inteiros com / joga fora o resto (7/2 dá 3), um decimal o mantém (7.0/2 dá 3.5), e o % dá o resto (1). (O Go usa ponto, não vírgula, nos números.)
O compilador rígido do Go
O Go é famoso por se recusar a compilar código que a maioria das linguagens só avisaria. Um import sem uso é erro:
1package main
2
3import (
4 "fmt"
5 "os"
6)
7
8func main() {
9 fmt.Println("Olá, Mundo!")
10}$ go run .
# ola
.\main.go:5:2: "os" imported and not used("O os foi importado e não foi usado.") Uma variável sem uso também:
1package main
2
3import "fmt"
4
5func main() {
6 mensagem := "Olá, Mundo!"
7 fmt.Println("Oi!")
8}$ go run .
# ola
.\main.go:6:2: mensagem declared and not used
As mensagens seguem o padrão de sempre: arquivo:linha:coluna: problema. (No macOS e no Linux o caminho aparece como ./main.go.) Os criadores do Go fizeram esses erros de propósito: imports sem uso deixam lento o build de programas grandes, e variáveis sem uso muitas vezes indicam um bug. O conserto é simples: apague o que você não usa. Enquanto experimenta, dá para calar uma variável sem uso atribuindo-a ao identificador vazio, _ = mensagem.
Onde fica a chave, e os pontos e vírgulas invisíveis
Os comandos do Go terminam com ponto e vírgula, mas você nunca os digita: o compilador coloca um no fim de toda linha que parece terminada. Isso tem uma consequência. Coloque a chave de abertura numa linha sozinha:
1package main
2
3import "fmt"
4
5func main()
6{
7 fmt.Println("Olá, Mundo!")
8}$ go run .
# ola
.\main.go:6:1: syntax error: unexpected semicolon or newline before {A linha func main() parecia terminada, então o Go colocou um ponto e vírgula depois dela, e aí a { na linha seguinte não fez sentido ("ponto e vírgula ou nova linha inesperados antes da {"). No Go, a chave de abertura fica sempre na mesma linha.
Letras maiúsculas importam
1package main
2
3import "fmt"
4
5func main() {
6 fmt.println("Olá, Mundo!")
7}$ go run .
# ola
.\main.go:6:6: undefined: fmt.printlnNo Go, um nome que começa com letra maiúscula é exportado: outros pacotes podem usá-lo. O Println é exportado; um println minúsculo no fmt seria privado do pacote fmt. Esse é todo o sistema de visibilidade do Go: nada de palavras-chave public ou private, só a primeira letra.
Tem que ser package main
Se o pacote tiver outro nome, o Go trata a pasta como uma biblioteca, algo que outros programas importam, e não um programa que dá para rodar:
$ go run .
package ola is not a main packageDeixe o gofmt formatar o seu código
O Go vem com um formatador oficial, e quase todo projeto em Go o usa. Eis um código digitado sem capricho:
1package main
2import "fmt"
3func main(){
4fmt.Println("Olá, Mundo!")
5 for i:=0;i<3;i++{fmt.Println(i)}
6}Rodar gofmt baguncado.go (ou go fmt no módulo inteiro) imprime:
1package main
2
3import "fmt"
4
5func main() {
6 fmt.Println("Olá, Mundo!")
7 for i := 0; i < 3; i++ {
8 fmt.Println(i)
9 }
10}Tabulações para indentar, espaços em volta dos operadores, um comando por linha. Como o código de todo mundo é formatado do mesmo jeito, não há o que discutir nas revisões de código, e todo projeto em Go parece familiar. A maioria dos editores roda o gofmt automaticamente ao salvar.
Lendo dados do teclado
O fmt.Scan lê valores digitados pelo usuário e os guarda em variáveis. Você passa o endereço da variável com & para o Scan poder preenchê-la:
1package main
2
3import "fmt"
4
5func main() {
6 var primeiro, segundo int
7 fmt.Print("Primeiro número: ")
8 fmt.Scan(&primeiro)
9 fmt.Print("Segundo número: ")
10 fmt.Scan(&segundo)
11 fmt.Printf("%d + %d = %d\n", primeiro, segundo, primeiro+segundo)
12}Uma execução de exemplo, em que os números depois dos dois-pontos são digitados pelo usuário:
Primeiro número: 12
Segundo número: 30
12 + 30 = 42var primeiro, segundo int declara duas variáveis inteiras. (O próximo artigo da série fala de variáveis a fundo.) Para ler uma linha inteira, com espaços, use um bufio.Reader:
1package main
2
3import (
4 "bufio"
5 "fmt"
6 "os"
7 "strings"
8)
9
10func main() {
11 leitor := bufio.NewReader(os.Stdin)
12 fmt.Print("Qual é o seu nome? ")
13 linha, _ := leitor.ReadString('\n')
14 nome := strings.TrimSpace(linha)
15 fmt.Printf("Olá, %s! Bem-vinda ao Go.\n", nome)
16}Qual é o seu nome? Ada Lovelace
Olá, Ada Lovelace! Bem-vinda ao Go.O ReadString('\n') lê até o Enter, inclusive, então o strings.TrimSpace tira o fim de linha (no Windows são dois caracteres, \r\n). O _ ignora o segundo valor que o ReadString devolve, um erro; funções em Go muitas vezes devolvem um resultado e um erro, um padrão que você vai ver em todo lugar.
Códigos de saída
Quando a main de um programa em Go termina, ele sai com o código 0, que quer dizer sucesso. Para informar uma falha, chame o os.Exit com outro número:
1package main
2
3import (
4 "fmt"
5 "os"
6)
7
8func main() {
9 fmt.Println("Algo deu errado!")
10 os.Exit(3)
11}1$ go build -o falha
2$ ./falha
3Algo deu errado!
4$ echo $?
53Scripts e ferramentas de build conferem esse número para decidir se continuam. (No PowerShell, use $LASTEXITCODE em vez de $?. E repare que o go run mostra uma saída diferente de zero com uma linha extra, exit status 3.)
Compile para qualquer sistema operacional
Um dos melhores truques do Go: defina duas variáveis de ambiente, GOOS (o sistema operacional de destino) e GOARCH (o processador), e o go build gera um programa para outro sistema, sem ferramenta extra nenhuma. Do mesmo computador com Windows:
1$ GOOS=linux GOARCH=amd64 go build -o ola-linux
2$ GOOS=darwin GOARCH=arm64 go build -o ola-mac
3$ file ola-linux
4ola-linux: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, …O ola-linux roda num servidor Linux de 64 bits, e o ola-mac num Mac com Apple Silicon. (Essa é a sintaxe do Bash; no PowerShell, defina $env:GOOS = "linux" e $env:GOARCH = "amd64" antes.) O go tool dist list mostra todas as combinações suportadas, mais de 40.
Sua vez: pratique
Tente fazer estes antes de espiar as respostas. Coloque cada programa na sua própria pasta com go mod init e rode com go run ..
Exercício 1: Adivinhe a saída (aquecimento). O que exatamente isto imprime?
1package main
2
3import "fmt"
4
5func main() {
6 fmt.Print("Go")
7 fmt.Println("pher", 1, 2)
8 fmt.Printf("%d%%\n", 100)
9 fmt.Println(10/4, 10.0/4)
10}Exercício 2: Conserte o programa. Ele tem três erros que impedem o build. Ache-os rodando o programa e lendo as mensagens.
1package main
2
3import (
4 "fmt"
5 "strings"
6)
7
8func main()
9{
10 fmt.println("Aprendendo Go")
11}Exercício 3: Desenhe uma caixa. Escreva um programa que imprima exatamente isto:
+--------+
| Go! |
+--------+Exercício 4: Um recibo. Use o Printf para imprimir uma linha para 3 cafés a 2.5 cada, com o total formatado com 2 casas decimais: 3 x café @ 2.50 = 7.50.
Exercício 5: Conversor de temperatura (desafio). Leia uma temperatura em graus Celsius como número inteiro e imprima em Fahrenheit com uma casa decimal, usando F = C × 9 / 5 + 32. Para 37, deve imprimir 98.6.
Quiz rápido
- De qual pacote e de qual função todo programa executável em Go precisa?
- Qual é a diferença entre
go runego build? - Por que o Go não compila um programa com um import sem uso?
- Por que a
{de abertura tem que ficar na mesma linha? - Por que é
fmt.Println, e nãofmt.println?
Respostas
Exercício 1: O Print não pula linha, então o pher continua na mesma linha, e o Println põe espaços entre os argumentos. O %% imprime um sinal de porcentagem. 10/4 é divisão de inteiros:
1package main
2
3import "fmt"
4
5func main() {
6 fmt.Print("Go")
7 fmt.Println("pher", 1, 2)
8 fmt.Printf("%d%%\n", 100)
9 fmt.Println(10/4, 10.0/4)
10}Gopher 1 2
100%
2 2.5Exercício 2: O import strings sem uso, a { sozinha na linha e o println minúsculo. Consertado:
1package main
2
3import "fmt"
4
5func main() {
6 fmt.Println("Aprendendo Go")
7}Aprendendo Go(O Go mostra primeiro o erro da chave. É um erro de sintaxe, então o compilador para antes de conferir imports e nomes. Conserte, rode de novo, e os próximos erros aparecem.)
Exercício 3: Um Println por linha:
1package main
2
3import "fmt"
4
5func main() {
6 fmt.Println("+--------+")
7 fmt.Println("| Go! |")
8 fmt.Println("+--------+")
9}+--------+
| Go! |
+--------+Exercício 4: %d para a quantidade, %s para o nome e %.2f para os dois preços:
1package main
2
3import "fmt"
4
5func main() {
6 quantidade := 3
7 preco := 2.5
8 fmt.Printf("%d x %s @ %.2f = %.2f\n", quantidade, "café", preco, float64(quantidade)*preco)
9}3 x café @ 2.50 = 7.50float64(quantidade) converte o inteiro num número decimal: o Go nunca mistura int e float64 numa conta automaticamente, mais uma das suas regras rígidas.
Exercício 5: Converta para float64 antes de dividir para as casas decimais sobreviverem:
1package main
2
3import "fmt"
4
5func main() {
6 var celsius int
7 fmt.Print("Temperatura em Celsius: ")
8 fmt.Scan(&celsius)
9 fahrenheit := float64(celsius)*9/5 + 32
10 fmt.Printf("%d C = %.1f F\n", celsius, fahrenheit)
11}Temperatura em Celsius: 37
37 C = 98.6 FTemperatura em Celsius: -40
-40 C = -40.0 FQuiz: (1) Do pacote main e da função main. (2) O go run compila numa pasta temporária e roda o programa na hora; o go build cria um arquivo executável que fica e pode ser copiado para outros computadores. (3) Os criadores do Go fizeram do import sem uso um erro para manter os builds rápidos e o código limpo; apague o import (ou use-o). (4) O Go coloca um ponto e vírgula no fim de uma linha que parece terminada, então uma { na linha seguinte viria depois de um ponto e vírgula, um erro de sintaxe. (5) Nomes que começam com letra maiúscula são exportados pelo pacote; nomes minúsculos são privados dele.
Cola rápida
| Eu quero… | Escreva |
|---|---|
| Começar um módulo | go mod init ola |
| Rodar enquanto desenvolve | go run . |
| Gerar um executável | go build (ou go build -o nome) |
| O esqueleto de um programa | package main + func main() { … } |
| Usar um pacote | import "fmt" (vários: import ( "fmt" "os" )) |
| Imprimir pulando linha | fmt.Println("Oi", nome) |
| Imprimir um modelo | fmt.Printf("%s tem %d\n", nome, idade) |
| Ler um valor | fmt.Scan(&idade) |
| Informar falha | os.Exit(1) |
| Formatar o código | gofmt -w ola.go ou go fmt ./... |
| Compilar para Linux | GOOS=linux GOARCH=amd64 go build |
Resumindo
Sete linhas, e agora você sabe o que cada uma faz:
- Um programa executável em Go é
package maincom umafunc main(), dentro de um módulo criado pelogo mod init. go run .compila e roda num passo só;go buildgera um executável único e independente (cerca de 1,9 MB para o Olá, Mundo, no nosso build).fmt.Println,PrintePrintfcobrem quase toda a impressão.- O compilador do Go é rígido: imports e variáveis sem uso são erros, a
{fica na mesma linha e as letras maiúsculas decidem o que um pacote exporta. - O
gofmtformata todo programa em Go do mesmo jeito. - Um único comando faz compilação cruzada para Linux, macOS ou Windows.
Próximos passos na série: como instalar o Go no Linux e como definir uma variável em Go. Para ver o quadro geral, leia O Que É a Linguagem de Programação Go?
Leia a seguir

O Que É a Linguagem de Programação Rust? Um Guia Simples da Linguagem Rápida Que Não Deixa Você Travar
Um guia simples e sem jargões sobre o Rust, a linguagem tão rápida quanto o C que impede famílias inteiras de erros de memória antes de o programa rodar. Entenda a ideia de posse, por que gigantes da tecnologia o adotam e onde ele é usado.

O Que É a Linguagem de Programação Go? Um Guia Simples da Linguagem da Nuvem
Um guia simples e sem jargões sobre o Go, a linguagem simples e rápida que o Google criou para a nuvem. Entenda o que são goroutines, por que um programa Go é um arquivo só e como o Go passou a mover o Docker, o Kubernetes e boa parte da internet.

O Que É a Linguagem de Programação Ruby? Um Guia Simples da Linguagem Feita para a Felicidade
Um guia simples e sem jargões sobre o Ruby, a linguagem de programação feita para deixar os programadores felizes. Entenda por que o código Ruby parece inglês, como o Ruby on Rails move sites como GitHub e Shopify, e onde o Ruby brilha.
Comentários
Seja gentil e específico. Comentários com links de contas novas aparecem depois da análise de um moderador.