Menu
Coddy logo textTech

Paso por valor vs referencia

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

Go es un lenguaje de paso por valor. Cuando pasas una variable a una función, Go crea una copia de ese valor. Esto significa que los cambios dentro de la función no afectan a la variable original.

func double(n int) {
    n = n * 2
}

func main() {
    x := 10
    double(x)
    fmt.Println(x)  // 10 (sin cambios)
}

Lo mismo se aplica a los structs. Pasar un struct a una función copia todos sus campos, por lo que las modificaciones dentro de la función se pierden.

type Person struct {
    Name string
    Age  int
}

func birthday(p Person) {
    p.Age++
}

func main() {
    alice := Person{Name: "Alice", Age: 30}
    birthday(alice)
    fmt.Println(alice.Age)  // 30 (sin cambios)
}

Para modificar el valor original, pasa un puntero en su lugar. El puntero en sí se copia, pero sigue apuntando a la misma dirección de memoria, lo que te permite cambiar los datos originales.

func birthday(p *Person) {
    p.Age++
}

func main() {
    alice := Person{Name: "Alice", Age: 30}
    birthday(&alice)
    fmt.Println(alice.Age)  // 31 (¡modificado!)
}

Usa punteros cuando necesites modificar el valor original o al pasar structs grandes para evitar copias costosas. Usa valores cuando quieras proteger los datos originales de cambios no deseados.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de carrito de compras que demuestre la diferencia entre pasar structs por valor frente a pasarlos por puntero. Verás de primera mano cómo solo los parámetros de puntero pueden modificar los datos originales.

Organizarás tu código en dos archivos:

  • cart.go: Define un struct CartItem con los campos Name (string), Price (float64) y Quantity (int). Crea dos funciones que intenten actualizar la cantidad:
    • UpdateQuantityByValue recibe un CartItem (por valor) y una nueva cantidad, luego establece la cantidad del artículo al nuevo valor.
    • UpdateQuantityByPointer recibe un *CartItem (puntero) y una nueva cantidad, luego establece la cantidad del artículo al nuevo valor.
    También crea un método Total en CartItem que devuelva el precio multiplicado por la cantidad.
  • main.go: Lee los detalles del artículo desde la entrada, crea un CartItem y luego demuestra ambos enfoques de actualización. Primero intenta actualizar con la función por valor y muestra el resultado, luego actualiza con la función por puntero y muestra el resultado nuevamente.

Se proporcionarán las siguientes entradas:

  • Línea 1: Nombre del artículo
  • Línea 2: Precio (float)
  • Línea 3: Cantidad inicial (entero)
  • Línea 4: Nueva cantidad a establecer (entero)

Formato de salida:

Initial: [Name] x[Quantity] = $[Total]
After value update: [Name] x[Quantity] = $[Total]
After pointer update: [Name] x[Quantity] = $[Total]

Por ejemplo, dados Laptop, 999.99, 1 y 3, tu salida debería ser:

Initial: Laptop x1 = $999.99
After value update: Laptop x1 = $999.99
After pointer update: Laptop x3 = $2999.97

Observa cómo la cantidad se mantiene en 1 después de la actualización por valor (la función modificó una copia), pero cambia a 3 después de la actualización por puntero (la función modificó el original). Formatea los totales con dos decimales.

Pruébalo tú mismo

package main

import (
	"fmt"
)

func main() {
	// Leer entrada
	var name string
	var price float64
	var initialQty, newQty int

	fmt.Scanln(&name)
	fmt.Scanln(&price)
	fmt.Scanln(&initialQty)
	fmt.Scanln(&newQty)

	// TODO: Crear un CartItem con los valores de entrada

	// TODO: Imprimir el estado inicial usando el formato:
	// fmt.Printf("Initial: %s x%d = $%.2f\n", ...)

	// TODO: Intentar actualizar la cantidad usando UpdateQuantityByValue
	// Luego imprimir el resultado (notar que la cantidad no cambiará)

	// TODO: Actualizar la cantidad usando UpdateQuantityByPointer
	// Luego imprimir el resultado (notar que la cantidad cambiará)
}
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