---
id: 548504c5a0b4857763527603f3e1059e
author: snowmerak
title: Any não é Any, mas Any é Any
description: Analisa detalhadamente o tipo `any` da linguagem Go e sua estrutura interna `EFace`, e descreve os métodos de tratamento dinâmico de tipos utilizando o pacote `reflect` e as asserções/switches de tipo.
language: pt
date: 2025-09-30T15:12:53.689280321Z
path: /blog/posts/any-is-not-any-but-any-is-any-z6161856d
category: language
---

## Any

Na linguagem Go, o tipo any é um alias para `interface{}`, uma interface mágica capaz de armazenar valores de qualquer tipo. Ou seja, qualquer tipo pode ser atribuído a uma variável do tipo any.

```go
var a any
a = 42          // int
a = "hello"     // string
a = true        // bool
a = 3.14        // float64
```

Dessa forma, o tipo any pode armazenar valores de diversos tipos, o que permite escrever código flexível. No entanto, ao usar o tipo any, há alguns pontos que requerem atenção.

### Type Assertion

Para utilizar o valor real de uma variável do tipo any, é necessário usar a asserção de tipo (type assertion). A asserção de tipo informa ao compilador que a variável any possui um tipo específico.

```go
var a any = "hello"
str, ok := a.(string)
if ok {
    fmt.Println("String value:", str)
} else {
    fmt.Println("Not a string")
}
```

No exemplo acima, `a.(string)` afirma que `a` é do tipo string. Caso `a` não seja do tipo string, `ok` será false, o que permite evitar que o programa entre em pânico.

### Type Switch

O switch de tipo (type switch) permite executar diferentes comportamentos de acordo com o tipo real de uma variável do tipo any. Isso é útil quando é necessário tratar vários tipos.

```go
var a any = 42
switch v := a.(type) {
case int:
    fmt.Println("Integer:", v)
case string:
    fmt.Println("String:", v)
case bool:
    fmt.Println("Boolean:", v)
default:
    fmt.Println("Unknown type")
}
```

No exemplo acima, `a.(type)` verifica o tipo real de `a` e executa o caso correspondente a esse tipo.

### Reflection

Ao utilizar o pacote reflect da linguagem Go, é possível inspecionar e manipular dinamicamente o tipo e o valor de uma variável do tipo any em tempo de execução. Isso é útil ao trabalhar com estruturas de dados complexas.

```go
import (
    "fmt"
    "reflect"
)

var a any = 3.14
v := reflect.ValueOf(a)
fmt.Println("Type:", v.Type())
fmt.Println("Value:", v.Float())
```

No exemplo acima, o pacote reflect é usado para verificar o tipo e o valor de `a` em tempo de execução.

## EFace

Na linguagem Go, as interfaces se dividem em duas formas principais: EFace (Empty Interface) e IFace (Interface with Methods). Dessas, EFace é o conceito idêntico ao tipo any que abordamos até aqui.

### Estrutura

EFace é uma estrutura especial que existe apenas dentro do runtime da linguagem Go; por isso, aqui vamos trabalhar criando um mimic (imitação).

```go
type runtimeTypeMimic struct {
	Size_       uintptr
	PtrBytes    uintptr // number of (prefix) bytes in the type that can contain pointers
	Hash        uint32  // hash of type; avoids computation in hash tables
	TFlag       uint8   // extra type information flags
	Align_      uint8   // alignment of variable with this type
	FieldAlign_ uint8   // alignment of struct field with this type
	Kind_       uint8   // enumeration for C
	Equal       func(unsafe.Pointer, unsafe.Pointer) bool
	GCData      *byte
	Str         int32 // string form
	PtrToThis   int32 // type for pointer to this type, may be zero
}

type eFaceMimic struct {
	Type *runtimeTypeMimic
	Data unsafe.Pointer
}
```

EFace possui dois campos:

- `Type`: um ponteiro que contém os metadados sobre o tipo real do valor.
- `Data`: um ponteiro que contém o valor real.

Além disso, o EFace gerencia as informações de tipo internamente por meio da estrutura `runtimeType`. Essa estrutura contém diversos metadados, como o tamanho do tipo, o alinhamento e o valor de hash.

Dentro dela, os pontos que devemos observar são os campos `Kind_`, `Hash` e `Equal`. `Kind_` representa a categoria do tipo, enquanto `Hash` e `Equal` são utilizados para calcular valores de hash e comparar tipos em tabelas de hash.

### Empacotamento

Agora, vamos encapsular este EFace para que seja possível usar a magia negra de forma mais conveniente.

```go
type TypeInfo struct {
	Hash  uint32
	TFlag uint8
	Kind  uint8
	Equal func(unsafe.Pointer, unsafe.Pointer) bool
	This  unsafe.Pointer
}

func GetTypeInfo(v any) TypeInfo {
	eface := *(*eFaceMimic)(unsafe.Pointer(&v))
	return TypeInfo{
		Hash:  eface.Type.Hash,
		TFlag: eface.Type.TFlag,
		Kind:  eface.Type.Kind_,
		Equal: eface.Type.Equal,
		This:  eface.Data,
	}
}
```

A função acima recebe uma variável do tipo any, extrai a estrutura EFace interna, obtém as informações de tipo a partir dela e as retorna como a estrutura `TypeInfo`. Agora, com este `TypeInfo`, é possível acessar facilmente o valor de hash, a categoria e a função de comparação do tipo.

### Utilização

A utilização é muito simples. Basta passar uma variável do tipo any para a função `GetTypeInfo`.

```go
func main() {
	i := 42
	eface := GetTypeInfo(i)
	fmt.Printf("%+v\n", eface)

	f := 3.14
	eface2 := GetTypeInfo(f)
	fmt.Printf("%+v\n", eface2)

	// Compare the two values using the Equal function from the type info
	log.Println(eface.Equal(eface.This, eface.This))
	log.Println(eface2.Equal(eface2.This, eface2.This))
	log.Println(eface2.Equal(eface.This, eface2.This))
	log.Println(eface.Equal(eface2.This, eface.This))
}
```

No exemplo acima, os valores inteiro e de ponto flutuante são passados para a função `GetTypeInfo`, que exibe as informações de tipo de cada um, e a função `Equal` é utilizada para comparar os valores. Dessa forma, é possível obter informações de tipo e compará-las de maneira mais rápida.

Além disso, esse método também pode ser aplicado a structs, ponteiros, interfaces e outros, e permite resolver o problema, nada incomum, do nil tipado (typed nil). `Hash` recebe um valor atribuído sempre que há um tipo, enquanto `This` é 0 quando é nil.

## Conclusão

O EFace desempenha um papel importante no tratamento do tipo any na linguagem Go atual. Por meio dele, é possível processar valores de diversos tipos de forma flexível e rápida, além de obter e utilizar informações detalhadas sobre os tipos. No entanto, trata-se de um recurso oculto no runtime, sujeito a alterações na especificação da linguagem, por isso é preciso ter cautela.
