11. Go to go: registros (estructuras) en Golang

Publicado por

Anteriormente traté el tema de arreglos, recordemos que estos nos permiten almacenar una colección de datos del mismo tipo bajo un único identificador.

Si queremos almacenar datos de diferentes miembros de un conjunto, pero dichos datos no corresponden al mismo tipo, podemos recurrir a los struct o registros.

Un struct es un registro que guarda datos de diferentes tipos. Imagina que deseas almacenar información de películas. Todas las películas comparten características generales pero con diferentes valores; por ejemplo, todas las películas tienen los siguientes características:

  • Título
  • Director
  • Protagonistas
  • Año de estreno

Con un struct puedes crear fácilmente registros de películas que almacenen los campos anteriores para cada una de ellas.

Sintaxis

Para definir un struct seguimos la siguiente sintaxis:

Struct = "struct" "{" { Campo_declaraciones ";" } "}"
Campo_declaraciones = (Lista_identificadores | Campo_anónimo) [Etiqueta]
Campo_anónimo = [ "*" ] Nombre_tipo
Etiqueta = Cadena_literal

Más información al respecto aquí.

Nota: para declarar variables de un struct que ya ha sido definido, se utiliza la sintaxis de declaración de variables con la que hemos trabajado (ejemplos más adelante):

Ejemplo de funcionamiento

En el siguiente programa defino un struct que almacenará información de películas, declaro dos variables de tipo Pelicula, asigno los datos correspondientes a cada una de ellas y, finalmente, imprimo lo que acabo de almacenar (los tabulares en la impresión se utilizan para aplicar estilo y son completamente arbitrarios).

package main

import "fmt"

//Definición de struct Pelicula
type Pelicula struct{
  titulo string
  director string
  protagonistas string
  año int //Recordemos que Go permite utilizar 'ñ' en identificadores
}

func main(){
  /*Declaración de variables tipo Pelicula*/
  var peli01 Pelicula
  var peli02 Pelicula

  /*Llenamos cada variable con la información
  correspondiente para cada película*/
  peli01.titulo = "Titanic"
  peli01.director = "James Cameron"
  peli01.protagonistas = "Leonardo DiCaprio,Kate Winslet"
  peli01.año = 1997

  peli02.titulo = "Soy leyenda"
  peli02.director = "Francis Lawrence"
  peli02.protagonistas = "Will Smith"

  peli02.año = 2007

  /*Imprimimos la información de las películas*/
  fmt.Printf("NOMBRE\t\tDIRECTOR\t\tPROTAGONISTAS\t\t\tAÑO\n")
  fmt.Printf("%s\t\t", peli01.titulo)
  fmt.Printf("%s\t\t", peli01.director)
  fmt.Printf("%s\t", peli01.protagonistas)
  fmt.Printf("%d\n", peli01.año)
  fmt.Printf("%s\t", peli02.titulo)
  fmt.Printf("%s\t", peli02.director)
  fmt.Printf("%s\t\t\t", peli02.protagonistas)
  fmt.Printf("%d\n", peli02.año)
}

Salida:
01-golang-struct

Arreglos de struct

Si no queremos crear variables con diferentes nombres, podemos declarar un arreglo de struct, y de ese modo trabajar bajo un mismo identificador con todos nuestros registros. El siguiente ejemplo demuestra este funcionamiento:

package main
import "fmt"

//Definición
type Pelicula struct{
  titulo string
  director string
  protagonistas string
  año int
}

func main(){
  /*Declaración de arreglo tipo Pelicula*/
  var pelis[2] Pelicula

  /*Llenamos cada índice con la información
  correspondiente para cada película*/
  pelis[0].titulo = "Titanic"
  pelis[0].director = "James Cameron"
  pelis[0].protagonistas = "Leonardo DiCaprio,Kate Winslet"
  pelis[0].año = 1997

  pelis[1].titulo = "Soy leyenda"
  pelis[1].director = "Francis Lawrence"
  pelis[1].protagonistas = "Will Smith"
  pelis[1].año = 2007

  /*Imprimimos la información de las películas*/
  fmt.Printf("NOMBRE\t\tDIRECTOR\t\tPROTAGONISTAS\t\t\tAÑO\n")
  fmt.Printf("%s\t\t", pelis[0].titulo)
  fmt.Printf("%s\t\t", pelis[0].director)
  fmt.Printf("%s\t", pelis[0].protagonistas)
  fmt.Printf("%d\n", pelis[0].año)
  fmt.Printf("%s\t", pelis[1].titulo)
  fmt.Printf("%s\t", pelis[1].director)
  fmt.Printf("%s\t\t\t", pelis[1].protagonistas)
  fmt.Printf("%d\n", pelis[1].año)
}

Salida:

02-golang-struct

struct como argumento de una función

Puedes pasar un struct como argumento a una función tal como si pasaras cualquier otra variable:

package main
import "fmt"

type Pelicula struct{
  titulo string
  director string
  protagonistas string
  año int
}

func main(){
  /*Declaración de variables tipo Pelicula*/
  var pelis[2] Pelicula

  /*Llenamos cada variable con la información
  correspondiente para cada película*/
  pelis[0].titulo = "Titanic"
  pelis[0].director = "James Cameron"
  pelis[0].protagonistas = "Leonardo DiCaprio,Kate Winslet"
  pelis[0].año = 1997

  pelis[1].titulo = "Soy leyenda"
  pelis[1].director = "Francis Lawrence"
  pelis[1].protagonistas = "Will Smith"
   pelis[1].año = 2007

  /*Imprimimos la información de las películas*/
  imprimePelicula(pelis[0])
  imprimePelicula(pelis[1])
}

//Función que imprime la información de una película
func imprimePelicula(peli Pelicula){
  fmt.Printf("NOMBRE: %s\n", peli.titulo)
  fmt.Printf("DIRECTOR: %s\n", peli.director)
  fmt.Printf("PROTAGONISTAS: %s\n", peli.protagonistas)
  fmt.Printf("AÑO: %d\n\n", peli.año)
}

Salida:

03-golang-struct

Apuntadores a struct

También puedes utilizar apuntadores a struct.

Usando el ejemplo anterior, declaremos un apuntador a un struct Pelicula:

var ptpeli *Pelicula

Asignemos una dirección de memoria al apuntador:

ptpeli = &peli01

Imprimamos la variable titulo del struct:

fmt.Println(ptpeli.titulo)

Modifiquemos el ejemplo para que la función imprimePelicula reciba un apuntador como argumento:

package main
import "fmt"

type Pelicula struct{
  titulo string
  director string
  protagonistas string
  año int
}

func main(){
  /*Declaración de variables tipo Pelicula*/
  var pelis[2] Pelicula

  /*Llenamos cada variable con la información
  correspondiente para cada película*/
  pelis[0].titulo = "Titanic"
  pelis[0].director = "James Cameron"
  pelis[0].protagonistas = "Leonardo DiCaprio,Kate Winslet"
  pelis[0].año = 1997

  pelis[1].titulo = "Soy leyenda"
  pelis[1].director = "Francis Lawrence"
  pelis[1].protagonistas = "Will Smith"
  pelis[1].año = 2007

  /*Para imprimir la información de las películas*/
  imprimePelicula(&pelis[0])
  imprimePelicula(&pelis[1])
}

//Función que imprime una variable tipo Pelicula por medio de un apuntador
func imprimePelicula(pt_peli *Pelicula){
  fmt.Printf("NOMBRE: %s\n", pt_peli.titulo)
  fmt.Printf("DIRECTOR: %s\n", pt_peli.director)
  fmt.Printf("PROTAGONISTAS: %s\n", pt_peli.protagonistas)
  fmt.Printf("AÑO: %d\n\n", pt_peli.año)
}

Salida:
04-golang-struct

Nota: Este es solo un ejemplo de cómo pasar un apuntador como argumento a una función, lo cual sería necesario si, por ejemplo, quisieramos modificar el struct original adentro de dicha funcion. Si quieres saber más al respecto de paso por referencia te recomiendo leer esta nota.

Finalizando…

Esto ha sido todo por esta ocasión, espero que te haya sido de utilidad. Nos vemos la próxima, see ya!

2 comments

    1. Hola, lamento si no explico bien esa parte. El objetivo de esa función es solo mostrarte cómo se pasa un apuntador a struct en Golang. Doy por hecho que el lector ya conoce la utilidad/diferencia de pasar referencias o valores a una función . Si te interesa saber un poco mas acerca de este tema, te recomiendo leer esta entrada: http://codingornot.com/cuando-se-utiliza-paso-por-referencia-y-cuando-paso-por-valor

      Le dare una revisada a esta entrada a la brevedad, gracias por tu comentario.

Deja una respuesta

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