Da trilha de Go Este conceito ainda não saiu como card do dia. ir para o card de hoje

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 v tem o tipo concreto em cada case; em casos múltiplos, ela mantém o tipo da interface.
  • case nil captura 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.
type_switch.go
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
}

Exercícios

  1. 1
    Fácil

    Classificador de tipos básicos

    Escreva uma função classify(i interface{}) string que retorna:

    • "nulo" se i for nil
    • "inteiro" se for int
    • "texto" se for string
    • "outro" para qualquer outro tipo

    Use um type switch para implementar.

    Resolver
  2. 2
    Médio

    Somando números heterogêneos

    Implemente uma função sum(i interface{}) float64 que aceita um int, float64 ou []interface{} contendo números (int ou float64). Retorne a soma de todos os números. Para tipos não suportados, retorne 0 e imprima uma mensagem de aviso. Use type switch, inclusive para o slice.

    Resolver
  3. 3
    Desafio

    Processador de comandos com type switch

    Crie um sistema que processa comandos representados por interface{}. Os comandos possíveis são:

    • string: imprime "Executando: <comando>".
    • int: imprime "Código: <número>".
    • []string: executa cada string como comando.
    • nil: imprime "Comando vazio".
    • bool ou float64: imprime "Comando inválido: <valor>".
    • Qualquer outro tipo: imprime "Tipo desconhecido: <tipo>".

    Implemente process(cmd interface{}) usando type switch, incluindo casos múltiplos para bool e float64. Demonstre com exemplos, incluindo um slice de strings e um nil.

    Resolver

Continue estudando