---
id: 548504c5a0b4857763527603f3e1059e
author: snowmerak
title: Any er ikke Any, men Any er Any
description: Der analyseres detaljeret Go-sprogets `any`-type og den interne `EFace`-struktur, og der forklares metoder til dynamisk typehåndtering ved hjælp af `reflect`-pakken samt type-assertions og type-switches.
language: da
date: 2025-09-30T15:12:53.689280321Z
path: /blog/posts/any-is-not-any-but-any-is-any-z6161856d
category: language
---

## Any

I Go er any-typen et alias for `interface{}`, en magisk grænseflade, der kan rumme alle typer. Det betyder, at en værdi af hvilken som helst type kan tildeles en any-variabel.

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

Således gør any-typen det muligt at skrive fleksibel kode, da den kan indeholde værdier af forskellige typer. Ved brug af any-typen bør man dog være opmærksom på nogle forhold.

### Type Assertion

For at anvende den faktiske værdi i en any-variabel skal man bruge en typeassertion (type assertion). Typeassertionen fortæller compileren, at any-variablen har en bestemt type.

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

I eksemplet ovenfor fastslår `a.(string)`, at `a` er af typen string. Hvis `a` ikke er af typen string, bliver `ok` false, og programmet undgår at gå i panik.

### Type Switch

En type switch (type switch) gør det muligt at udføre forskellige handlinger afhængigt af den faktiske type i en any-variabel. Dette er nyttigt, når flere typer skal håndteres.

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

I eksemplet ovenfor undersøger `a.(type)` den faktiske type af `a` og udfører den case, der svarer til denne type.

### Reflection

Ved hjælp af pakken reflect i Go kan man dynamisk undersøge og manipulere typen og værdien af en any-variabel under kørsel. Dette er nyttigt, når man arbejder med komplekse datastrukturer.

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

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

I eksemplet ovenfor bruges pakken reflect til at bestemme typen og værdien af `a` under kørsel.

## EFace

I Go deles grænseflader op i to hovedformer: EFace (Empty Interface) og IFace (Interface with Methods). Af disse er EFace det samme koncept som any-typen, som vi hidtil har behandlet.

### Struktur

EFace er en speciel struktur, der kun findes inde i Go's runtime, og derfor vil vi her arbejde med en mimic (mimic) til at efterligne den.

```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 har to felter:

- `Type`: En pointer, der indeholder metadata om værdiens faktiske type.
- `Data`: En pointer, der indeholder selve værdien.

EFace administrerer desuden typeinformation internt gennem strukturen `runtimeType`. Denne struktur indeholder forskellige metadata, såsom typens størrelse, justering og hashværdi.

De felter, vi bør være særligt opmærksomme på, er `Kind_`, `Hash` og `Equal`. `Kind_` angiver typens art, mens `Hash` og `Equal` bruges til at beregne hashværdier og sammenligne typer i hashtabeller.

### Indpakning

Lad os nu indpakke denne EFace, så vi kan anvende den sorte magi mere bekvemt.

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

Ovenstående funktion modtager en any-variabel, udtrækker den interne EFace-struktur, henter typeinformationen herfra og returnerer den som en `TypeInfo`-struktur. Med denne `TypeInfo` kan man nu nemt tilgå typens hashværdi, art, sammenligningsfunktion m.m.

### Anvendelse

Anvendelsen er meget enkel. Man sender blot en any-variabel til funktionen `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))
}
```

I eksemplet ovenfor sendes en heltalsværdi og en flydende kommaværdi til `GetTypeInfo`, hvorefter typeinformationen for hver af dem udskrives, og værdierne sammenlignes ved hjælp af funktionen `Equal`. På den måde kan man hurtigere få typeinformation og sammenligne typer.

Denne metode kan desuden anvendes på structs, pointere, grænseflader m.m., og den kan også løse det hyppigt forekommende problem med typed nil. `Hash` er tildelt, hvis der findes en type, mens `This` er 0, hvis værdien er nil.

## Konklusion

EFace spiller i dag en vigtig rolle, når any-typen skal håndteres i Go. Det gør det muligt at behandle værdier af forskellige typer fleksibelt og effektivt, og typeinformation kan hentes og anvendes i detaljer. Det skal dog bemærkes, at dette er en skjult funktionalitet inde i runtime, som kan blive påvirket af ændringer i sprogspecifikationen, og derfor bør man udvise forsigtighed.
