Go: Simplicidade e Performance

Aprenda Go, a linguagem do Google para sistemas escaláveis e concorrência


Go: Simplicidade e Performance
1 Carregando...

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

  1. Compilação Rápida - Compile projetos grandes em segundos
  2. Garbage Collection - Gerenciamento automático de memória eficiente
  3. Concorrência Nativa - Goroutines e channels facilitam programação paralela
  4. Tipagem Estática - Com inferência de tipos para código conciso
  5. Ferramentas Integradas - Formatação, testes e build nativos
  6. 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

ComandoPropósito
go buildCompila o projeto
go runCompila e executa
go testExecuta testes
go fmtFormata código
go mod initInicializa módulo
go getAdiciona 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!