package main import ( "fmt" "math" "reflect" ) func compute(fn func(float64, float64) float64) float64 { return fn(2, 7) } func incrementer() func() int { // returns a function -that requires and returns an int value- curVal := 0 return func() int { curVal += 1 return curVal } } func incrementWithNum() func(int) int { // returns a function -that requires and returns an int value- curVal := 0 return func(i int) int { curVal += i return curVal } } func adder(a int) func(int) int { // gets first value with adder(int), returns a function -that requires and returns an int value- return func(b int) int { return a + b } } func main() { fmt.Println("Includes function values, closures and other function related subject, if you want to see functions basics, go to 0basics/basics.go > Section \"Functions\"") fmt.Println("Functions are values too, They can be passed around just like other values") sum := func(x, y float64) float64 { return float64(x + y) } fmt.Println(sum(2, 3)) fmt.Println(sum) fmt.Println(&sum) fmt.Println(reflect.TypeOf(sum)) fmt.Println(reflect.TypeOf(sum).Kind()) fmt.Printf("\n\n") fmt.Println("Function values may be used as function arguments and return values") fmt.Println(compute(sum)) fmt.Println(compute(math.Pow)) fmt.Printf("%p\n", compute) fmt.Println(reflect.TypeOf(compute)) fmt.Println(reflect.TypeOf(compute).Kind()) fmt.Printf("\ncompute a function that gets a function as an argument (that gets two float64 values and returns float64) and returns float64\n\n\n") fmt.Println("Go functions may be closures") fmt.Println("With this feature inner functions can read outer functions values, use them. Also with assigning it to a variable we can use same function from scratch") fmt.Println("A bit confusing but just see the examples:") // SECTION incrementer() newInc1 := incrementer() fmt.Println(newInc1()) fmt.Println(newInc1()) fmt.Println(newInc1()) fmt.Printf("\n") newInc1 = incrementer() // you can initialize again fmt.Println(newInc1()) newInc2 := incrementer() newInc2() newInc2() newInc2() newInc2() newInc2() fmt.Println(newInc2()) fmt.Println(newInc1()) fmt.Printf("\n\n") // !SECTION // SECTION incrementWithNum() numInc1 := incrementWithNum() // fmt.Println(numInc1()) // ERROR, not enough arguments in call to numInc1 fmt.Println(numInc1(4)) // Increments curVal by 4 and print out fmt.Println(numInc1(3)) // Increments curVal by 3 and print out fmt.Println(numInc1(2)) // "" 2 "" fmt.Println(numInc1(1)) // "" 1 "" fmt.Printf("\n\n") // !SECTION // SECTION adder() myAdder1 := adder(5) fmt.Println(myAdder1(1)) // 5+1=6 fmt.Println(myAdder1(8)) // 5+8=13 myAdder2 := adder(8) fmt.Println(myAdder2(myAdder1(3))) // 8 + (5+3) }