Empty Interface (any)
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 28 of 107.
The empty interface is an interface with zero methods. Since every type in Go has at least zero methods, every type automatically satisfies the empty interface. This makes it capable of holding values of any type.
var anything interface{}
anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}Starting with Go 1.18, the keyword any was introduced as an alias for interface{}. They're completely interchangeable, but any is cleaner to read.
var value any = "Go is awesome"The empty interface is useful when you need to handle values of unknown or varying types. Functions like fmt.Println use it to accept arguments of any type:
func PrintAnything(v any) {
fmt.Println("Value:", v)
}
func main() {
PrintAnything(100)
PrintAnything("text")
PrintAnything(3.14)
}However, there's a tradeoff. When a value is stored in an empty interface, you lose access to its specific type information.
You can't directly call methods or access fields without first extracting the underlying type. The next lessons will cover how to retrieve the concrete type from an empty interface using type assertions and type switches.
Challenge
EasyLet's build a flexible storage container that can hold values of any type using the empty interface. You'll create a simple box that demonstrates how any allows you to store different types in the same structure.
You'll organize your code across two files:
box.go: Define aBoxstruct with a single fieldContentof typeany. Create aNewBoxconstructor function that accepts a value of any type and returns a pointer to a Box containing that value. Add aDescribemethod that returns a string showing what's stored in the box.main.go: Read different values from input, create boxes containing an integer, a string, and a boolean, then print the description of each box to show how the same Box type can hold completely different values.
The following inputs will be provided:
- Line 1: An integer value
- Line 2: A string value
- Line 3: A boolean value (
trueorfalse)
Your Describe method should return a string in this format:
Box contains: [value]For example, given 42, hello, and true, your output should be:
Box contains: 42
Box contains: hello
Box contains: trueThe key insight here is that your single Box struct can store an integer, a string, or a boolean—all because the any type accepts values of any type. Each box holds something different, yet they're all the same Box type.
Cheat sheet
The empty interface (interface{}) is an interface with zero methods. Since every type in Go has at least zero methods, every type automatically satisfies the empty interface, making it capable of holding values of any type.
var anything interface{}
anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}Starting with Go 1.18, the keyword any was introduced as an alias for interface{}. They're completely interchangeable, but any is cleaner to read:
var value any = "Go is awesome"The empty interface is useful for handling values of unknown or varying types. Functions can accept arguments of any type:
func PrintAnything(v any) {
fmt.Println("Value:", v)
}
func main() {
PrintAnything(100)
PrintAnything("text")
PrintAnything(3.14)
}Tradeoff: When a value is stored in an empty interface, you lose access to its specific type information. You can't directly call methods or access fields without first extracting the underlying type using type assertions or type switches.
Try it yourself
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Read integer value
line1, _ := reader.ReadString('\n')
intVal, _ := strconv.Atoi(strings.TrimSpace(line1))
// Read string value
line2, _ := reader.ReadString('\n')
strVal := strings.TrimSpace(line2)
// Read boolean value
line3, _ := reader.ReadString('\n')
boolVal, _ := strconv.ParseBool(strings.TrimSpace(line3))
// TODO: Create boxes for each value using NewBox
// TODO: Print the description of each box using the Describe method
// Use the variables to avoid compilation errors (remove these lines when implementing)
_ = intVal
_ = strVal
_ = boolVal
// Example output format:
// fmt.Println(box.Describe())
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of Go OOP
External FilesGo Workspace & ModulesPackages & ImportsExported vs Unexported NamesIntroduction to OOP in GoStructs as ClassesDefining Methods on StructsPointer vs Value ReceiversStruct InitializationConstructor FunctionsRecap - Simple Calculator4Interfaces
Introduction to InterfacesImplicit ImplementationInterface as ContractEmpty Interface (any)Type AssertionType SwitchInterface CompositionStringer & Error InterfacesRecap - Shape Calculator7Encapsulation
Exported vs Unexported FieldsPackage-Level EncapsulationGetter & Setter MethodsInformation Hiding in GoRecap - Student Records10Generics (Go 1.18+)
Introduction to GenericsType ParametersType ConstraintsGeneric StructsGeneric Methods WorkaroundRecap - Generic Collection2Types & Structs Deep Dive
Basic & Composite TypesCustom Type DefinitionsStruct TagsAnonymous StructsNested StructsZero Values & DefaultsRecap - Contact Book5Composition Over Inheritance
Why Go Has No InheritanceStruct Embedding BasicsMethod PromotionEmbedding Multiple StructsEmbedding vs AggregationShadowing Embedded MethodsRecap - Employee Hierarchy8Error Handling & OOP
The error InterfaceCustom Error TypesError Wrapping (fmt.Errorf)Sentinel Errorserrors.Is() and errors.As()Panic, Defer, and RecoverRecap - File Parser3Pointers & Memory
Pointer Basics in GoPointers to StructsPass by Value vs ReferenceThe new() FunctionGarbage Collection in GoRecap - Linked List Builder6Polymorphism in Go
Polymorphism via InterfacesDuck Typing in GoInterface Satisfaction RulesPolymorphic CollectionsDependency InjectionRecap - Payment Processor9Concurrency & OOP
Goroutines BasicsChannels & CommunicationBuffered vs Unbuffered ChanSelect Statementsync.Mutex & sync.RWMutexsync.WaitGroupThread-Safe Struct DesignRecap - Worker Pool