Go Tipos Intermediário
Type switch
Em Go, um type switch é uma construção que permite executar diferentes blocos de código dependendo do tipo dinâmico armazenado em uma variável de interface. A sintaxe switch v := x.(type) declara uma nova variável v cujo tipo estático muda em cada case, já com o valor extraído e convertido para o tipo correspondente. Isso evita asserções de tipo repetitivas e torna o código mais limpo e seguro.
Um ponto crucial é o tratamento de nil. Se a interface x for nil, o type switch entra no case nil. Se x contém um valor não nulo, mas o tipo subjacente é, por exemplo, *int e o ponteiro é nil, o case será *int (não nil). Essa distinção entre interface nula e valor nulo dentro da interface é uma fonte comum de bugs.
Também é possível agrupar vários tipos em um único case, como case int, int64:. Nesse caso, a variável v terá o tipo da interface original (por exemplo, interface{}), pois o compilador não pode garantir qual dos tipos foi correspondido. Para acessar o valor concreto, ainda é necessário fazer uma asserção de tipo dentro do bloco.
O type switch é especialmente útil ao processar dados heterogêneos, como JSON decodificado em map[string]interface{}, ou ao implementar funções que aceitam any. Ele combina a flexibilidade das interfaces com a segurança de tipos em tempo de execução.
Pontos-chave
switch v := x.(type)só pode ser usado com variáveis de tipo interface.- A variável
vtem o tipo concreto em cadacase; em casos múltiplos, ela mantém o tipo da interface. case nilcaptura quando a interface é nula, não quando o valor interno é nulo.- É possível agrupar tipos:
case int, float64:. - O
defaulté executado quando nenhum tipo corresponde e é opcional.
package main
import "fmt"
func describe(i interface{}) {
switch v := i.(type) {
case nil:
fmt.Println("interface nula")
case int:
fmt.Printf("int: %d\n", v)
case string:
fmt.Printf("string: %q\n", v)
case bool, float64:
// v tem tipo interface{} aqui
fmt.Printf("bool ou float64: %v (tipo %T)\n", v, v)
default:
fmt.Printf("tipo desconhecido: %T\n", v)
}
}
func main() {
describe(42)
describe("olá")
describe(true)
describe(3.14)
describe(nil)
describe([]int{1, 2, 3})
var p *int
describe(p) // *int, não nil
}