Menu
Coddy logo textTech

Campos exportados vs. no exportados

Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 47 de 107.

En Go, el encapsulamiento a nivel de struct se controla mediante el uso de mayúsculas y minúsculas en los nombres de los campos. Esta regla simple determina si se puede acceder a los campos desde fuera del paquete donde se define el struct.

Los campos que comienzan con una letra mayúscula son exportados—accesibles desde cualquier paquete. Los campos que comienzan con una letra minúscula no son exportados—solo accesibles dentro del mismo paquete:

// En el paquete "user"
type User struct {
    Name     string  // Exportado - accesible en todas partes
    Email    string  // Exportado - accesible en todas partes
    password string  // No exportado - solo accesible en el paquete "user"
    age      int     // No exportado - solo accesible en el paquete "user"
}

Cuando otro paquete importa y utiliza esta estructura, solo puede interactuar con los campos exportados:

// En el paquete "main"
import "user"

func main() {
    u := user.User{
        Name:  "Alice",      // funciona
        Email: "a@mail.com", // funciona
        // password: "secret", // error de compilación: campo desconocido
    }
    
    fmt.Println(u.Name)     // funciona
    // fmt.Println(u.password) // error de compilación: no se puede hacer referencia a un campo no exportado
}

Este mecanismo protege los datos sensibles y los detalles de implementación interna. El campo password no se puede leer ni modificar directamente desde fuera del paquete, lo que obliga a que el resto del código utilice los métodos que proporciones. Este es el enfoque de Go para lograr la ocultación de datos, un principio fundamental de la encapsulación en la programación orientada a objetos.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de cuenta bancaria que demuestre el encapsulamiento a través de campos exportados y no exportados. Crearás un paquete que proteja los datos financieros sensibles mientras expone información pública segura.

Organizarás tu código en dos archivos:

  • account.go: Crea un struct BankAccount en el paquete main que modele una cuenta bancaria real con la protección de datos adecuada:
    • HolderName (exportado) - el nombre del titular de la cuenta, seguro para mostrar públicamente
    • AccountType (exportado) - el tipo de cuenta (por ejemplo, "Savings", "Checking")
    • balance (no exportado) - el saldo real, que debe estar protegido
    • pin (no exportado) - el PIN de la cuenta, datos altamente sensibles
    Añade una función constructora NewBankAccount que reciba el nombre del titular, el tipo de cuenta, el saldo inicial y el PIN, y luego devuelva un puntero a un nuevo BankAccount. También añade un método GetPublicInfo() string que devuelva el formato: Account: [HolderName] ([AccountType])
  • main.go: Lee los detalles de la cuenta desde la entrada, crea un BankAccount usando el constructor y demuestra el encapsulamiento. Imprime la información pública usando el método, luego accede directamente e imprime cada campo exportado en líneas separadas. Los campos no exportados (balance y pin) están protegidos; solo puedes establecerlos a través del constructor.

Se proporcionarán las siguientes entradas:

  • Línea 1: Nombre del titular de la cuenta
  • Línea 2: Tipo de cuenta
  • Línea 3: Saldo inicial (como un float)
  • Línea 4: Código PIN

Por ejemplo, dados Alice Johnson, Savings, 5000.50, y 1234, tu salida debería ser:

Account: Alice Johnson (Savings)
Holder: Alice Johnson
Type: Savings

Observa que el saldo y el PIN nunca aparecen en la salida; están ocultos de forma segura dentro del struct, accesibles solo dentro del paquete. Esto es el encapsulamiento en acción: los datos sensibles están protegidos mientras que la información pública permanece accesible.

Hoja de referencia

En Go, la encapsulación se controla mediante el uso de mayúsculas y minúsculas en los nombres de los campos de los structs:

  • Los campos en Mayúscula están exportados (son accesibles desde cualquier paquete)
  • Los campos en Minúscula no están exportados (solo son accesibles dentro del mismo paquete)
type User struct {
    Name     string  // Exportado - accesible desde cualquier lugar
    Email    string  // Exportado - accesible desde cualquier lugar
    password string  // No exportado - solo accesible en el mismo paquete
    age      int     // No exportado - solo accesible en el mismo paquete
}

Al usar un struct de otro paquete, solo los campos exportados son accesibles:

import "user"

func main() {
    u := user.User{
        Name:  "Alice",      // funciona
        Email: "a@mail.com", // funciona
        // password: "secret", // error de compilación: campo desconocido
    }
    
    fmt.Println(u.Name)     // funciona
    // fmt.Println(u.password) // error de compilación: no se puede referir a un campo no exportado
}

Este mecanismo protege los datos sensibles y los detalles de implementación interna, obligando al código externo a utilizar los métodos proporcionados para el acceso.

Pruébalo tú mismo

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Leer el nombre del titular de la cuenta
	holderName, _ := reader.ReadString('\n')
	holderName = strings.TrimSpace(holderName)

	// Leer el tipo de cuenta
	accountType, _ := reader.ReadString('\n')
	accountType = strings.TrimSpace(accountType)

	// Leer el saldo inicial
	balanceStr, _ := reader.ReadString('\n')
	balanceStr = strings.TrimSpace(balanceStr)
	balance, _ := strconv.ParseFloat(balanceStr, 64)

	// Leer el PIN
	pinStr, _ := reader.ReadString('\n')
	pin := strings.TrimSpace(pinStr)

	// TODO: Crear una nueva BankAccount usando el constructor
	// account := NewBankAccount(...)

	// TODO: Imprimir la información pública usando el método GetPublicInfo()

	// TODO: Imprimir el nombre del titular accediendo directamente al campo exportado
	// fmt.Println("Holder:", ...)

	// TODO: Imprimir el tipo de cuenta accediendo directamente al campo exportado
	// fmt.Println("Type:", ...)

	// Note: balance y pin no están exportados - no se pueden acceder directamente aquí
	// Están encapsulados de forma segura dentro del struct

	_ = balance // Elimina esta línea cuando uses balance
	_ = pin     // Elimina esta línea cuando uses pin
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos