Menu
Coddy logo textTech

Erros Sentinela

Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 55 de 107.

Um erro sentinela é uma variável de erro predefinida em nível de pacote que representa uma condição de erro específica. Ao contrário de criar novos erros a cada vez com errors.New, os erros sentinela são declarados uma única vez e reutilizados em todo o seu código.

Você define erros sentinela como variáveis de nível de pacote, geralmente com nomes começando com Err:

package user

import "errors"

var (
    ErrNotFound     = errors.New("user not found")
    ErrInvalidEmail = errors.New("invalid email address")
    ErrDuplicate    = errors.New("user already exists")
)

As funções retornam estes erros predefinidos quando condições específicas ocorrem:

func FindUser(id int) (*User, error) {
    user, exists := users[id]
    if !exists {
        return nil, ErrNotFound
    }
    return user, nil
}

O poder dos erros sentinela é que os chamadores podem verificar condições de erro específicas comparando os valores de erro diretamente:

user, err := FindUser(42)
if err == ErrNotFound {
    fmt.Println("Creating new user...")
} else if err != nil {
    fmt.Println("Unexpected error:", err)
}

A biblioteca padrão do Go usa erros sentinela extensivamente. Por exemplo, io.EOF sinaliza o fim da entrada, e sql.ErrNoRows indica um resultado de consulta vazio. Este padrão cria um contrato claro entre os pacotes e seus usuários sobre quais erros esperar.

No entanto, verificações de igualdade simples falham quando os erros são envolvidos. Na próxima lição, você aprenderá como errors.Is() resolve esse problema verificando toda a cadeia de erros.

challenge icon

Desafio

Fácil

Vamos criar um sistema de gerenciamento de inventário que usa erros sentinela para comunicar condições específicas de falha. Você definirá variáveis de erro no nível do pacote que os chamadores poderão verificar para tratar diferentes cenários adequadamente.

Você organizará seu código em dois arquivos:

  • inventory.go: Crie um sistema de inventário com erros sentinela predefinidos para casos comuns de falha.

    Defina três erros sentinela no nível do pacote:

    • ErrItemNotFound com a mensagem "item not found in inventory"
    • ErrOutOfStock com a mensagem "item is out of stock"
    • ErrInsufficientQuantity com a mensagem "insufficient quantity available"

    Crie uma struct Inventory que contenha um mapa de nomes de itens para suas quantidades. Implemente estes métodos:

    • NewInventory() *Inventory - cria um inventário vazio
    • AddItem(name string, quantity int) - adiciona ou atualiza a quantidade de um item
    • GetQuantity(name string) (int, error) - retorna a quantidade de um item ou ErrItemNotFound se ele não existir
    • Purchase(name string, quantity int) error - tenta comprar itens. Retorne ErrItemNotFound se o item não existir, ErrOutOfStock se a quantidade atual for zero ou ErrInsufficientQuantity se a quantidade solicitada exceder o estoque disponível. Em caso de sucesso, reduza o inventário e retorne nil.
  • main.go: Leia as operações de inventário da entrada e demonstre como os chamadores podem verificar erros sentinela específicos usando comparação direta de igualdade.

    Leia o nome do item e a quantidade a ser comprada da entrada. Crie um inventário, adicione o item "laptop" com a quantidade 5 e tente realizar a compra. Com base no erro retornado, imprima uma mensagem específica mostrando que você identificou qual erro sentinela ocorreu.

As seguintes entradas serão fornecidas:

  • Linha 1: Nome do item a ser comprado
  • Linha 2: Quantidade a ser comprada

Trate o resultado verificando qual erro específico foi retornado:

  • Se err == ErrItemNotFound: imprima Error: Item '[name]' does not exist in our inventory
  • Se err == ErrOutOfStock: imprima Error: Item '[name]' is currently out of stock
  • Se err == ErrInsufficientQuantity: imprima Error: Cannot purchase [quantity] units of '[name]' - not enough in stock
  • Se tiver sucesso: imprima Successfully purchased [quantity] units of '[name]'

Por exemplo, dadas as entradas laptop e 3, sua saída deverá ser:

Successfully purchased 3 units of 'laptop'

E, dadas as entradas phone e 2, sua saída deverá ser:

Error: Item 'phone' does not exist in our inventory

E, dadas as entradas laptop e 10, sua saída deverá ser:

Error: Cannot purchase 10 units of 'laptop' - not enough in stock

Experimente você mesmo

package main

import (
	"fmt"
)

func main() {
	// Ler a entrada
	var itemName string
	var quantity int
	fmt.Scanln(&itemName)
	fmt.Scanln(&quantity)

	// Criar inventário e adicionar "laptop" com quantidade 5
	inv := NewInventory()
	inv.AddItem("laptop", 5)

	// TODO: Tentar comprar o item
	// Chamar inv.Purchase(itemName, quantity)

	// TODO: Verificar qual erro sentinela específico foi retornado usando comparação direta de igualdade
	// Usar instruções if/else if para verificar:
	// - err == ErrItemNotFound
	// - err == ErrOutOfStock
	// - err == ErrInsufficientQuantity
	// - err == nil (sucesso)

	// TODO: Imprimir a mensagem apropriada com base no erro
	// Se ErrItemNotFound: fmt.Printf("Error: Item '%s' does not exist in our inventory\n", itemName)
	// Se ErrOutOfStock: fmt.Printf("Error: Item '%s' is currently out of stock\n", itemName)
	// Se ErrInsufficientQuantity: fmt.Printf("Error: Cannot purchase %d units of '%s' - not enough in stock\n", quantity, itemName)
	// Se sucesso: fmt.Printf("Successfully purchased %d units of '%s'\n", quantity, itemName)
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de Go online