Receptores de puntero
Parte de la sección Lógica y Flujo del Journey de GO de Coddy — lección 8 de 68.
Mientras que los receptores de valor trabajan con copias de structs, los receptores de puntero trabajan directamente con la instancia original del struct. Cuando defines un método con un receptor de puntero, el método puede modificar los datos originales porque recibe un puntero al struct en lugar de una copia.
Para crear un receptor de puntero, se añade un asterisco * antes del nombre del tipo en la declaración del receptor:
type Person struct {
Name string
Age int
}
func (p *Person) haveBirthday() {
p.Age++ // Esto modifica la estructura original
}En este ejemplo, (p *Person) es un receptor de puntero. Cuando llamas al método haveBirthday en una instancia de Person, el método recibe un puntero a la estructura original. Cualquier cambio realizado en los campos de la estructura a través de este puntero modificará permanentemente los datos originales.
Los receptores de puntero son esenciales cuando sus métodos necesitan actualizar los campos del struct, lo que los hace perfectos para operaciones que cambian el estado de sus datos.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Desafío
FácilEn este desafío, practicarás la creación de métodos con receptores de puntero construyendo un sistema de cuenta bancaria simple. Crearás una estructura Account y definirás métodos que puedan modificar el saldo de la cuenta utilizando receptores de puntero.
Recibirás tres entradas:
- Una cadena que representa el nombre del titular de la cuenta (por ejemplo,
"John Smith") - Una cadena que representa el saldo inicial de la cuenta (por ejemplo,
"1000.50") - Una cadena que representa el monto de una transacción (por ejemplo,
"250.75")
Tu tarea es:
- Definir una estructura
Accountcon dos campos:Name(string) yBalance(float64) - Crear un método llamado
depositcon un receptor de puntero que sume el monto dado al saldo de la cuenta - Crear un método llamado
withdrawcon un receptor de puntero que reste el monto dado del saldo de la cuenta - Crear un método llamado
displayBalancecon un receptor de valor que imprima la información de la cuenta en el formato:"Account: [name], Balance: $[balance]" - Analizar las entradas para crear una instancia de
Account - Llamar a
displayBalancepara mostrar el saldo inicial - Llamar a
depositcon el monto de la transacción - Llamar a
displayBalancepara mostrar el saldo después del depósito - Llamar a
withdrawcon el monto de la transacción - Llamar a
displayBalancepara mostrar el saldo final
El saldo debe mostrarse con una precisión de dos decimales. Este desafío demuestra cómo los receptores de puntero permiten que los métodos modifiquen los datos de la estructura original, a diferencia de los receptores de valor que trabajan con copias.
Hoja de referencia
Los receptores de puntero trabajan directamente con la instancia original de la estructura al recibir un puntero a la estructura en lugar de una copia. Esto permite que los métodos modifiquen los datos originales.
Para crear un receptor de puntero, añade un asterisco * antes del nombre del tipo en la declaración del receptor:
type Person struct {
Name string
Age int
}
func (p *Person) haveBirthday() {
p.Age++ // Esto modifica la estructura original
}Utiliza receptores de puntero cuando tus métodos necesiten actualizar los campos de la estructura, lo que los hace perfectos para operaciones que cambian el estado de tus datos.
Pruébalo tú mismo
package main
import (
"fmt"
"strconv"
)
// TODO: Define la estructura Account aquí
// TODO: Define el método deposit con un receptor de puntero aquí
// TODO: Define el método withdraw con un receptor de puntero aquí
// TODO: Define el método displayBalance con un receptor de valor aquí
func main() {
// Leer entrada
var name string
var initialBalanceStr string
var transactionAmountStr string
fmt.Scanln(&name)
fmt.Scanln(&initialBalanceStr)
fmt.Scanln(&transactionAmountStr)
// Convertir las entradas de cadena a los tipos apropiados
initialBalance, _ := strconv.ParseFloat(initialBalanceStr, 64)
transactionAmount, _ := strconv.ParseFloat(transactionAmountStr, 64)
// TODO: Crear una instancia de Account
// TODO: Mostrar el saldo inicial, realizar el depósito, mostrar el saldo, realizar el retiro, mostrar el saldo final
}Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Lógica y Flujo
1Flujo de control avanzado
Switch con `fallthrough`Salir de bucles anidadosContinuar un bucle específicoLa sentencia `goto`Repaso: Control de bucles avanzado4Proyecto: Lista de tareas sencilla
Configuración del proyectoAñadir una tarea2Estructuras y Métodos
Definición de métodos en estructurasReceptores de valorReceptores de punteroElegir receptoresMétodos vs FuncionesResumen - Comportamiento de estructuras5Mapas en profundidad
Mapas de StructsPunteros como valores de MapVerificación de Maps NilComparación de MapsResumen - Contador de frecuencia de palabras3Interfaces (Conceptos básicos)
¿Qué es una interfaz?Definir una interfazImplementar una interfazUso de tipos de interfazInterfaz vacíaAserciones de tipoType SwitchResumen: Formas y comportamientos