Menu
Coddy logo textTech

Punteros a Structs

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

Al trabajar con structs, a menudo usarás punteros para evitar copiar grandes estructuras de datos y para modificar el struct original. Un puntero a un struct contiene la dirección de memoria de esa instancia de struct.

Puedes crear un puntero a una estructura utilizando el operador & en una estructura existente, o utilizando el operador de dirección directamente con un literal de estructura.

type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Alice", Age: 30}
ptr := &p  // puntero a una estructura existente

// O crear directamente
ptr2 := &Person{Name: "Bob", Age: 25}

Go proporciona un atajo conveniente al acceder a los campos de una estructura a través de un puntero. En lugar de escribir (*ptr).Name, simplemente puedes escribir ptr.Name. Go desreferencia automáticamente el puntero por ti.

ptr := &Person{Name: "Alice", Age: 30}

// Ambos funcionan de forma idéntica
fmt.Println((*ptr).Name)  // desreferencia explícita
fmt.Println(ptr.Name)     // desreferencia automática

Esta desreferenciación automática también se aplica al modificar campos. Los cambios a través del puntero afectan a la estructura original.

p := Person{Name: "Alice", Age: 30}
ptr := &p

ptr.Age = 31           // modifica el original
fmt.Println(p.Age)     // 31

Los punteros a struct son esenciales en los patrones de OOP de Go. Permiten que los métodos modifiquen el estado del receptor, permiten pasar structs grandes a funciones de manera eficiente y forman la base para construir estructuras de datos enlazadas como árboles y listas.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de cuenta bancaria que demuestre cómo los punteros a estructuras permiten modificar los datos originales de manera eficiente. Crearás una cuenta que se puede actualizar a través de operaciones con punteros.

Organizarás tu código en dos archivos:

  • account.go: Define una estructura BankAccount con los campos Owner (string), Balance (float64) y AccountNumber (string). Crea una función llamada NewAccount que reciba un nombre de propietario y un número de cuenta como parámetros y devuelva un puntero a una nueva BankAccount con un saldo inicial de 0. También crea una función Deposit que reciba un puntero *BankAccount y un monto, y luego sume ese monto al saldo de la cuenta a través del puntero.
  • main.go: Lee la información de la cuenta desde la entrada, crea una cuenta usando tu función constructora (que devuelve un puntero), realiza un depósito usando el puntero y muestra los detalles de la cuenta para confirmar que el saldo fue modificado.

Se proporcionarán las siguientes entradas:

  • Línea 1: Nombre del propietario
  • Línea 2: Número de cuenta
  • Línea 3: Monto del depósito (float)

Formato de salida:

Account: [AccountNumber]
Owner: [Owner]
Balance: [Balance]

Por ejemplo, dados John Smith, ACC-12345 y 500.50, tu salida debería ser:

Account: ACC-12345
Owner: John Smith
Balance: 500.50

Recuerda que tu función NewAccount debe devolver *BankAccount usando el operador &, y tu función Deposit puede modificar el saldo directamente a través del puntero usando la desreferenciación automática de Go (por ejemplo, account.Balance en lugar de (*account).Balance).

Hoja de referencia

Un puntero a una estructura contiene la dirección de memoria de una instancia de estructura. Crea punteros a estructuras usando el operador &:

type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Alice", Age: 30}
ptr := &p  // puntero a una estructura existente

// O crear directamente
ptr2 := &Person{Name: "Bob", Age: 25}

Go proporciona desreferenciación automática al acceder a los campos de una estructura a través de un puntero. En lugar de (*ptr).Name, puedes escribir ptr.Name:

ptr := &Person{Name: "Alice", Age: 30}

// Ambos funcionan de forma idéntica
fmt.Println((*ptr).Name)  // desreferenciación explícita
fmt.Println(ptr.Name)     // desreferenciación automática

Los cambios a través de un puntero afectan a la estructura original:

p := Person{Name: "Alice", Age: 30}
ptr := &p

ptr.Age = 31           // modifica el original
fmt.Println(p.Age)     // 31

Los punteros a estructuras permiten que los métodos modifiquen el estado del receptor, permiten pasar estructuras grandes a funciones de manera eficiente y forman la base para estructuras de datos enlazadas.

Pruébalo tú mismo

package main

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

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Leer el nombre del propietario
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)
	
	// Leer el número de cuenta
	accountNumber, _ := reader.ReadString('\n')
	accountNumber = strings.TrimSpace(accountNumber)
	
	// Leer el monto del depósito
	amountStr, _ := reader.ReadString('\n')
	amountStr = strings.TrimSpace(amountStr)
	amount, _ := strconv.ParseFloat(amountStr, 64)
	
	// TODO: Crear una nueva cuenta usando la función NewAccount (devuelve un puntero)
	
	// TODO: Realizar un depósito usando la función Deposit con el puntero de la cuenta
	
	// TODO: Imprimir los detalles de la cuenta en el formato requerido:
	// Account: [AccountNumber]
	// Owner: [Owner]
	// Balance: [Balance]
}
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