This function intSeq returns another function, which we define anonymously in the body of intSeq. The returned function closes over the variable i to form a closure.
func intSeq() func() int {
i := 0
return func() int {
i++
return i
}
}
func main() {
nextInt := intSeq()
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
newInts := intSeq()
fmt.Println(newInts())
}
$ go run closures.go
1
2
3
1
An interface is two things: it is a set of methods, but it's also a type.
The Animal
type will be an interface, and we'll define an Animal as being anything that can speak. This is a core concept in Go’s type system; instead of designing our abstractions in terms of what kind of data our types can hold, we design our abstractions in terms of what actions our types can execute.
type Animal interface {
Speak() string
}
The interface{}
type
The interface{} type is the interface that has no methods. All types satisfy the empty interface. If you write a function that takes an interface{}
value as a parameter, you can apply that function with any value.
func DoSomething(v interface{}) {
// ...
}
A interface value is constructed of two words of data; one word is used to point to a method table for the value's underlying type, and the other word is used to point to the actual data being held by that value.
func PrintAll(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}
}
func main() {
names := []string{"stanley", "david", "oscar"}
PrintAll(names)
}
// cannot use names (type []string) as type []interface {} in argument to PrintAll
We would have to convert the []string
to an []interface{}
func main() {
names := []string{"stanley", "david", "oscar"}
vals := make([]interface{}, len(names))
for i, v := range names {
vals[i] = v
}
PrintAll(vals)
}
stanley
david
oscar
Pointers and interfaces
Another subtlety of interfaces is that an interface definition does not prescribe whether an implementor should implement the interface using a pointer receiver or a value receiver.