Closures

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

Interfaces

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.