Receivers por puntero en métodos
Modificación del estado de un struct mediante receivers por puntero
Receivers por puntero en métodos es una lección gratuita de Go Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Go Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Go Academy incluye 4 lecciones en total.
Repaso: receptor por valor frente a receptor por puntero
Un receptor por valor opera sobre una copia de la estructura. Un receptor por puntero opera sobre la original. Utilice receptores por puntero siempre que un método necesite modificar el estado.
Modificación con un receptor por puntero
Solo un receptor por puntero puede modificar la estructura:
package main
import "fmt"
type Stack struct{ items []int }
func (s *Stack) Push(v int) { s.items = append(s.items, v) }
func (s *Stack) Pop() int {
n := len(s.items) - 1
v := s.items[n]
s.items = s.items[:n]
return v
}
func main() {
var st Stack
st.Push(1); st.Push(2)
fmt.Println(st.Pop()) // 2
}Regla de coherencia
Si algún método de un tipo necesita un receptor por puntero, todos sus métodos deben utilizar receptores por puntero. Mezclarlos provoca problemas para satisfacer interfaces:
package main
import "fmt"
type Counter struct{ n int }
func (c *Counter) Inc() { c.n++ } // pointer
func (c *Counter) Val() int { return c.n } // pointer too
func main() {
c := &Counter{}
c.Inc(); c.Inc()
fmt.Println(c.Val()) // 2
}Satisfacción de interfaces
Un método con receptor por puntero solo forma parte del conjunto de métodos de *T, no de T. Esto afecta a la satisfacción de interfaces:
package main
import "fmt"
type Writer interface{ Write([]byte) }
type File struct{ name string }
func (f *File) Write(b []byte) { fmt.Println(string(b)) }
func main() {
var w Writer = &File{"out.txt"} // OK
// var w Writer = File{} — compile error
w.Write([]byte("hello"))
}Toma automática de direcciones
Go toma automáticamente la dirección al llamar a un método con receptor por puntero sobre un valor direccionable:
package main
import "fmt"
type Box struct{ V int }
func (b *Box) Double() { b.V *= 2 }
func main() {
b := Box{5}
b.Double() // Go does (&b).Double()
fmt.Println(b.V) // 10
}Valores no direccionables
No puede llamar a métodos con receptor por puntero sobre valores no direccionables (elementos de mapas y valores devueltos por funciones que no se han asignado a variables):
package main
type T struct{ V int }
func (t *T) Set(v int) { t.V = v }
func getT() T { return T{} }
func main() {
var t T
t.Set(1) // OK — t is addressable
// getT().Set(1) — ERROR: cannot take address of getT()
_ = t
}Receptores de estructuras grandes
Utilice siempre receptores por puntero para las estructuras grandes, a fin de evitar copias costosas en cada llamada a un método:
package main
type Image struct{ pixels [1024][1024]uint8 }
// Value receiver copies 1MB per call!
func (img Image) Bad() uint8 { return img.pixels[0][0] }
// Pointer receiver — zero copy
func (img *Image) Good() uint8 { return img.pixels[0][0] }
func main() { _ = Image{} }Receptores de puntero nil
Los métodos con receptores por puntero pueden gestionar nil correctamente:
package main
import "fmt"
type List struct{ head *node }
type node struct{ val int; next *node }
func (l *List) Len() int {
if l == nil { return 0 }
count := 0
for n := l.head; n != nil; n = n.next { count++ }
return count
}
func main() {
var l *List
fmt.Println(l.Len()) // 0
}Inserción y receptores por puntero
Al insertar un tipo con receptores por puntero, la estructura externa también debe utilizarse como puntero para obtener los métodos promovidos:
package main
import "fmt"
type Base struct{ V int }
func (b *Base) Set(v int) { b.V = v }
type Derived struct{ Base }
func main() {
d := &Derived{}
d.Set(42) // promoted pointer-receiver method
fmt.Println(d.V) // 42
}Copiar mutexes
No copie nunca una estructura que contenga un sync.Mutex; utilice siempre un receptor por puntero o pase la estructura mediante un puntero. Copiar un mutex bloqueado provoca un interbloqueo:
package main
import "sync"
type Safe struct {
mu sync.Mutex
v int
}
// Correct: pointer receiver
func (s *Safe) Set(v int) {
s.mu.Lock()
defer s.mu.Unlock()
s.v = v
}
func main() { _ = Safe{} }go vet detecta errores
Ejecute go vet ./... para detectar errores comunes relacionados con receptores por puntero, como copiar mutexes y bloqueos. Forma parte de las canalizaciones de go build y de las comprobaciones de CI.
Comprobación rápida
¿En el conjunto de métodos de qué tipos se encuentra un método con receptor por puntero?
Repaso
Conclusiones principales:
- Los receptores por puntero modifican datos; los receptores por valor no
- Mantenga el mismo tipo de receptor en todos los métodos de un tipo
- Solo
*Tsatisface interfaces que requieren métodos con receptores por puntero - No copie nunca estructuras con mutexes; utilice receptores por puntero
Propuesta de práctica
Implemente una estructura Queue con los métodos Enqueue(int), Dequeue() (int, bool) y Len() int, todos con receptores por puntero y respaldados por un slice []int.
Preguntas frecuentes
¿La lección «Receivers por puntero en métodos» es gratis?
Sí — el texto completo de «Receivers por puntero en métodos» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Go Academy, actualiza a CoddyKit PRO. El curso de Go Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Receivers por puntero en métodos»?
Modificación del estado de un struct mediante receivers por puntero Practicas Go Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Go Academy?
No se requiere experiencia previa. Go Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Receivers por puntero en métodos»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Go Academy?
Sí. Cada lección de Go Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- ¿Qué son los punteros?
- Punteros y funciones
- Receivers por puntero en métodos
- new() y cuándo usar punteros