Go - Anonymous function



In Go, the anonymous functions (also known as lambda functions or function literals) are functions that are defined without a name. We can use them when you want to define a function inline without declaring it individual.

Go's anonymous functions allow you to define temporary, one-time-use functions exactly where you want them - without giving them a name. They are like quick shortcuts for little tasks that don't require full-function declarations. They are ideal for:

  • Executing code on the spot
  • Satisfying variable usage from surrounding code
  • Scheduling fast jobs in goroutines
  • Sweeping up with defer statements

These convenient little functions keep your code organized and versatile, when you must pass little pieces of logic around. Easy to use but robust enough for tough challenges, they are a go-to tool for Go developers.

Syntax

Following is the syntax for the Anonymous function in Golang −

func(parameters) return_type {
    // function body
}

Assigning to Variables

This illustrates how to put anonymous functions into variables. You can define a function without a name and put it into a variable such as greet or add. Then you can use it later just like any other function.

In this program, we use anonymous functions (functions without names) to print "Tutorialspoint" and add two numbers (9 + 5), printing the result (14). It shows how to declare and call inline functions.

package main
import "fmt"
func main() {
   greet := func() {
      fmt.Println("Tutorialspoint")
   }
   greet() // Call the anonymous function

   // With parameters and return value
   add := func(a, b int) int {
      return a + b
   }
   sum := add(9, 5)
   fmt.Println("Sum =", sum)
}

Following is the output to the above program −

Tutorialspoint
Sum = 14

Invoked Function Expressions

This demonstrates how to create and run anonymous functions immediately. The function is defined and called right away in one step - you will see the parentheses () right after the function body that make it run immediately.

This Go program uses immediately invoked anonymous functions to print a message, multiply two numbers (6×4=24), and greet a user ("Revathi"). The functions run instantly when defined.

package main
import "fmt"
func main() {
   // Without parameters
   func() {
      fmt.Println("Executed immediately!")
   }()
   
   // With parameters and return value
   result := func(a, b int) int {
      return a * b
   }(6, 4)
   fmt.Println("Result:", result)
   
   // With multiple statements
   func(name string) {
      fmt.Printf("Hello, %s!\n", name)
      fmt.Println("Welcome to Go!")
   }("Revathi")
}

Following is the output to the above program −

Executed immediately!
Result: 24
Hello, Revathi!
Welcome to Go!

Closures and Variable Capturing

Anonymous functions can access variables from their enclosing scope, creating closures:

In this program, we demonstrate two important closure examples: counter() maintains and increments its internal count state, and multiplier() remembers the factor value between calls.

package main
import "fmt"
func main() {
   c := counter()
   fmt.Println(c()) // 1
   fmt.Println(c()) // 2
   fmt.Println(c()) // 3
   
   double := multiplier(2)
   triple := multiplier(3)
   fmt.Println(double(6)) 
   fmt.Println(triple(6)) 
}  
func counter() func() int {
   count := 0
   return func() int {
      count++
      return count
   }
}
func multiplier(factor int) func(int) int {
   return func(x int) int {
      return x * factor
   }
}

Following is the output to the above program −

1
2
3
12
18

Passing Anonymous Functions as Arguments

This demonstrates how anonymous functions can be used as parameters to other functions.

To Higher-Order Functions

The transform function accepts a list of numbers and an operation to execute on each number.

In this program, we use a 'transform' function to square each number in [2,4,6] by passing an anonymous function (x*x), then prints the result [4,16,36]. It demonstrates how functions can accept and execute other functions in Go.

package main
import "fmt"
func main() {
   squares := transform([]int{2, 4, 6}, func(x int) int {
      return x * x
   })
   fmt.Println(squares) 
}

func transform(numbers []int, op func(int) int) []int {
   result := make([]int, len(numbers))
   for i, v := range numbers {
      result[i] = op(v)
   }
   return result
}

Following is the output to the above program −

[4 16 36]

As Callbacks

The fetchData function accepts a callback function to process the results.

In this program, we demostrate how to make asynchronous HTTP requests using callback functions. The fetchData function takes a URL and a callback that handles either the response data (as bytes) is successful or error if it fails.

package main
import (
   "fmt"
   "io"
   "net/http"
)
func main() {
   fetchData("https://example.com", func(data []byte, err error) {
      if err != nil {
         fmt.Println("Error:", err)
         return
      }  
      fmt.Println("Data length:", len(data))
   })
   // Wait for async operation
   fmt.Scanln()
}
func fetchData(url string, callback func([]byte, error)) {
   go func() {
      resp, err := http.Get(url)
      if err != nil {
         callback(nil, err)
         return
      }
      defer resp.Body.Close()
      data, err := io.ReadAll(resp.Body)
      callback(data, err)
   }()
}

The output of this program will depend on whether the HTTP request succeeds or fails:

If the request succeeds, the output will be

Data length: 1256

The actual number will vary - this is the size of example.com's HTML response.

If the request fails (no internet connection or other error), the output will be

d /home/cg/root/67e51fd62d11b
bash: d: command not found

Recursive Anonymous Functions

This demonstrates how an anonymous function can be called again and again by itself. It is a function that keeps repeating itself until some point is reached.

Here, the function repeatedly calls itself with decreasing values (n-1) until reaching the base case (n <= 1), forming a loop using recursion.

package main
import "fmt"
func main() {
   var factorial func(int) int
   factorial = func(n int) int {
      if n <= 1 {
         return 1
      }
      return n * factorial(n-1)
   }
   fmt.Println(factorial(5))
}

Following is the output to the above program −

120

Struct Fields with Function Types

Structs in Go can hold functions as fields, allowing each instance to have different behavior.

In this program, the processor struct has two function fields - transform for converting strings and validate for validations. You can pass various anonymous functions to these fields while creating instances so that each processor will behave differently but have the same interface.

package main
import (
   "fmt"
   "strings"
)
func main() {
   p := Processor{
      transform: func(s string) string { return strings.ToUpper(s) },
      validate:  func(s string) bool { return len(s) > 0 },
   }
   fmt.Println(p.transform("hello")) 
   fmt.Println(p.validate(""))      
}
type Processor struct {
   transform func(string) string
   validate  func(string) bool
}

Following is the output to the above program −

HELLO
false
Advertisements