Fundamentos de punteros en Go
Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 19 de 107.
Un puntero es una variable que almacena la dirección de memoria de otra variable. En lugar de contener un valor directamente, contiene la ubicación donde vive ese valor en la memoria. Los punteros son fundamentales en Go y esenciales para una manipulación de datos eficiente.
Para crear un puntero, usa el operador & para obtener la dirección de una variable, y el operador * para declarar un tipo de puntero o acceder al valor en esa dirección.
x := 42
p := &x // p contiene la dirección de memoria de x
fmt.Println(p) // 0xc000018030 (dirección de memoria)
fmt.Println(*p) // 42 (valor en esa dirección)El operador & significa "dirección de" y devuelve un puntero. El operador *, cuando se usa en un puntero, significa "valor en" y se llama desreferenciación. También puedes modificar el valor original a través del puntero.
x := 10
p := &x
*p = 25 // cambiar el valor a través del puntero
fmt.Println(x) // 25 (la variable original cambió)El tipo de puntero se escribe como *T donde T es el tipo al que se apunta. Un puntero a un int tiene el tipo *int.
var p *int // declara un puntero a int
x := 100
p = &x // p ahora apunta a xEl valor cero de un puntero es nil, lo que significa que no apunta a nada. Intentar desreferenciar un puntero nil provoca un pánico en tiempo de ejecución (runtime panic), por lo que siempre debes asegurarte de que los punteros estén inicializados antes de su uso.
Desafío
FácilVamos a construir un intercambiador de valores simple que demuestre el poder de los punteros para modificar variables a través de sus direcciones de memoria.
Organizarás tu código en dos archivos:
swap.go: Crea una función llamadaSwapValuesque reciba dos punteros*intcomo parámetros. Esta función debe intercambiar los valores a los que apuntan estos punteros; después de llamarla, cada variable debe contener el valor original de la otra. La función no devuelve nada; modifica los valores directamente a través de los punteros.main.go: Lee dos números enteros de la entrada, almacénalos en variables y luego usa tu funciónSwapValuespara intercambiar sus valores. Imprime ambos valores antes y después del intercambio para mostrar el cambio.
Se proporcionarán las siguientes entradas:
- Línea 1: Primer número entero
- Línea 2: Segundo número entero
Formato de salida:
Before: a=[first] b=[second]
After: a=[first] b=[second]Por ejemplo, dados 10 y 25, tu salida debería ser:
Before: a=10 b=25
After: a=25 b=10Recuerda usar el operador & al pasar tus variables a la función, y el operador * dentro de la función para acceder y modificar los valores reales.
Hoja de referencia
Un puntero es una variable que almacena la dirección de memoria de otra variable. Utilice el operador & para obtener la dirección de una variable, y el operador * para declarar un tipo de puntero o acceder al valor en esa dirección.
x := 42
p := &x // p holds the memory address of x
fmt.Println(p) // 0xc000018030 (memory address)
fmt.Println(*p) // 42 (value at that address)El operador & significa "dirección de" y devuelve un puntero. El operador *, cuando se usa en un puntero, significa "valor en" y se llama desreferenciación.
Puede modificar el valor original a través del puntero:
x := 10
p := &x
*p = 25 // change value through pointer
fmt.Println(x) // 25 (original variable changed)El tipo de puntero se escribe como *T donde T es el tipo al que se apunta:
var p *int // declares a pointer to int
x := 100
p = &x // p now points to xEl valor cero de un puntero es nil. Intentar desreferenciar un puntero nil provoca un pánico en tiempo de ejecución (runtime panic).
Pruébalo tú mismo
package main
import "fmt"
func main() {
// Lee dos enteros de la entrada
var a, b int
fmt.Scanln(&a)
fmt.Scanln(&b)
// Imprime los valores antes del intercambio
fmt.Printf("Before: a=%d b=%d\n", a, b)
// TODO: Llama a la función SwapValues con punteros a a y b
// Recuerda usar el operador & para pasar direcciones
// Imprime los valores después del intercambio
fmt.Printf("After: a=%d b=%d\n", a, b)
}
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
1Fundamentos de POO en Go
Archivos externosEspacio de trabajo y módulos de GoPaquetes e importacionesNombres exportados vs. no exportadosIntroducción a la POO en GoStructs como clasesDefinición de métodos en structsReceptores de puntero vs. de valorInicialización de structsFunciones constructorasResumen - Calculadora simple4Interfaces
Introducción a las interfacesImplementación implícitaLa interfaz como contratoInterfaz vacía (any)Type AssertionType SwitchComposición de interfacesInterfaces Stringer y ErrorResumen: Calculadora de figuras7Encapsulamiento
Campos exportados vs. no exportadosEncapsulamiento a nivel de paqueteMétodos Getter y SetterOcultamiento de información en GoResumen - Registros de estudiantes10Genéricos (Go 1.18+)
Introducción a los GenéricosParámetros de tipoRestricciones de tipoStructs genéricosSolución alternativa para métodos genéricosResumen - Colección genérica13Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón Abstract FactoryPatrón ObserverPatrón Strategy2Inmersión profunda en Tipos y Structs
Tipos básicos y compuestosDefiniciones de tipos personalizadosEtiquetas de StructsStructs anónimosStructs anidadosValores cero y por defectoRepaso - Libreta de contactos5Composición sobre herencia
Por qué Go no tiene herenciaConceptos básicos de incrustación de structsPromoción de métodosIncrustación de múltiples structsIncrustación vs AgregaciónShadowing de métodos incrustadosResumen - Jerarquía de empleados8Manejo de Errores y OOP
La interfaz errorTipos de errores personalizadosEnvoltura de errores (fmt.Errorf)Errores centinelaerrors.Is() y errors.As()Panic, Defer y RecoverResumen - Analizador de archivos3Punteros y Memoria
Fundamentos de punteros en GoPunteros a StructsPaso por valor vs referenciaLa función new()Garbage Collection en GoResumen - Constructor de Linked List6Polimorfismo en Go
Polimorfismo mediante interfacesDuck Typing en GoReglas de satisfacción de interfacesColecciones polimórficasInyección de dependenciasResumen - Procesador de pagos9Concurrencia y POO
Fundamentos de GoroutinesChannels y comunicaciónChannels con buffer vs. sin bufferSentencia Selectsync.Mutex y sync.RWMutexsync.WaitGroupDiseño de estructuras Thread-SafeResumen - Worker Pool