Seu primeiro programa: Hello World e o compilador

1. Configurando o ambiente para o primeiro programa

Antes de escrever qualquer linha de código em Go, é essencial configurar o ambiente corretamente. A primeira decisão importante é sobre a estrutura de diretórios.

Historicamente, Go utilizava o GOPATH, um diretório único onde todos os projetos e suas dependências residiam. A estrutura era rígida: $GOPATH/src/github.com/usuario/projeto. Hoje, o ecossistema evoluiu para o sistema de módulos (introduzido no Go 1.11), que elimina a necessidade do GOPATH para projetos individuais.

Para iniciar, crie uma pasta para seu projeto e acesse-a:

mkdir hello-world
cd hello-world

Agora, inicialize um módulo Go:

go mod init hello-world

Esse comando cria o arquivo go.mod, que define o nome do módulo e gerencia as dependências. O nome do módulo (aqui hello-world) será usado internamente para importar pacotes.

Quanto ao editor, qualquer IDE moderna funciona bem com Go. Visual Studio Code com a extensão oficial da Go é a escolha mais popular, oferecendo autocomplete, linting e integração com ferramentas essenciais como:

  • go fmt — formata automaticamente o código seguindo o padrão da linguagem
  • go vet — analisa o código em busca de suspeitas de bugs

2. Escrevendo o clássico Hello World

Com o ambiente pronto, crie o arquivo main.go com o seguinte conteúdo:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

Vamos analisar cada parte desse código:

  • package main: Todo arquivo .go pertence a um pacote. O pacote main é especial — ele define que este código pode ser executado como um programa independente. Sem essa declaração, o compilador não geraria um executável.

  • import "fmt": O pacote fmt (format) fornece funções para entrada e saída formatada. Aqui usamos Println para exibir texto no terminal.

  • func main(): Esta é a função de entrada obrigatória de todo programa Go. A execução sempre começa aqui. Note que main não recebe parâmetros e não retorna valor (diferente de C, por exemplo).

  • fmt.Println("Hello, World!"): A função Println imprime o argumento seguido de uma quebra de linha. As aspas duplas delimitam a string literal.

3. Entendendo o fluxo do compilador Go

Go é uma linguagem compilada, não interpretada. Diferente de Python ou JavaScript, que dependem de um interpretador em tempo de execução, Go traduz seu código diretamente para instruções de máquina nativas do sistema operacional alvo.

O compilador Go (go build) realiza várias etapas:

  1. Análise léxica e sintática: Verifica se o código segue a gramática da linguagem
  2. Verificação de tipos: Garante que operações entre tipos incompatíveis não ocorram
  3. Otimizações: Elimina código morto, inlineia funções pequenas, otimiza loops
  4. Geração de código nativo: Produz binário específico para a arquitetura (amd64, arm64) e sistema operacional (Linux, Windows, macOS)

Uma característica marcante é que o compilador Go é extremamente rápido. Isso é alcançado por um design que simplifica a análise de dependências e evita otimizações agressivas que atrasariam a compilação.

4. Compilando o programa: passo a passo

Para compilar seu programa, execute:

go build

Isso gera um binário executável com o nome do diretório (no nosso caso, hello-world). Você pode especificar um nome diferente:

go build -o meu-programa

O binário gerado é estaticamente vinculado — ele contém tudo que precisa para executar, incluindo o runtime Go. Não depende de bibliotecas externas no sistema. Isso resulta em binários maiores (cerca de 1-2 MB para um Hello World), mas extremamente portáteis.

Execute o binário compilado:

./hello-world

Saída:

Hello, World!

Para compilar para outro sistema operacional, use variáveis de ambiente:

GOOS=windows GOARCH=amd64 go build -o hello.exe
GOOS=linux GOARCH=arm64 go build

Isso permite criar binários para diferentes plataformas sem modificar o código.

5. Executando sem compilar: o comando go run

O comando go run combina compilação e execução em um único passo:

go run main.go

Saída:

Hello, World!

Internamente, go run compila o código em um diretório temporário, executa o binário e o descarta. Isso é útil durante o desenvolvimento para testes rápidos.

Diferenças práticas:

go build go run
Gera binário permanente Compila e executa, depois descarta
Ideal para distribuição Ideal para desenvolvimento
Único comando para executar depois Precisa recompilar toda vez
Binário pode ser copiado para outras máquinas Não gera artefato reutilizável

Para projetos reais, use go run durante o desenvolvimento e go build quando precisar distribuir o programa.

6. Explorando o código compilado

Vamos examinar o binário gerado:

file hello-world
ls -lh hello-world

No Linux, a saída típica é:

hello-world: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
-rwxr-xr-x 1 user user 1.8M Mar 15 10:30 hello-world

Observe que o binário é statically linked (vinculado estaticamente). Diferente de programas em C que geralmente dependem de bibliotecas dinâmicas (.so ou .dll), um binário Go contém todo o runtime necessário.

Isso significa que você pode copiar o binário para qualquer máquina com o mesmo sistema operacional e arquitetura, e ele executará sem precisar instalar Go ou qualquer outra dependência. Não há máquina virtual (como a JVM do Java) — o runtime é embutido diretamente no executável.

7. Erros comuns no primeiro programa

Pacote main não declarado

package minhaapp

func main() {
    fmt.Println("Hello")
}

Erro: runtime.main_main·f: function main is undeclared in the main package. O compilador espera que o pacote seja main para gerar um executável.

Função main ausente

package main

import "fmt"

func init() {
    fmt.Println("Hello")
}

Erro: runtime.main_main·f: function main is undeclared in the main package. A função init existe e é executada automaticamente, mas não substitui a main.

Import não utilizado

package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println("Hello")
}

Erro: imported and not used: "os". Go não permite imports não utilizados. Isso evita código morto e mantém as dependências limpas.

Espaços em branco e formatação

Go impõe um estilo de formatação único. Execute go fmt ./... no diretório do projeto para corrigir automaticamente indentação, espaçamento e alinhamento. Isso garante consistência em todo o ecossistema Go.


Com este primeiro programa, você já percorreu o ciclo completo: configurou o ambiente, escreveu código, compilou, executou e aprendeu a lidar com erros comuns. Esse conhecimento forma a base para explorar conceitos mais avançados da linguagem.

Referências