Menu
Coddy logo textTech

Ocultação de Informação em Go

Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 50 de 107.

Ocultação de informações vai além de apenas tornar os campos não exportados. Trata-se de projetar seus tipos de modo que o código externo saiba apenas o que precisa saber — nada mais.

O objetivo é expor comportamento através de métodos enquanto mantém a estrutura interna completamente oculta. Considere esta abordagem:

type Counter struct {
    value    int
    maxLimit int
}

func NewCounter(limit int) *Counter {
    return &Counter{maxLimit: limit}
}

func (c *Counter) Increment() bool {
    if c.value >= c.maxLimit {
        return false
    }
    c.value++
    return true
}

func (c *Counter) Value() int {
    return c.value
}

O código externo não sabe que o Counter usa um int internamente. Poderia ser um float64, um slice ou algo totalmente diferente. A implementação pode mudar sem afetar nenhum código que use o Counter—desde que os métodos se comportem da mesma maneira.

Este princípio também se aplica a funções auxiliares. Mantenha a lógica interna não exportada:

// Exportado - parte da API pública
func (c *Counter) Reset() {
    c.value = 0
}

// não exportado - auxiliar interno
func (c *Counter) isAtLimit() bool {
    return c.value >= c.maxLimit
}

Ao ocultar isAtLimit(), você tem a liberdade de alterá-lo ou removê-lo mais tarde. A ocultação de informações cria um limite claro entre o que seu pacote promete aos usuários externos e como ele funciona internamente.

challenge icon

Desafio

Fácil

Vamos construir um sistema de carteira segura que demonstra a ocultação de informações. Você criará uma carteira digital onde o rastreamento do saldo interno e o histórico de transações ficam completamente ocultos do código externo — apenas o comportamento é exposto por meio de métodos.

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

  • wallet.go: Crie uma struct Wallet que oculte todo o seu estado interno. A carteira deve rastrear o saldo atual e um limite de gastos internamente, mas o código externo nunca deve saber como eles são armazenados ou representados. Exponha o comportamento através destes métodos:
    • NewWallet(limit float64) *Wallet - construtor que cria uma carteira com o limite de gastos fornecido e saldo zero
    • Deposit(amount float64) bool - adiciona dinheiro à carteira, retorna true se for bem-sucedido (o valor deve ser positivo)
    • Spend(amount float64) bool - remove dinheiro se houver saldo suficiente E o valor não exceder o limite de gastos, retorna true se for bem-sucedido
    • Balance() float64 - retorna o saldo atual
    • Status() string - retorna uma mensagem de status no formato: Balance: $[balance] (Limit: $[limit])
    Mantenha qualquer lógica auxiliar (como verificar se uma transação é válida) como funções ou métodos não exportados — esses são detalhes de implementação interna que podem mudar posteriormente.
  • main.go: Leia a configuração da carteira e as transações da entrada, crie uma carteira, realize operações e exiba os resultados após cada ação.

As seguintes entradas serão fornecidas:

  • Linha 1: Limite de gastos
  • Linha 2: Valor do depósito
  • Linha 3: Valor do primeiro gasto
  • Linha 4: Valor do segundo gasto

Após criar a carteira, imprima seu status inicial. Em seguida, realize cada operação e imprima o status atualizado (se for bem-sucedido) ou Transaction failed (se a operação for rejeitada). Formate todos os valores monetários com duas casas decimais.

Por exemplo, dados 50, 100, 30 e 80, sua saída deve ser:

Balance: $0.00 (Limit: $50.00)
Balance: $100.00 (Limit: $50.00)
Balance: $70.00 (Limit: $50.00)
Transaction failed

A última transação falha porque $80 excede o limite de gastos de $50 — mesmo que haja saldo suficiente. A carteira impõe suas regras internamente sem expor como toma essas decisões. O código externo simplesmente chama métodos e recebe resultados, sem nunca conhecer os detalhes da implementação interna.

Folha de consulta

Ocultação de informações significa projetar tipos de forma que o código externo saiba apenas o que precisa saber. Exponha o comportamento por meio de métodos, mantendo a estrutura interna completamente oculta.

Exemplo de um tipo com implementação oculta:

type Counter struct {
    value    int
    maxLimit int
}

func NewCounter(limit int) *Counter {
    return &Counter{maxLimit: limit}
}

func (c *Counter) Increment() bool {
    if c.value >= c.maxLimit {
        return false
    }
    c.value++
    return true
}

func (c *Counter) Value() int {
    return c.value
}

O código externo não conhece a representação interna (poderia ser int, float64 ou qualquer outra coisa). A implementação pode mudar sem afetar o código que a utiliza.

Mantenha as funções auxiliares não exportadas:

// Exportado - parte da API pública
func (c *Counter) Reset() {
    c.value = 0
}

// não exportado - auxiliar interno
func (c *Counter) isAtLimit() bool {
    return c.value >= c.maxLimit
}

A ocultação de informações cria um limite claro entre o que seu pacote promete externamente e como ele funciona internamente.

Experimente você mesmo

package main

import (
	"fmt"
)

func main() {
	// Ler as entradas
	var limit float64
	var depositAmount float64
	var spend1 float64
	var spend2 float64

	fmt.Scanln(&limit)
	fmt.Scanln(&depositAmount)
	fmt.Scanln(&spend1)
	fmt.Scanln(&spend2)

	// TODO: Criar uma nova carteira com o limite de gastos fornecido

	// TODO: Imprimir o status inicial

	// TODO: Realizar o depósito e imprimir o resultado (status ou "Transaction failed")

	// TODO: Realizar o primeiro gasto e imprimir o resultado

	// TODO: Realizar o segundo gasto e imprimir o resultado
}
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