Unlocking Go’s Empty Interface: How Any Type Becomes a Value
This article explains Go’s empty interface, showing how it can hold values of any type, how to declare and use it in functions and data structures, and why copying between concrete slices and empty‑interface slices requires element‑wise assignment due to its two‑word memory layout.
Empty Interface
In Go, an empty interface is an interface that defines no methods, meaning any type satisfies it and can be stored in a variable of that type.
Definition:
<code>type empty_int interface {}</code>Often abbreviated as
type empty_int interface{}or simply
interface{}.
Example of declaring an empty interface variable:
<code>var i interface{}</code>Using an empty interface as a function parameter, e.g., fmt.Print functions:
<code>func myfunc(i interface{}) {}</code>Common usage: fmt.Print* methods accept
...interface{}arguments.
Empty Interface Data Structures
You can create slices, arrays, maps, or structs of empty interface type to hold values of any type.
Example slice of empty interfaces:
<code>package main
import "fmt"
func main() {
any := make([]interface{}, 5)
any[0] = 11
any[1] = "hello world"
any[2] = []int{11, 22, 33, 44}
for _, value := range any {
fmt.Println(value)
}
}
</code>Output:
<code>11
hello world
[11 22 33 44]
<nil>
<nil>
</code>Thus, Go can store heterogeneous data similarly to dynamic languages.
Copying Data into Empty Interface Structures
Assigning any value to an empty interface variable stores both the type information and the value (two pointers).
The empty interface has a memory layout of two machine words. Copying a slice of concrete type directly into a slice of empty interfaces fails because of differing layouts.
<code>package main
import "fmt"
func main() {
testSlice := []int{11, 22, 33, 44}
// Successful copy
var newSlice []int
newSlice = testSlice
fmt.Println(newSlice)
// Failed copy
var any []interface{}
any = testSlice // compile error
fmt.Println(any)
}
</code>To copy, iterate over the source slice and append each element to the empty‑interface slice:
<code>var any []interface{}
for _, value := range testSlice {
any = append(any, value)
}
</code>This approach creates a slice where each element is an independent empty‑interface instance pointing to the original data.
Raymond Ops
Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.