First class functions in Go

前端 未结 5 1512
鱼传尺愫
鱼传尺愫 2021-01-30 08:49

I come from JavaScript which has first class function support. For example you can:

  • pass a function as a parameter to another function
  • return a function f
5条回答
  •  旧巷少年郎
    2021-01-30 09:08

    The related section from the specification: Function types.

    All other answers here first declare a new type, which is good (practice) and makes your code easier to read, but know that this is not a requirement.

    You can work with function values without declaring a new type for them, as seen in the below example.

    Declaring a variable of function type which has 2 parameters of type float64 and has one return value of type float64 looks like this:

    // Create a var of the mentioned function type:
    var f func(float64, float64) float64
    

    Let's write a function which returns an adder function. This adder function should take 2 parameters of type float64 and should returns the sum of those 2 numbers when called:

    func CreateAdder() func(float64, float64) float64 {
        return func(x, y float64) float64 {
            return x + y
        }
    }
    

    Let's write a function which has 3 parameters, first 2 being of type float64, and the 3rd being a function value, a function that takes 2 input parameters of type float64 and produces a value of float64 type. And the function we're writing will call the function value that is passed to it as parameter, and using the first 2 float64 values as arguments for the function value, and returns the result that the passed function value returns:

    func Execute(a, b float64, op func(float64, float64) float64) float64 {
        return op(a, b)
    }
    

    Let's see our previous examples in action:

    var adder func(float64, float64) float64 = CreateAdder()
    result := Execute(1.5, 2.5, adder)
    fmt.Println(result) // Prints 4
    

    Note that of course you can use the Short variable declaration when creating adder:

    adder := CreateAdder() // adder is of type: func(float64, float64) float64
    

    Try these examples on the Go Playground.

    Using an existing function

    Of course if you already have a function declared in a package with the same function type, you can use that too.

    For example the math.Mod() has the same function type:

    func Mod(x, y float64) float64
    

    So you can pass this value to our Execute() function:

    fmt.Println(Execute(12, 10, math.Mod)) // Prints 2
    

    Prints 2 because 12 mod 10 = 2. Note that the name of an existing function acts as a function value.

    Try it on the Go Playground.

    Note:

    Note that the parameter names are not part of the type, the type of 2 functions having the same parameter and result types is identical regardless of the names of the parameters. But know that within a list of parameters or results, the names must either all be present or all be absent.

    So for example you can also write:

    func CreateAdder() func(P float64, Q float64) float64 {
        return func(x, y float64) float64 {
            return x + y
        }
    }
    

    Or:

    var adder func(x1, x2 float64) float64 = CreateAdder()
    

提交回复
热议问题