Closures in Go ============== :: package main import ( "fmt" ) //////////////////////////////////////////////////////////// // Go uses escape analysis to determine that the local variable result should // not be declared on the stack. func twice(s string) *string { result := s + s // result is a local variable return &result // return a pointer to the result } func test1() { fmt.Println(*twice("apple")) fmt.Println(*twice("down")) } //////////////////////////////////////////////////////////// // In Go, functions can returned functions. You can also pass functions as // parameters to functions. func makeGreeter1() func() { return func() { fmt.Println("Hello!") } } func test2() { greet := makeGreeter1() greet() greet() } //////////////////////////////////////////////////////////// func makeGreeter2(s string) func() { return func() { fmt.Println(s) } } func test3() { greet := makeGreeter2("Hi!") greet() greet() } //////////////////////////////////////////////////////////// func makeGreeter3() func(string) { return func(s string) { fmt.Println(s + "!") } } func test4() { greet := makeGreeter3() greet("Hey") greet("Hi") } //////////////////////////////////////////////////////////// // makeAdder1 returns a closure, i.e. a special value that contains a function // *and* references to the free variables that are in the function. A closure // can be called just like a function. func makeAdder1() func() int { total := 0 // local variable inc := func() int { total++ return total } return inc } func test5() { next := makeAdder1() fmt.Println(next()) fmt.Println(next()) fmt.Println(next()) } //////////////////////////////////////////////////////////// // This example shows that two closures can share the same variable. func makeAdder2() (func() int, func() int) { total := 0 // local variable inc := func() int { total++ return total } dec := func() int { total-- return total } return inc, dec } func test6() { next, prev := makeAdder2() fmt.Println(next()) fmt.Println(prev()) fmt.Println(next()) } //////////////////////////////////////////////////////////// func makeAdder3() (func() int, func() int, func()) { total := 0 // local variable inc := func() int { total++ return total } dec := func() int { total-- return total } reset := func() { total = 0 } return inc, dec, reset } func test7() { next, prev, reset := makeAdder3() fmt.Println(next()) fmt.Println(prev()) fmt.Println(next()) reset() fmt.Println(next()) fmt.Println(prev()) fmt.Println(next()) } //////////////////////////////////////////////////////////// // Closures are quite powerful, and could, for instance, be used to implemente // a kind of object-oriented programming. func makePerson(initName string, initAge int) (func(string), func() string, func(int), func() int) { name := initName age := initAge setName := func(s string) { if len(s) > 0 { name = s } } getName := func() string { return name } setAge := func(n int) { if n > 0 { age = n } } getAge := func() int { return age } return setName, getName, setAge, getAge } func test8() { setName, getName, setAge, getAge := makePerson("May", 11) fmt.Printf("%v, %v\n", getName(), getAge()) setName("Irene") setAge(getAge() + 1) fmt.Printf("%v, %v\n", getName(), getAge()) } //////////////////////////////////////////////////////////// func main() { // test1() // test2() // test3() // test4() // test5() // test6() // test7() test8() }