- Zero Initialization
- Generic Data Structures
- Specialized Generic Data Structures
- Implementation Hiding
- Type Composition
Generic Data Structures
5 next*stackEntry 6 value interface {} 7 } 8 9 type stack struct { 10 top*stackEntry 11 } 12 13 func (s*stack) Push(vinterface{}) { 14 var e stackEntry 15 e.value = v 16 e.next = s.top 17 s.top = &e 18 } 19 func (s*stack) Pop()interface{} { 20 if nil == s.top { 21 return nil 22 } 23 v := s.top.value 24 s.top = s.top.next 25 return v 26 }
From: genericStack.go
The empty interface typeis a very important part of the Go type system. This has a similar, although slightly more generic, place to void* in C: It can represent any type.
It is common to use the empty interface type in generic data structures. If you can store values of the generic interface type, then you can store values of any type. You can’t, however, perform any operations on them.
It is common to use the empty interface type in generic data structures. If you can store values of the generic interface type, then you can store values of any type. You can’t, however, perform any operations on them.
If you want to create something like a set, then you must define a mechanism for defining equality, which typically involves defining an interface with an isEqual() method or similar. If you are creating a data structure that doesn’t need to be aware of the representation or semantics of the values that it contains, then you should use the empty interface.
The example at the start of this section shows a generic stack type, with Push() and Pop() methods, capable of storing any Go type. The implementation is very simple: a singly-linked list of a private structure type that stores a value.
You can use the same technique when creating far more complex data structures. The advantage of using the empty interface type is that it allows both structure and primitive types to be stored. In the next section, we’ll look at how you can extend this general approach and specialize it for specific types.