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 las estructuras. Pasar una estructura a una función copia todos sus campos, por lo que las modificaciones realizadas 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

Construyamos un sistema de carrito de compras que demuestre la diferencia entre pasar estructuras por valor y pasarlas mediante 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 una estructura CartItem con 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; después establece la cantidad del artículo en el nuevo valor
    • UpdateQuantityByPointer recibe un *CartItem (puntero) y una nueva cantidad; después establece la cantidad del artículo en el 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 después demuestra ambos enfoques de actualización. Primero intenta actualizarlo con la función por valor y muestra el resultado; después actualízalo con la función mediante puntero y vuelve a mostrar el resultado.

Se proporcionarán las siguientes entradas:

  • Línea 1: Nombre del artículo
  • Línea 2: Precio (coma flotante)
  • Línea 3: Cantidad inicial (entero)
  • Línea 4: Nueva cantidad que se 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, dadas las entradas 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 permanece 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 mediante puntero (la función modificó el original). Da formato a 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

Practica por tu cuenta: Compilador de Go online