12 Métodos en Structs y Comparación en Go

Published Apr 30, 2024

GoProgrammingStructs

🧠 Introducción

En Go, un método es una función asociada a un tipo definido por el usuario, como un struct. Esto permite encapsular comportamientos relacionados con los datos, de forma muy similar (pero no igual) a la programación orientada a objetos.

1. 🧱 ¿Qué es un método?

Un método es simplemente una función que se define con un receptor:

func (p Point) nombreMetodo() tipoRetorno {
    // código
}

Donde Point es un struct y p es una copia (o un puntero) a la instancia actual.

2. ✍️ Ejemplo básico

type Point struct {
	x float32
	y float32
}

func (p Point) Sum() float32 {
	return p.x + p.y
}

func main() {
	pt1 := Point{x: 5.6, y: 3.8}
	fmt.Println(pt1.Sum()) // 9.4
}
  • El receptor (p Point) hace que Sum sea un método del struct Point.
  • Los métodos pueden usar cualquier lógica y acceder a los campos del struct.

3. 🔄 Métodos con punteros

Cuando quieres modificar el valor del struct dentro del método, necesitas pasar un puntero:

func (p *Point) MoveX() {
	p.x = p.x + 5
}
pt1 := Point{x: 5.6, y: 3.8}
pt1.MoveX()
fmt.Println(pt1.x) // 10.6

🧠 Nota:

Aunque esto se parece a programación orientada a objetos, Go no tiene herencia ni sobrecarga de métodos.

Sobrecarga es cuando defines varias funciones con el mismo nombre pero distintas firmas.

Go no lo permite: cada nombre de método debe ser único dentro del mismo tipo.

4. 📊 Comparar structs

Puedes usar el operador == solo si el struct no contiene slices, maps o funciones:

type Point struct {
	x float32
	y float32
}

pt1 := Point{5.6, 3.8}
pt2 := Point{5.6, 3.8}

fmt.Println(pt1 == pt2) // true

Pero si el struct incluye un slice:

type Point struct {
	x    float32
	y    float32
	name []string
}

Recibirás un error:

invalid operation: pt1 == pt2 (struct containing []string cannot be compared)

5. 🧰 Comparación con cmp

El paquete github.com/google/go-cmp/cmp permite comparar structs complejos (con slices, maps, etc).

📦 Instalación:

go get -u github.com/google/go-cmp/cmp

Para que funcione, los campos deben estar exportados (inicial con mayúscula).

✅ Ejemplo:

import "github.com/google/go-cmp/cmp"

type Point struct {
	X    float32
	Y    float32
	Name []string
}

pt1 := Point{X: 5.6, Y: 3.8, Name: []string{"elprogramadorgt"}}
pt2 := Point{X: 5.6, Y: 3.8, Name: []string{"elprogramadorgt"}}

fmt.Println(cmp.Equal(pt1, pt2)) // true

6. 🛠️ Método de comparación personalizado

Puedes definir tu propio método .Equal() para comparar lo que a ti te interese:

func (p Point) Equal(p2 Point) bool {
	return p.X == p2.X && p.Y == p2.Y
}

Así ignoras el campo Name, por ejemplo:

pt1 := Point{X: 5.6, Y: 3.8, Name: []string{"a"}}
pt2 := Point{X: 5.6, Y: 3.8, Name: []string{"b"}}

fmt.Println(pt1.Equal(pt2)) // true

✅ Conclusión

  • Puedes definir métodos sobre structs para agregarles lógica propia.
  • Usa punteros () si quieres que el método modifique el struct.
  • Los structs no admiten sobrecarga de métodos.
  • Go permite comparar structs simples con ==, pero para structs complejos (como los que contienen slices) usa cmp o define tu propia comparación.

🛠️ Práctica recomendada

  1. Crea un struct Rectangle con campos Width y Height.
  2. Define un método Area() que retorne su área.
  3. Define un método Resize(factor float64) que modifique los valores usando puntero.
  4. Crea dos Rectangle con los mismos valores, pero con un campo adicional tipo []string, y usa cmp.Equal() para compararlos.
  5. Agrega tu propio método .Equal() que compare solo Width y Height.

🚀 Siguientes pasos

Ya sabes definir structs y métodos, así que es momento de avanzar hacia:

  • 🧱 Composición de structs: cómo reutilizar structs dentro de otros structs.
  • 🧠 Interfaces en Go: cómo describir comportamientos reutilizables.
  • 📦 Organización de structs en paquetes y archivos reales de proyecto.