Advanced usage of Golang language functions

Posted by ziola on Tue, 30 Nov 2021 02:54:30 +0100

01 introduction

In the Golang language, in addition to the main and init functions, other functions can also receive one or more parameters, and the Golang function can receive variable length parameters. It should be noted that when the Golang function receives variable length parameters, the variable length parameters need to be placed at the end of all received parameters. In fact, The variable length parameter is a slice type parameter.

Functions in the Golang language can also receive multiple return values, which are usually used to return error messages.

The function of Golang language is the first citizen "first class", which allows functions to assign values to variables, pass them to other functions as parameters, or return from other functions.

In this article, we will introduce the advanced usage of functions in Golang language. We have already introduced the basic usage of functions in the previous article, and we will not repeat it in this article.

02 anonymous function

The so-called anonymous function, as its name implies, is a function without a function name defined. It is usually used for functions that only need to be used for a short time. We can also assign an anonymous function to a variable and call the anonymous function through the variable. We demonstrate the use of anonymous functions through the following example code.

Anonymous function - no parameters and return value:

func TestAnonymous(t *testing.T) {
 func () {
  t.Log("Hello World")
 }()
}

Anonymous function - with parameters and return values:

func TestAnonymous(t *testing.T) {
 func (a, b int) int {
  return a + b
 }(1,2)
}

Anonymous function - assign to variable:

func TestAnonymous(t *testing.T) {
 sum := func (a, b int) int {
  return a + b
 }
 t.Log(sum(1, 2))
}

03 closure

In Golang language, functions support anonymous functions. Closure is a special anonymous function, which can be used to access variables outside the function body.

Example code:

func TestClosures(t *testing.T) {
 x, y := 1, 2
 func (a, b int) {
  t.Log(a + b)
 }(x, y)
}

It should be noted that in for... Range... When using a coroutine to execute a closure, a "pit" often falls. Because anonymous functions can access variables outside the function body, and the value of val returned by for... Range... Is the data of the same memory address referenced, the value of val outside the function body accessed by anonymous functions will be the last value output in the loop.

Example code:

func TestClosures(t *testing.T) {
 values := []int{1,2,3,4,5}
 for _, val := range values {
  go func() {
   t.Logf("%p %d\n", &val, val)
  }()
 }
 time.Sleep(time.Second)
}

The way to avoid "pit" is to pass parameters using closure function. The example code is as follows:

func TestClosures(t *testing.T) {
 values := []int{1,2,3,4,5}
 for _, val := range values {
  go func(val int) {
   t.Logf("%p %d\n", &val, val)
  }(val)
 }
 time.Sleep(time.Second)
}

04 recursion

Recursive functions are also supported in the Golang language. It should be noted that when using closure recursion, you need to explicitly declare closures before defining closures.

Example code:

func TestRecursion(t *testing.T) {
 var fib func(n int) int
 fib = func (n int) int {
  if n < 2 {
   return n
  }
  return fib(n - 1) + fib(n -2)
 }
 t.Log(fib(7))
}

05 custom function type

In Golang language, we can also define function types just as we define structure types.

Example code:

type sum func(int, int) int

A custom function type that can be used as a parameter or return value of a higher-order function.

06 higher order function

A high-order function is a function that receives a variable whose parameter or return value is a function type, that is, a high-order function is a function that operates on other functions.

Function as an argument:

func TestHigherOrder(t *testing.T) {
 t.Log(operation(1, 2, func(x, y int) int {
  return x + y
 }))
}

func operation(x, y int, operaFuc func(int, int) int) int {
 rst := operaFuc(x, y)
 return rst
}

Function as return value:

func TestHigherOrder(t *testing.T) {
 sum := operation1()
 t.Log(sum(2, 3))
}

func operation1() func(x, y int) int {
 sum := func(x, y int) int {
  return x + y
 }
 return sum
}

07 summary

In this paper, we introduce the advanced usage of functions in Golang language, including anonymous functions, closures, recursion, custom function types and high-order functions, and list a simple example respectively. Interested readers can run the example code locally and deepen their understanding by modifying the mode code.

reference material: https://gobyexample.com/closures https://gobyexample.com/recursion https://zetcode.com/golang/function/ https://golangbot.com/first-class-functions/ https://www.golangprograms.com/go-language/functions.html https://golangbyexample.com/function-golang-complete-guide/