En Go, un struct es una secuencia de elementos con nombre llamados campos, y cada campo tiene un nombre y un tipo.
El nombre de un campo debe ser único dentro del struct.
Los structs se pueden comparar con las clases del paradigma de la programación orientada a objetos.
Para crear un struct se usan las palabras clave type y struct, y se define explícitamente el nombre y el tipo de los campos.
Por ejemplo, aquí definimos el struct Shape, que contiene el nombre de una figura y su tamaño:
type Shape struct {
name string
size int
}
Los nombres de los campos de un struct siguen la convención de Go: los campos cuyo nombre empieza por minúscula solo son visibles para el código del mismo paquete, mientras que los que empiezan por mayúscula son visibles en otros paquetes.
Una vez definido el struct, tienes que crear una instancia nueva indicando los campos por su nombre, en cualquier orden:
s := Shape {
name: "Square",
size: 25,
}
Para leer o modificar los campos de una instancia, usa la notación con .:
// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35
Los campos a los que no se les asigna un valor inicial tendrán su valor cero. Por ejemplo:
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
Puedes crear una instancia de un struct sin usar los nombres de los campos, siempre que los definas en orden:
s := Shape {
"Oval",
20,
}
Sin embargo, esta sintaxis se considera código frágil, ya que puede romperse cuando se añade un campo, sobre todo si el campo nuevo es de un tipo distinto.
En el siguiente ejemplo añadimos un campo extra a Shape:
type Shape struct {
name string
description string // new field 'description' added
size int
}
s := Shape{
"Circle",
20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}
A veces resulta útil tener funciones que nos ayuden a crear instancias de un struct.
Por convención, estas funciones suelen llamarse New o tener nombres que empiezan por New, pero como no son más que funciones normales, puedes darles el nombre que quieras.
Puede que te recuerden a los constructores de otros lenguajes, pero en Go son funciones normales y corrientes.
En el siguiente ejemplo, se usa una de estas funciones New para crear una instancia nueva de Shape y establecer automáticamente un valor predeterminado para el size de la figura:
func NewShape(name string) Shape {
return Shape{
name: name,
size: 100, //default-value for size is 100
}
}
NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }
Usar funciones New puede tener las siguientes ventajas:
New suelen declararse en el mismo paquete que los structs que inicializan, pueden inicializar incluso los campos privados del structPara profundizar en este tipo, puedes consultar estos recursos: Structs en Go by Example, Structs en A Tour of Go o Structures in Go (structs)
new
Otra forma de crear una instancia nueva de un struct es usar la función incorporada new:
s := new(Shape) // s will be of type *Shape (pointer to shape)
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: size: 0
En este ejemplo, new crea una instancia del struct Shape con todos los valores inicializados al valor cero de su tipo y devuelve un puntero a ella.
La mayoría de las veces no verás instancias nuevas de structs creadas con la función incorporada new.
Siempre es preferible usar un literal de struct, una función New personalizada o cualquier otra función que proporcione el paquete y que te ayude a construir un struct.
Usa la función incorporada new para crear instancias nuevas de structs solo como último recurso.