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

Go Tipos Intermediário

Interfaces

Em Go, interfaces são tipos que definem um conjunto de métodos. Qualquer tipo que implemente todos esses métodos satisfaz a interface automaticamente, sem precisar declarar implements. Isso é chamado de satisfação implícita e permite desacoplamento e polimorfismo.

Interfaces pequenas, com um ou dois métodos, são idiomáticas em Go. Exemplos clássicos são io.Writer e fmt.Stringer. Quanto menor a interface, mais fácil é reutilizá-la e combiná-la.

O tipo any (alias para interface{}) representa qualquer valor. Para recuperar o tipo concreto por trás de uma interface, usamos type assertion (v, ok := i.(T)) ou type switch (switch v := i.(type)).

Neste card, você verá como definir interfaces, implementá-las implicitamente, usar any e fazer asserções de tipo com segurança.

Pontos-chave

  • Um tipo satisfaz uma interface automaticamente se tiver todos os métodos exigidos.
  • Prefira interfaces pequenas (1 ou 2 métodos) para maior reuso e testabilidade.
  • any é um alias para interface{} e aceita qualquer valor.
  • Type assertion v, ok := i.(T) verifica se o valor dinâmico é do tipo T sem causar panic.
  • Um type switch permite tratar vários tipos concretos de forma limpa.
interfaces.go
package main

import "fmt"

// Interface pequena: apenas um método
type Stringer interface {
	String() string
}

type Pessoa struct {
	Nome string
	Idade int
}

// Implementação implícita de Stringer
func (p Pessoa) String() string {
	return fmt.Sprintf("%s (%d anos)", p.Nome, p.Idade)
}

type Cachorro struct {
	Nome string
}

func (c Cachorro) String() string {
	return "Cachorro: " + c.Nome
}

// Função que aceita qualquer Stringer
func imprimir(s Stringer) {
	fmt.Println(s.String())
}

func main() {
	p := Pessoa{"Ana", 30}
	c := Cachorro{"Rex"}

	imprimir(p)
	imprimir(c)

	// any aceita qualquer valor
	var x any = 42
	if n, ok := x.(int); ok {
		fmt.Println("É int:", n)
	}

	// Type switch
	valores := []any{1, "texto", true, 3.14}
	for _, v := range valores {
		switch t := v.(type) {
		case int:
			fmt.Println("int:", t)
		case string:
			fmt.Println("string:", t)
		case bool:
			fmt.Println("bool:", t)
		default:
			fmt.Printf("outro tipo: %T\n", t)
		}
	}
}

Exercícios

  1. 1
    Fácil

    Implementando uma interface pequena

    Crie uma interface Saudacao com o método Ola() string. Defina um tipo Pessoa com campo Nome e implemente Ola() retornando "Olá, <Nome>!". No main, crie uma Pessoa e chame Ola() diretamente e via interface.

    Resolver
  2. 2
    Médio

    Usando any e type assertion

    Escreva uma função descrever(v any) string que retorne uma descrição do valor:

    • Se for int, retorne "inteiro: N".
    • Se for string, retorne "texto: S".
    • Caso contrário, retorne "tipo desconhecido". Use type assertion com a forma v, ok := i.(T) para checar os tipos. No main, chame a função com 42, "Go" e true e imprima os resultados.

    Resolver
  3. 3
    Desafio

    Interface pequena com múltiplas implementações

    Defina uma interface Forma com o método Area() float64. Crie dois tipos: Retangulo (campos Largura, Altura) e Circulo (campo Raio). Implemente Area() para ambos. Escreva uma função somaAreas(formas []Forma) float64 que some as áreas. No main, crie uma slice com um retângulo e um círculo, calcule a soma e imprima com duas casas decimais. Use math.Pi para o círculo.

    Resolver

Continue estudando