Em Go, uma struct é uma sequência de elementos nomeados chamados campos, e cada campo tem um nome e um tipo.
O nome de um campo deve ser único dentro da struct.
As structs podem ser comparadas às classes do paradigma de Programação Orientada a Objetos.
Você cria uma nova struct usando as palavras-chave type e struct, e define explicitamente o nome e o tipo dos campos.
Por exemplo, aqui definimos a struct Shape, que guarda o nome de uma forma e o seu tamanho:
type Shape struct {
name string
size int
}
Os nomes dos campos em structs seguem a convenção do Go: campos cujo nome começa com letra minúscula são visíveis apenas para o código do mesmo pacote, enquanto os que começam com letra maiúscula são visíveis em outros pacotes.
Depois de definir a struct, você precisa criar uma nova instância informando os campos pelo nome, em qualquer ordem:
s := Shape {
name: "Square",
size: 25,
}
Para ler ou modificar os campos de uma instância, use a notação .:
// 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
Os campos que não recebem um valor inicial ficam com o valor zero do seu tipo. Por exemplo:
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
Você pode criar uma instância de uma struct sem usar os nomes dos campos, desde que defina os campos na ordem:
s := Shape {
"Oval",
20,
}
No entanto, essa sintaxe é considerada código frágil, pois pode quebrar quando um campo é adicionado, especialmente se o novo campo for de um tipo diferente.
No exemplo a seguir, adicionamos um 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{...}
Às vezes, é bom ter funções que nos ajudem a criar instâncias de structs.
Por convenção, essas funções costumam se chamar New ou ter nomes que começam com New, mas, como são apenas funções comuns, você pode dar a elas o nome que quiser.
Elas podem lembrar os construtores de outras linguagens, mas, em Go, são apenas funções comuns.
No exemplo a seguir, uma dessas funções New é usada para criar uma nova instância de Shape e definir automaticamente um valor padrão para o size da forma:
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 funções New pode trazer as seguintes vantagens:
New costumam ser declaradas no mesmo pacote das structs que inicializam, elas podem inicializar até os campos privados da structPara se aprofundar nesse tipo, você pode conferir estes recursos: Go by Example: Structs, A Tour of Go: Structs ou Structures in Go (structs)
new
Outra forma de criar uma nova instância de uma struct é usando a função embutida 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
Neste exemplo, new cria uma instância da struct Shape com todos os valores inicializados com o valor zero do seu tipo e retorna um ponteiro para ela.
Na maioria das vezes, você não vai ver novas instâncias de structs criadas com a função embutida new.
Prefira sempre usar um literal de struct, uma função New personalizada ou qualquer outra função fornecida pelo pacote que ajude você a construir uma struct.
Use a função embutida new para criar novas instâncias de structs apenas como último recurso.