Pular para o conteúdo principal

victorstein.dev

81/100 Dias de Golang - Reflect

Table of Contents

# Reflect

Go é uma linguagem fortemente tipada, mas em alguns tipos de aplicações temos que trabalhar com tipos dinâmicos, exemplo disso é quando usamos um serializador ou ferramentas que inspecionam e manipulam structs no runtime. Para esses casos, a linguagem oferece o pacote reflect. O pacote reflect fornece reflexão de tempo de execução: a capacidade de inspecionar tipos, valores, e até modificar dados dinamicamente. Ele permite:

  1. Verificar o tipo de um valor genérico
  2. Obter campos e tags de structs
  3. Chamar métodos dinamicamente
  4. Modificar valores - Parece perigoso

O reflect gira em torno de dois tipos principais:

  • reflect.Type: representa o tipo de um valor
  • reflect.Value: representa o valor em si, e permite lê-lo ou alterá-lo

Vamos ver como isso funciona:

package main

import (
	"fmt"
	"reflect"
)

func main() {
	var x float64 = 3.14
	t := reflect.TypeOf(x)
	v := reflect.ValueOf(x)

	fmt.Println("Tipo:", t)  
	fmt.Println("Valor:", v) 
	fmt.Println("Tipo do valor:", v.Type())
	fmt.Println("É float64?", v.Kind() == reflect.Float64)
}

Saída:

Tipo: float64
Valor: 3.14
Tipo do valor: float64
É float64? true

Uma coisa muito “legal” que podemo fazer é chamar os métodos de forma dinâmica com o reflect

package main

import (
	"fmt"
	"reflect"
)

type Pessoa struct{}

func (Pessoa) Falar(msg string) {
	fmt.Println("Falando:", msg)
}

func main() {
	p := Pessoa{}
	v := reflect.ValueOf(p)
	m := v.MethodByName("Falar")
	if m.IsValid() {
		args := []reflect.Value{reflect.ValueOf("Olá victorstein.dev!")}
		m.Call(args)
	}
}

O reflect é muito útil em algumas situações, serializer e desserializar JSON, inspecionar tags em structs, mapeamento de structs e várias outras. Mas todas são bem específicas. Pelas coisas que li o reflect deve ser usado com muito cuidado, vários alertas sobre complexidade do código, performance e segurança de tipos.