Go: Simplicidade e Performance
Aprenda Go, a linguagem do Google para sistemas escaláveis e concorrência
Go: Simplicidade e Performance
Go (ou Golang) é uma linguagem de programação criada pelo Google em 2009. Projetada por Rob Pike, Ken Thompson e Robert Griesemer, Go combina a eficiência de linguagens compiladas com a facilidade de uso de linguagens dinâmicas. É especialmente popular para construir serviços web, ferramentas de linha de comando e sistemas distribuídos.
Por que Go? Go é usado por empresas como Google, Uber, Dropbox, Docker e Kubernetes. Sua simplicidade e excelente suporte a concorrência a tornam ideal para microsserviços e sistemas cloud-native.
Características Distintivas
- Compilação Rápida - Compile projetos grandes em segundos
- Garbage Collection - Gerenciamento automático de memória eficiente
- Concorrência Nativa - Goroutines e channels facilitam programação paralela
- Tipagem Estática - Com inferência de tipos para código conciso
- Ferramentas Integradas - Formatação, testes e build nativos
- Single Binary - Compile para um único executável sem dependências
Fundamentos
Tipos de Dados e Variáveis
package main
import "fmt"
func main() {
// Declaração explícita
var nome string = "Maria"
var idade int = 25
var altura float64 = 1.68
var ativo bool = true
// Declaração curta (inferência de tipo)
email := "[email protected]"
contador := 0
// Constantes
const pi = 3.14159
const (
StatusPendente = iota // 0
StatusAprovado // 1
StatusRejeitado // 2
)
// Arrays (tamanho fixo)
var numeros [5]int = [5]int{1, 2, 3, 4, 5}
// Slices (tamanho dinâmico)
frutas := []string{"maçã", "banana", "laranja"}
frutas = append(frutas, "uva")
// Maps
usuarios := map[string]int{
"alice": 25,
"bob": 30,
}
usuarios["carol"] = 28
fmt.Println(nome, idade, altura, ativo, email)
fmt.Println(numeros, frutas, usuarios)
}
Estruturas de Controle
package main
import "fmt"
func main() {
// If/else
idade := 18
if idade >= 18 {
fmt.Println("Maior de idade")
} else if idade >= 13 {
fmt.Println("Adolescente")
} else {
fmt.Println("Criança")
}
// If com declaração inicial
if valor := obterValor(); valor > 0 {
fmt.Println("Valor positivo:", valor)
}
// For (único loop em Go)
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// For como while
contador := 0
for contador < 10 {
contador++
}
// For range
frutas := []string{"maçã", "banana", "laranja"}
for indice, fruta := range frutas {
fmt.Printf("%d: %s\n", indice, fruta)
}
// Switch
dia := "segunda"
switch dia {
case "segunda", "terça", "quarta", "quinta", "sexta":
fmt.Println("Dia útil")
case "sábado", "domingo":
fmt.Println("Fim de semana")
default:
fmt.Println("Dia inválido")
}
// Switch sem expressão
hora := 14
switch {
case hora < 12:
fmt.Println("Bom dia")
case hora < 18:
fmt.Println("Boa tarde")
default:
fmt.Println("Boa noite")
}
}
func obterValor() int {
return 42
}
Funções
package main
import (
"errors"
"fmt"
)
// Função simples
func saudar(nome string) string {
return fmt.Sprintf("Olá, %s!", nome)
}
// Múltiplos retornos
func dividir(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("divisão por zero")
}
return a / b, nil
}
// Retornos nomeados
func calcular(a, b int) (soma, produto int) {
soma = a + b
produto = a * b
return // retorno implícito
}
// Variadic function
func somar(numeros ...int) int {
total := 0
for _, n := range numeros {
total += n
}
return total
}
// Função como valor
func aplicar(fn func(int) int, valor int) int {
return fn(valor)
}
// Closure
func contador() func() int {
count := 0
return func() int {
count++
return count
}
}
// Defer
func processarArquivo() {
fmt.Println("Abrindo arquivo...")
defer fmt.Println("Fechando arquivo...") // Executa ao final
fmt.Println("Processando...")
}
func main() {
fmt.Println(saudar("Maria"))
resultado, err := dividir(10, 2)
if err != nil {
fmt.Println("Erro:", err)
} else {
fmt.Println("Resultado:", resultado)
}
fmt.Println(somar(1, 2, 3, 4, 5))
dobrar := func(x int) int { return x * 2 }
fmt.Println(aplicar(dobrar, 5))
cont := contador()
fmt.Println(cont(), cont(), cont())
processarArquivo()
}
Structs e Métodos
package main
import "fmt"
// Struct
type Usuario struct {
ID int
Nome string
Email string
Ativo bool
}
// Método (receiver por valor)
func (u Usuario) Saudar() string {
return fmt.Sprintf("Olá, %s!", u.Nome)
}
// Método (receiver por ponteiro - pode modificar)
func (u *Usuario) Desativar() {
u.Ativo = false
}
// Construtor (convenção)
func NovoUsuario(id int, nome, email string) *Usuario {
return &Usuario{
ID: id,
Nome: nome,
Email: email,
Ativo: true,
}
}
// Embedding (composição)
type Admin struct {
Usuario // Embedded
Permissoes []string
}
func (a Admin) ListarPermissoes() {
fmt.Println("Permissões:", a.Permissoes)
}
func main() {
// Criando struct
u1 := Usuario{ID: 1, Nome: "Maria", Email: "[email protected]", Ativo: true}
u2 := NovoUsuario(2, "João", "[email protected]")
fmt.Println(u1.Saudar())
fmt.Println(u2.Saudar())
u2.Desativar()
fmt.Println("João ativo:", u2.Ativo)
// Admin com embedding
admin := Admin{
Usuario: Usuario{ID: 3, Nome: "Carlos", Ativo: true},
Permissoes: []string{"criar", "editar", "deletar"},
}
fmt.Println(admin.Saudar()) // Método herdado
admin.ListarPermissoes()
}
Interfaces
package main
import (
"fmt"
"math"
)
// Interface
type Forma interface {
Area() float64
Perimetro() float64
}
// Implementação: Retangulo
type Retangulo struct {
Largura, Altura float64
}
func (r Retangulo) Area() float64 {
return r.Largura * r.Altura
}
func (r Retangulo) Perimetro() float64 {
return 2 * (r.Largura + r.Altura)
}
// Implementação: Circulo
type Circulo struct {
Raio float64
}
func (c Circulo) Area() float64 {
return math.Pi * c.Raio * c.Raio
}
func (c Circulo) Perimetro() float64 {
return 2 * math.Pi * c.Raio
}
// Função que aceita interface
func descreverForma(f Forma) {
fmt.Printf("Área: %.2f, Perímetro: %.2f\n", f.Area(), f.Perimetro())
}
// Interface vazia (qualquer tipo)
func imprimir(v interface{}) {
fmt.Printf("Tipo: %T, Valor: %v\n", v, v)
}
// Type assertion
func processar(v interface{}) {
if s, ok := v.(string); ok {
fmt.Println("É uma string:", s)
} else {
fmt.Println("Não é uma string")
}
}
func main() {
ret := Retangulo{Largura: 10, Altura: 5}
cir := Circulo{Raio: 7}
descreverForma(ret)
descreverForma(cir)
imprimir(42)
imprimir("hello")
imprimir(true)
}
Concorrência
package main
import (
"fmt"
"sync"
"time"
)
// Goroutine básica
func tarefa(id int) {
for i := 0; i < 3; i++ {
fmt.Printf("Tarefa %d: iteração %d\n", id, i)
time.Sleep(100 * time.Millisecond)
}
}
// Channels
func produtor(ch chan<- int) {
for i := 0; i < 5; i++ {
ch <- i
time.Sleep(100 * time.Millisecond)
}
close(ch)
}
func consumidor(ch <-chan int) {
for valor := range ch {
fmt.Println("Recebido:", valor)
}
}
// Select
func seletor(ch1, ch2 chan string) {
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("Canal 1:", msg1)
case msg2 := <-ch2:
fmt.Println("Canal 2:", msg2)
case <-time.After(1 * time.Second):
fmt.Println("Timeout!")
}
}
}
// WaitGroup
func comWaitGroup() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Printf("Worker %d executando\n", id)
time.Sleep(time.Second)
}(i)
}
wg.Wait()
fmt.Println("Todos os workers finalizaram")
}
func main() {
// Goroutines
go tarefa(1)
go tarefa(2)
time.Sleep(500 * time.Millisecond)
// Channels
ch := make(chan int)
go produtor(ch)
consumidor(ch)
// WaitGroup
comWaitGroup()
}
Ferramentas Essenciais
| Comando | Propósito |
|---|---|
go build | Compila o projeto |
go run | Compila e executa |
go test | Executa testes |
go fmt | Formata código |
go mod init | Inicializa módulo |
go get | Adiciona dependência |
Checklist de Aprendizado
- Dominar tipos básicos e estruturas de dados
- Entender funções, métodos e interfaces
- Aprender goroutines e channels
- Estudar patterns de concorrência
- Praticar com APIs REST
- Explorar testing nativo
- Construir um microserviço
Recursos Essenciais
Citação
“Go é projetada para pessoas que escrevem e mantêm sistemas de software grandes.” - Rob Pike
Go é a escolha perfeita quando você precisa de performance, simplicidade e excelente suporte a concorrência!