Funções, métodos e interfaces são componentes fundamentais da linguagem Go, oferecenod mecanismos poderosos para estruturar e organizar o código.
Funções
Go suporta tanto funções nomeadas quanto anônimas. Funções nomeadas geralmente são definidas no nível do pacote, enquanto as anônimas podem ser atribuídas a variáveis ou usadas como argumentos de outras funções. Quando uma função anônima captura variáveis de seu escopo externo, ela se torna um fechamento (closure).
Exemplo de Funções
// Função nomeada
func somar(x, y int) int {
return x + y
}
// Função anônima
var somarAnonima = func(x, y int) int {
return x + y
}
As funções em Go também podem aceitar um número variável de argumentos, mas esses argumentos devem ser os últimos na lista de parâmetros. Internamente, esses argumentos são tratados como um slice.
Exemplo de Função com Parâmetros Variáveis
func incrementar() (v int) {
defer func() { v++ }()
return 42
}
Neste exemplo, a instrução defer executa uma função anônima após o retorno da função incrementar. Esta função anônima captura a variável local v, formando um fechamento. O fechamento não copia a variável v, mas sim mantém uma referência a ela.
Métodos
Métodos em Go são funções associadas a tipos específicos, permitindo operações orientadas a objetos. Cada tipo e seus métodos devem ser definidos no mesmo pacote. Além disso, os nomes dos métodos devem ser únicos dentro do tipo, e não há suporte a sobrecarga de métodos.
Exemplo de Métodos
// Método para fechar um arquivo
func (arquivo *Arquivo) Fechar() erro {
// implementação
}
// Método para ler dados de um arquivo
func (arquivo *Arquivo) Ler(offset int64, dados []byte) int {
// implementação
}
Em Go, a herança pode ser simulaad através da incorporação de structs anônimos. Isso permite que um tipo herde campos e métodos de outro tipo.
Exemplo de Herança por Incorporação
type Cache struct {
dados map[string]string
sync.Mutex
}
func (cache *Cache) Buscar(chave string) string {
cache.Lock()
defer cache.Unlock()
return cache.dados[chave]
}
No exemplo acima, a struct Cache incorpora sync.Mutex, herdando assim os métodos Lock e Unlock.
Interfaces
Interfaces em Go são conjuntos de assinaturas de métodos. Elas permitem polimorfismo, pois a ligação entre a interface e sua implementação ocorre em tempo de execução.
Exemplo de Interface
package principal
import (
"fmt"
"testing"
)
type Testador struct {
testing.TB
}
func (t *Testador) Fatal(args ...interface{}) {
fmt.Println("Fatal desabilitado!")
}
func main() {
var tb testing.TB = &Testador{}
tb.Fatal("Olá, playground")
}
Neste exemplo, Testador incorpora a interface testing.TB e redefine o método Fatal. A interface testing.TB é implicitamente implementada por Testador.
Interfaces em Go permitem conversões implícitas entre objetos e interfaces, facilitando a composição de código flexível e reutilizável.