Comparación de struct, slice y map en Go: análisis completo

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Comparación de struct, slice y map en Go: de principiante a experto

\n\n

¿Alguna vez ha escrito código en Go que debía comparar dos estructuras, dos slices o dos maps, y recibió un error de compilación: invalid operation: cannot compare? Si es así, no está solo. Esta es una de las preguntas más populares en Stack Overflow (¡decenas de miles de visitas!), que desconcierta incluso a desarrolladores experimentados que migraron a Go desde otros lenguajes.

\n\n

En este artículo, analizaremos de una vez por todas cómo comparar correctamente tipos de datos compuestos en Go. Aprenderá por qué == no siempre funciona, cuándo usar reflect.DeepEqual y cómo escribir su propia función de comparación eficiente. ¡Comencemos!

\n\n

¿Por qué la comparación simple con == no siempre funciona?

\n\n

En Go, el operador == solo funciona para tipos comparables (comparable). Estos incluyen:

\n\n
    \n
  • Tipos básicos: int, string, bool, float, etc.
  • \n
  • Punteros (pointer)
  • \n
  • Canales (channel)
  • \n
  • Interfaces (si los tipos dinámicos son comparables)
  • \n
  • Estructuras, cuyos campos sean todos comparables
  • \n
  • Arreglos (array), si el elemento del arreglo es comparable
  • \n
\n\n

Sin embargo, los slices y los maps no son comparables directamente con ==. Intentar hacerlo generará un error de compilación. ¿Por qué? Porque un slice es un tipo de referencia que incluye un puntero a los datos, la longitud y la capacidad. Dos slices pueden ser "iguales" en contenido, pero tener estructuras internas diferentes.

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    a := []int{1, 2, 3}\n    b := []int{1, 2, 3}\n    \n    // ¡Error de compilación!\n    // fmt.Println(a == b) \n    \n    fmt.Println("Solo funciona con nil:")\n    fmt.Println(a == nil) // false\n    fmt.Println(b == nil) // false\n}
\n\n

Lo mismo aplica para los maps. Lo único que puede verificar con == es la igualdad con nil.

\n\n

Comparación de estructuras (struct) en Go

\n\n

La comparación de estructuras es el caso más engañoso. Si todos los campos de su estructura son de tipos comparables, entonces == funciona.

\n\n
type Person struct {\n    Name string\n    Age  int\n}\n\nfunc main() {\n    p1 := Person{"Alice", 30}\n    p2 := Person{"Alice", 30}\n    \n    fmt.Println(p1 == p2) // true — ¡funciona!\n}
\n\n

Pero el problema surge cuando la estructura contiene un slice o un map:

\n\n
type PersonWithHobbies struct {\n    Name    string\n    Age     int\n    Hobbies []string  // slice — tipo no comparable\n}\n\nfunc main() {\n    p1 := PersonWithHobbies{"Bob", 25, []string{"reading", "coding"}}\n    p2 := PersonWithHobbies{"Bob", 25, []string{"reading", "coding"}}\n    \n    // ¡Error de compilación!\n    // fmt.Println(p1 == p2)\n}
\n\n

En este caso, el compilador de Go mostrará un error: struct containing []string cannot be compared.

\n\n

Solución n.º 1: reflect.DeepEqual — universal pero lento

\n\n

La forma más sencilla de comparar cualquier tipo complejo es usar la función reflect.DeepEqual de la biblioteca estándar de Go. Esta recorre recursivamente estructuras, slices y maps y compara su contenido.

\n\n
import (\n    "fmt"\n    "reflect"\n)\n\nfunc main() {\n    // Comparación de slices\n    a := []int{1, 2, 3}\n    b := []int{1, 2, 3}\n    fmt.Println(reflect.DeepEqual(a, b)) // true\n    \n    // Comparación de maps\n    m1 := map[string]int{"a": 1, "b": 2}\n    m2 := map[string]int{"a": 1, "b": 2}\n    fmt.Println(reflect.DeepEqual(m1, m2)) // true\n    \n    // Comparación de estructuras con campos no comparables\n    p1 := PersonWithHobbies{"Bob", 25, []string{"reading"}}\n    p2 := PersonWithHobbies{"Bob", 25, []string{"reading"}}\n    fmt.Println(reflect.DeepEqual(p1, p2)) // true\n}
\n\n

<

Blogs

Book Recommendations