Closures

Define the Person struct


type Person struct {
	FirstName string
	LastName  string
	Age       int
}

  • initialize a slice of 3 people
  • Sort by age, then last name
  • People is captured by the anonymous function closure,

people := []Person{
	{"Pat", "Patterson", 16},
	{"Amy", "Bobbart", 19},
	{"Bob", "Bobbart", 18},
}

sort.Slice(people, func(i int, j int) bool {
		return people[i].Age < people[j].Age
})

sort.Slice(people, func(i int, j int) bool {
		return people[i].LastName < people[j].LastName
})
fmt.Println(people)
[{Bob Bobbart 18} {Amy Bobbart 19} {Pat Patterson 16}]

Defining a closure type


// Returns a function that multiplies by the given factor
type twoFactor func(factor int) int


func makeMult(base int) twoFactor {
	return func(factor int) int {
		return base *factor
	}
}


twoBase := makeMult(2)
threeBase := makeMult(3)
fourBase := makeMult(4)
for i := 0; i < 10; i++ {
	fmt.Println(twoBase(i), threeBase(i), fourBase(i))
}
0 0 0
2 3 4
4 6 8
6 9 12
8 12 16
10 15 20
12 18 24
14 21 28
16 24 32
18 27 36

Remind caller to do something with a closure e.g. close a file, as it's returned to caller and Go doesn't allow unused values, they know that they should do something with it


func getFile(name string) (*os.File, func(), error) {
	file, err := os.Open(name)
	if err != nil {
		return nil, nil, err
	}
	return file, func() {
		file.Close()
	}, err
}


_, closer, err := getFile("./out.txt")
if err != nil {
	log.Fatal(err)
}
defer closer()
2 3 4
4 6 8
6 9 12
8 12 16
10 15 20
12 18 24
14 21 28
16 24 32
18 27 36
gobook-output-start
2021/08/18 10:27:47 open ./out.txt: no such file or directory
exit status 1