Folha de dicas de Golang

Comandos e construções úteis em golang

Conteúdo da página

Aqui está a estrutura básica de um programa Go, padrões de tratamento de erros e comparação entre canais e goroutines.

bunnies around golang sign

Cheatsheet da Linguagem Go

Sintaxe Básica

Declaração de Pacote

package main

Importar Pacotes

import "fmt"
import (
    "fmt"
    "math"
)

Função Principal

func main() {
    // Seu código aqui
}

Variáveis e Tipos

Declaração de Variáveis

var name string
var age int = 25
x := 10 // Declaração curta

Tipos Básicos

  • bool
  • string
  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • float32, float64
  • complex64, complex128

Estruturas de Controle

Instrução If

if x > 0 {
    // código
} else if x < 0 {
    // código
} else {
    // código
}

Laço For

for i := 0; i < 10; i++ {
    // código
}

Laço Range

for index, value := range collection {
    // código
}

Instrução Switch

switch variable {
case value1:
    // código
case value2:
    // código
default:
    // código
}

Funções

Declaração de Função

func functionName(param1 type1, param2 type2) returnType {
    // código
    return value
}

Vários Valores de Retorno

func divideAndRemainder(x, y int) (int, int) {
    return x / y, x % y
}

Estruturas de Dados

Arrays

var numbers int
numbers := int{1, 2, 3, 4, 5}

Slices

slice := []int{1, 2, 3}
slice := make([]int, 3, 5)

Maps

m := make(map[string]int)
m["key"] = value

Structs

type Person struct {
    Name string
    Age  int
}
p := Person{Name: "Alice", Age: 30}

Métodos

Declaração de Método

func (r Rectangle) Area() float64 {
    return r.width * r.height
}

Interfaces

Declaração de Interface

type Shape interface {
    Area() float64
}

Concorrência

Goroutines

go functionName()

Canais

ch := make(chan int)
ch <- value  // Enviar
value := <-ch  // Receber

Tratamento de Erros

Verificação de Erros

if err != nil {
    // Tratar erro
}

Defer

defer file.Close()

Testes

Função de Teste

func TestFunction(t *testing.T) {
    // Código de teste
}

Este cheatsheet cobre as construções e comandos mais essenciais da linguagem Go. Ele inclui sintaxe básica, estruturas de controle, funções, estruturas de dados, métodos, interfaces, primitivas de concorrência e tratamento de erros. Lembre-se de que a Go enfatiza simplicidade e legibilidade, então essas construções formam a base para escrever código Go eficiente e claro.

Tratamento de Erros em Go

O tratamento de erros em Go é direto e explícito, enfatizando clareza e robustez. Aqui estão as técnicas principais para lidar com erros em Go:

  1. Retornar erros como valores: Funções que podem falhar devem retornar um erro como seu último valor de retorno. Por exemplo:
func Hello(name string) (string, error) {
    if name == "" {
        return "", errors.New("empty name")
    }
    message := fmt.Sprintf("Hi, %v. Welcome!", name)
    return message, nil
}
  1. Sempre verificar erros: Após chamar uma função que retorna um erro, verifique imediatamente se o erro não é nulo. Por exemplo:
result, err := SomeFunction()
if err != nil {
    // Tratar o erro
    log.Fatal(err)
}
  1. Usar envoltura de erros: Ao propagar erros para cima da pilha de chamadas, envolva-os para adicionar contexto usando fmt.Errorf() com o verbo %w. Por exemplo:
f, err := os.Open(path)
if err != nil {
    return nil, fmt.Errorf("open failed: %w", err)
}
  1. Utilizar defer para limpeza: Use defer para garantir que recursos sejam fechados ou limpos corretamente, mesmo que ocorra um erro.

  2. Criar tipos de erro personalizados: Implemente a interface error para tipos de erro personalizados para fornecer informações de erro mais detalhadas.

  3. Usar o pacote errors: Aproveite funções como errors.New() para criar mensagens de erro simples, e errors.Is() ou errors.As() para verificação e conversão de tipos de erro.

  4. Evitar o uso de panic: Reserve panic para situações verdadeiramente irreparáveis. O tratamento normal de erros deve usar valores de retorno.

  5. Fornecer informações de erro explícitas: Faça com que as mensagens de erro sejam claras e informativas para ajudar no depuração e resolução de problemas.

Ao seguir essas práticas, você pode criar programas Go robustos que lidam com erros de forma eficaz e mantêm a clareza do código.

Boas Práticas para Goroutines e Canais em Go

Uso Eficiente de Goroutines

  1. Evite a criação excessiva de goroutines: Crie goroutines com juízo, considerando a natureza da tarefa e se ela se beneficia da execução paralela.

  2. Sincronização adequada: Use mecanismos de sincronização, como canais ou grupos de espera, para gerenciar goroutines de forma eficaz e evitar desperdício de recursos.

  3. Considere a natureza da tarefa: Avalie se uma tarefa realmente se beneficia da execução concorrente antes de usar goroutines.

Uso Eficiente de Canais

  1. Escolha o tipo de canal apropriado: Use canais não bufferizados para sincronização e canais bufferizados quando precisar desacoplar operações de envio e recebimento.

  2. Capacidade do buffer: Ao usar canais bufferizados, considere cuidadosamente o tamanho do buffer para equilibrar desempenho e uso de recursos.

  3. Feche canais corretamente: Certifique-se de fechar canais quando não houver mais dados a serem enviados para evitar deadlocks e vazamentos de recursos.

Padrões de Concorrência

  1. Padrão de pool de trabalhadores: Implemente pools de trabalhadores usando goroutines e canais para distribuição eficiente de tarefas e coleta de resultados.

  2. Padrão produtor-consumidor: Use goroutines como produtores e consumidores, com canais facilitando o fluxo de dados entre eles.

Tratamento de Erros e Gerenciamento de Recursos

  1. Use defer para limpeza: Empregue declarações defer para garantir a limpeza adequada de recursos, mesmo na presença de erros.

  2. Trate panics: Implemente recover() em goroutines de longa execução para evitar que o programa inteiro caia em um panic em uma única goroutine.

Comunicação e Sincronização

  1. Prefira canais a memória compartilhada: Use canais para comunicação entre goroutines para evitar condições de corrida e simplificar a sincronização.

  2. Use select para múltiplos canais: Empregue a instrução select para lidar com múltiplas operações de canal de forma concorrente.

Considerações de Desempenho

  1. Limite operações concorrentes: Use semáforos ou pools de trabalhadores para limitar o número de operações concorrentes e evitar exaustão de recursos.

  2. Evite otimização prematura: Profile seu código para identificar gargalos antes de aplicar otimizações de concorrência.

Testes e Depuração

  1. Use o detector de corridas: Execute regularmente seus testes com a bandeira -race para detectar corridas de dados.

  2. Escreva testes concorrentes: Crie testes que exercitem especificamente os caminhos de código concorrente para garantir a confiabilidade.

Ao seguir essas boas práticas, você pode aproveitar efetivamente o modelo de concorrência da Go, tornando seus programas mais eficientes, mantiveis e menos propensos a problemas comuns relacionados à concorrência.

Veja outros artigos do blog técnico.

Atualizando o golang no Linux

  1. vá e baixe a nova versão: https://go.dev/doc/install
  2. remova a antiga:
sudo rm -rf /usr/local/go
  1. instale a nova:
cd Downloads
sudo tar -C /usr/local -xzf go1.24.3.linux-amd64.tar.gz