| Tipo | Nome | Valor Padrão | Observação |
|---|---|---|---|
| pointer | Ponteiro | nil | |
| array | Array | 0 | Tamanho fixo |
| slice | Slice | nil | Tipo por referência |
| map | Mapa | nil | Tipo por referência |
| struct | Struct | zero value |
Arrays
Para armazenar as notas de matemática de uma turma, criar dezenas de variáveis individuais seria impraticável. A solução é utilizar um array: uma coleção de elementos do mesmo tipo.
Declaração
var notas [10]int
A declaração usa a palavra-chave var, seguida do nome da variável, do tamanho entre colchetes e do tipo. O array notas armazena 10 valores inteiros.
Verificação do tamanho:
var notas [10]int
fmt.Println(cap(notas)) // 10
Ao declarar o array, o Go aloca um bloco contínuo de memória. Cada posição armazena um elemento, e o total de posições define o comprimento.
var tamanho int = 10
var notas [tamanho]int // ERRO: tamanho não é constante
Structs agrupam campos relacionados em uma única entidade:
package main
import "fmt"
func main() {
// Definição do struct
type Pessoa struct {
codigo int
nome string
idade int
cidade string
}
// Inicialização por posição
aluno := Pessoa{1, "Ana", 21, "São Paulo"}
fmt.Println(aluno) // {1 Ana 21 São Paulo}
// Inicialização com campos nomeados
professor := Pessoa{nome: "Carlos"}
fmt.Println(professor) // {0 Carlos 0 }
// Acesso e modificação de campos
aluno.codigo = 100
fmt.Println(aluno.codigo)
// Comparação de structs
fmt.Println(aluno == professor) // false
// Atribuição entre structs do mesmo tipo
var copia Pessoa
copia = professor
fmt.Println(copia)
}
Composição com Campos Anônimos
Go permite incorporar tipos sem nome explícito de campo, promovendo seus campos para o escopo da struct externa:
// Base
type SerHumano struct {
nome string
sexo byte
idade int
}
// Derivada com composição
type Aluno struct {
SerHumano // Campo anônimo: todos os campos de SerHumano são acessíveis diretamente
matricula int
endereco string
}
Inicialização de Structs Compositos
// Inicialização completa
a1 := Aluno{SerHumano{"Pedro", 'm', 20}, 123, "RJ"}
fmt.Printf("%+v\n", a1)
// Inicialização parcial com campos nomeados
a2 := Aluno{SerHumano: SerHumano{"Maria", 'f', 22}, matricula: 456}
fmt.Printf("%+v\n", a2)
// Inicialização seletiva do campo anônimo
a3 := Aluno{SerHumano: SerHumano{nome: "João"}, matricula: 789}
fmt.Printf("%+v\n", a3)
Manipulação de Campos Promovidos
var a Aluno
// Acesso direto aos campos promovidos
a.nome = "Pedro" // equivale a: a.SerHumano.nome = "Pedro"
a.sexo = 'm'
a.idade = 20
a.matricula = 123
a.endereco = "Rio"
fmt.Println(a)
// Atribuição do campo anônimo completo
var b Aluno
b.SerHumano = SerHumano{"Maria", 'f', 21}
b.matricula = 456
b.endereco = "SP"
fmt.Println(b)
Resolução de Nomes Duplicados
Quando campos de mesmo nome existem, a prioridade é do nível mais externo:
type SerHumano struct {
nome string
idade int
}
type Funcionario struct {
SerHumano
cargo string
nome string // Colisão de nomes
}
func main() {
var f Funcionario
f.nome = "Silva" // Atribui a Funcionario.nome
f.SerHumano.nome = "Sousa" // Atribui a SerHumano.nome explicitamente
fmt.Printf("%+v\n", f)
}
Tipos Anônimos Diversos
Tipos Básicos e Customizados
type TextoCustom string
type Dados struct {
SerHumano // Struct anônimo
int // Tipo básico anônimo
TextoCustom // Tipo customizado anônimo
}
func main() {
d := Dados{SerHumano{"Luiz", 'm', 30}, 100, "SP"}
// Acesso direto
fmt.Printf("%s, %d, %s\n", d.nome, d.int, d.TextoCustom)
}
Ponetiro para Struct Anônimo
type Empregado struct {
*SerHumano // Ponteiro para struct anônimo
registro int
setor string
}
func main() {
// Inicialização com ponteiro literal
e1 := Empregado{&SerHumano{"Fernanda", 'f', 28}, 1000, "TI"}
fmt.Printf("%+v\n", e1)
// Inicialização com alocação dinâmica
var e2 Empregado
e2.SerHumano = new(SerHumano)
e2.nome = "Ricardo"
e2.idade = 35
e2.registro = 1001
e2.setor = "RH"
fmt.Println(e2.nome, e2.idade, e2.registro)
}
Structs com Mutex para Concorrência
package main
import (
"fmt"
"sync"
)
type CadastroIdades struct {
valores map[string]int
sync.RWMutex
}
func (c *CadastroIdades) Definir(nome string, idade int) {
c.Lock()
defer c.Unlock()
c.valores[nome] = idade
}
func (c *CadastroIdades) Consultar(nome string) int {
c.RLock()
defer c.RUnlock()
if idade, existe := c.valores[nome]; existe {
return idade
}
return -1
}
func main() {
base := make(map[string]int)
base["sistema"] = 5
registro := CadastroIdades{valores: base}
registro.Definir("teste", 25)
fmt.Println(registro.Consultar("sistema")) // 5
fmt.Println(registro.Consultar("teste")) // 25
fmt.Println(registro.Consultar("inexistente")) // -1
}