Let’s start with a simple example, addition, subtraction, multiplication and division.

var add = func(a, b int) int { return a + b }
var multiply = func(a, b int) int { return a * b }
var result = multiply(add(1.2), add(3.4))
Copy the code

This is a simple function, and I’m going to use a mathematical example in order to change it to a functional form later on, so far, this is a very simple function, and I’m going to rewrite it as a functional form later on. Consider that Go does not support functions very well, and because it is generic, it is prone to evil forms, such as funcForString(string) and funcForInt(int). Here are some common ones.

Functions are first-class citizens

When we say functions, the first thing we mean is that functions can be created, assigned, and modified just like variables. You can assign a function to any object. Here’s a simple example:

var hello = func(name string) string { return "hello " + name }
Copy the code

When you call it, you just add () to it like a normal function. If hello is a function variable, hello() will execute the function inside, i.e. :

hello        // func(name string) string { return "hello " + name }
hello("tim") // "hello tim"
Copy the code

This hello is the same thing as

func hello(name string) string {
  return "hello " + name
}
Copy the code

So why write it like this? Let’s take a look at an HTTP service written in Go that uses the Ginex framework. We don’t need to understand the internals, just that it creates an HTTP server

server := ginex.Default()
server.Get("/api/index".func (ctx *gin.Context) {
  doSomething(ctx)
})
Copy the code

The correct way to write it, you can understand his brevity at once.

server.Get("/api/index", doSomething)
Copy the code

Pure functions

Let’s take an example. What is an impure function

var v = 20
func check(n int) bool {
  return n >= v
}
Copy the code

This code is very simple. It just passes in an argument n and tells you whether n is greater than 20. However, since the v is outside the function, any code can change it, and if you accidentally change the variable in another place, the return value of the function may change, which is unacceptable in some cases. So what’s the right thing to do?

func check(n int) bool {
  var v = 20
  return n >= v
}
Copy the code

You might laugh at this, but isn’t it just a variable that you need to be careful about? On the contrary, this is just a simple example. When you have multiple impure functions in your code, you start to wonder what this variable is actually used for. You need to be careful not to change it, which is not the case with pure functions. It also reduces the burden of reading this function, doesn’t make you think too much about external variables, and when the system gets bigger, you’ll come back and thank yourself for the specification. In addition, a mathematical function is essentially the same input and returns the same value, and if that property is satisfied, then the function is very stable. If you can, make your code a pure function.

Currie,

As usual, let’s start with a simple piece of code

var add = func(x, y int) int { return x + y }

var increment = func(x int) int { return add(1, x) }
var addTen = func(x int) int { return add(10, x) }

increment(3) / / 4
addTen(5)    / / 15
Copy the code

Before we had a function, we usually constructed some functions like this, but after we introduced a function, we had a better way, which is as follows

var add = func(x int) func(int) int {
  return func(y int) int {
    return a + b
  }
}

var increment = add(1)
var addTen = add(10)

increment(3) / / 4
addTen(5)    / / 15
add(4) (5)    / / 9
Copy the code

As you can see, this code is much cleaner, removing a bunch of unnecessary func(int) ints and using things like add(1) instead, which also improves readability. In addition, we can find an infinitive: pass in an argument and return a function.

combination

So what is a combination

type F func(string) string // go1There were no generics before.18, so I'll use them herestringFor example
var compose = func(f, g F) F {
  return func(x) {
    return f(g(x))
  }
}
Copy the code

This code is easy to understand. It executes functions from right to left. Here is a practical example:

var toUpper = strings.ToUpper
var exclaim = func(x string) string { return x + "!" }
var shout = compose(toUpper, exclaim)

shout("hello world") // HELLO WORLD!
Copy the code

For example, with the compose function, you can easily compose various functions, and if you don’t use the functional idea, then your code will look something like this, which looks a lot more unnecessary

var shout = function(x string) string {
  return toUpper(exclaim(x));
};
Copy the code

conclusion

By now, you should know how to use functional programming ideas in your Go code, but be aware that functional programming is not everything, and there will be times when you will need imperative programming, so just use it without too much hassle.