---
id: 548504c5a0b4857763527603f3e1059e
author: snowmerak
title: Any is not Any, but Any is Any
description: This document provides a detailed analysis of Go's `any` type and its internal `EFace` structure, and explains dynamic type handling methods utilizing the `reflect` package as well as type assertions and type switches.
language: en
date: 2025-09-30T15:12:53.689280321Z
path: /blog/posts/any-is-not-any-but-any-is-any-z6161856d
category: language
---

## Any

In the Go language, the any type is an alias for `interface{}`, a magical interface capable of holding values of every type. In other words, a variable of type any can be assigned a value of any type.

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

In this way, the any type can hold values of various types, allowing you to write flexible code. However, there are several points to be careful about when using the any type.

### Type Assertion

To use the actual value held in an any type variable, you must use a type assertion. A type assertion serves to inform the compiler that an any type variable is of a specific type.

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

In the example above, `a.(string)` asserts that `a` is of type string. If `a` is not of type string, `ok` becomes false, which prevents the program from panicking.

### Type Switch

A type switch allows you to perform different actions depending on the actual type of an any type variable. This is useful when you need to handle multiple types.

```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")
}
```

In the example above, `a.(type)` inspects the actual type of `a` and executes the case that matches that type.

### Reflection

Using the reflect package in Go, you can dynamically inspect and manipulate the type and value of an any type variable at runtime. This is useful when working with complex data structures.

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

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

In the example above, the reflect package is used to check the type and value of `a` at runtime.

## EFace

In the Go language, interfaces are divided into two main forms: EFace (Empty Interface) and IFace (Interface with Methods). Of these, EFace is the same concept as the any type we have covered so far.

### Structure

Since EFace is a special structure that exists only within the Go runtime, we will work with a mimic here.

```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 has two fields:

- `Type`: A pointer that holds metadata about the actual type of the value.
- `Data`: A pointer that holds the actual value.

Additionally, EFace internally manages type information through the `runtimeType` structure. This structure contains various metadata, such as the size, alignment, and hash value of the type.

Within this, the parts we should pay attention to are the `Kind_`, `Hash`, and `Equal` fields. `Kind_` indicates the kind of the type, while `Hash` and `Equal` are used to compare types and compute hash values in hash tables.

### Wrapping

Now, let's wrap this EFace so that we can use black magic more conveniently.

```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,
	}
}
```

The above function takes an any type variable, extracts the internal EFace structure, retrieves the type information from it, and returns it as a `TypeInfo` structure. Now you can easily access the type's hash value, kind, comparison function, and so on using this `TypeInfo`.

### Usage

Usage is really simple. You just pass an any type variable to the `GetTypeInfo` function.

```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))
}
```

In the example above, integer and floating-point values are passed to the `GetTypeInfo` function to print their respective type information, and the `Equal` function is used to compare the values. Through this, you can obtain type information and compare types more quickly.

In addition, this approach can be used identically for structs, pointers, interfaces, and so on, and it can also resolve the typed nil problem, a fairly common issue. `Hash` will be assigned if a type exists, whereas `This` is 0 if it is nil.

## Conclusion

EFace plays an important role in handling the any type in the current Go language. Through it, values of various types can be processed flexibly and quickly, and type information can be obtained and utilized in detail. However, since this is a feature hidden within the runtime, it may be affected by changes to the language specification, so caution is required.
