En el post previo hablamos de las operaciones básicas con estructuras; como crear ,instanciar y/o asignar valores, en esta entrada veremos operaciones mas avanzadas que podemos realizar con las estructuras.

Estructuras Anidadas

Las estructuras son anidadas cuando agregamos un campo de tipo Estructura dentro de otra Estructura. Es de mucha ayuda anidar estructuras cuando necesitamos crear modelos complejos.
Veamos un ejemplo:

package main

import "fmt"

//Declaramos la estructura que anidaremos
type Club struct {
	Nombre     string
	Temporadas int
}

//Declaramos la estructura principal
type Jugador struct {
	Nombre, Posicion string
	Edad             int
	//Realizamos un slice de la estructura Club
	Clubes []Club
}

func main() {
	//creamos una instancia de la estructura jugador
	j := Jugador{
		Nombre:   "Critiano Dos Santos",
		Posicion: "Delantero",
		Edad:     36,
		//agregamos elementos al slice de la estructura club
		Clubes: []Club{
			Club{
				Nombre:     "Lisboa",
				Temporadas: 2,
			},
			Club{
				Nombre:     "Manchester",
				Temporadas: 6,
			},
			Club{
				Nombre:     "Madrid",
				Temporadas: 6,
			},
		},
	}
	fmt.Println(j.Nombre, j.Posicion)
	//imprimimos los elementos del slice clubes
	fmt.Println(j.Clubes[0])
	fmt.Println(j.Clubes[1])
	fmt.Println(j.Clubes[2])
}

Agregar Etiquetas en los campos de la Estructura

El uso de las etiquetas dentro de la definición de cada campo es un concepto sumamente importante, de esta manera cuando estemos trabajando con otros formatos como JSON o XML entre otros, nos facilitará la conversión(mapeo) de objetos en otro formato a nuestra estructura. Las etiquetas se agregan con los caracteres ` después del tipo de dato, estas etiquetas no interfieren en la ejecución del código.

Veamos un ejemplo donde simulamos la conversión de un objeto json a una estructura.

package main

import (
	"encoding/json"
	"fmt"
)

type Cantante struct {
	//agregamos las etiquetas despues del tipo de dato
	Nombre string `json:"nombre"`
	Grupo  string `json:"grupo"`
}

func main() {
	//simulamos un objeto json, con una variable string
	json_string := `
    {
        "nombre": "Nicky Sixx",
        "grupo": "Motley Crew"
    }`
	//creamos un objeto de tipo cantante
	cantante1 := new(Cantante)
	//con la función unmarshal vertimos el contenido del json al objeto cantante
	json.Unmarshal([]byte(json_string), cantante1)
	fmt.Println(cantante1)

	cantante2 := new(Cantante)
	cantante2.Nombre = "Freddy Mercury"
	cantante2.Grupo = "Queen"
	//con la función marshal creamos un objeto json apartir de un objeto cantante
	jsonStr, _ := json.Marshal(cantante2)
	fmt.Printf("%s\n", jsonStr)
}

Agregar Métodos a una Estructura

Es posible agregar métodos a las estructuras, usando un receptor de método (method receiver). Agregaremos un método llamado JugadorDetalle a la estructura Jugador.

package main

import "fmt"

//Declaramos la estructura que anidaremos
type Club struct {
	Nombre     string
	Temporadas int
}

//Declaramos la estructura principal
type Jugador struct {
	Nombre, Posicion string
	Edad             int
	//Realizamos un slice de la estructura Club
	Clubes []Club
}

//Creamos una función con el receiver (j Jugador) con lo cual el método
//es agregado a la estructura Jugador
func (j Jugador) JugadorDetalle() string {
	fmt.Println(j.Nombre, j.Posicion)
	fmt.Println(j.Edad)
	for _, detalle := range j.Clubes {
		fmt.Println("*********CLUB*******")
		fmt.Println(detalle.Nombre)
		fmt.Println(detalle.Temporadas)
	}
	return "*********CLUB*******"
}

func main() {
	//creamos una instancia de la estructura jugador
	j := Jugador{
		Nombre:   "Critiano Dos Santos",
		Posicion: "Delantero",
		Edad:     36,
		//agregamos elementos al slice de la estructura club
		Clubes: []Club{
			Club{
				Nombre:     "Lisboa",
				Temporadas: 2,
			},
			Club{
				Nombre:     "Manchester",
				Temporadas: 6,
			},
			Club{
				Nombre:     "Madrid",
				Temporadas: 6,
			},
		},
	}
	//invocamos el método JugadorDetalle
	fmt.Println(j.JugadorDetalle())
}

Copiar una Estructura mediante Valor y Apuntador

Cuando copiamos una estructura por valor , cualquier cambio realizado en la copia no afectara al objeto original y viceversa. A diferencia de cuando realizamos una copia por referencia usando &, cualquier campo en la copia será actualizado en el original.


package main

import "fmt"

type cuadrado struct {
	lado  float64
	color string
}

func main() {
	//creamos un objeto de tipo cuadrado
	c1 := cuadrado{40, "Azul"}
	fmt.Println(c1)

	//creamos una copia por valor de c1
	c2 := c1
	//actualizamos el valor de color
	c2.color = "Rojo"
	fmt.Println(c2)

	//creamos una referencia a c1
	c3 := &c1
	//actualizamos el valor de color
	c3.color = "Amarillo"
	//como vemos la copia afectó a la copia y al valor referenciado
	fmt.Println(c3)
	fmt.Println(c1)
}

Hemos llegado al final del manejo de estructuras, desde realizar operaciones básicas a trabajar con tags, ahora que conocemos el manejo y trato de estructuras en golang podemos implementar estructuras en nuestras aplicaciones.

Jesus Flores

Ingeniero de Software y Agile Coach

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *