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) }
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:
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:
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) }
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!
Buenos dias, en el ultimo ejemplo no veo la logica de usar apuntadores para los Struct, no he entendido para que usarlos. Me podrian explicar
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.