# Functions

We've already seen various functions at this point, beginning with the `main` function. But on this page we will explore various functions including simple functions, functions that return multiple values, anonymous (no-name) functions, variadic functions, and closures.

#### 1. Simple Functions

Functions can be assigned to variables, passed as arguments to functions or returned from functions. This makes the language more flexible. A function declaration begins with the `func` keyword. The body is wrapped around curly brackets `{}` and the function can have parameters or chose to omit them.

In the example below, we will define a simple function that solves a quadratic equation using the quadratic formula:

$$
x =  \frac{-b\pm\sqrt{b^2 - 4ac}}{2a}
$$

{% code lineNumbers="true" %}

```go
package main

import (
  "fmt"
  "math"
)

// define a function called solve_quadratic that takes three float values
// and returns a float as the answer
func solve_quadratic(a float64, b float64, c float64) float64 {
  bb := b * b
  quotient := (-1 * b) + math.Sqrt((bb - (4 * a * c)))
  divisor := 2 * a
  ans := quotient / divisor
  return ans
}

func main() {
  a := 1.0
  b := -3.0
  c := -4.0
  // call the solve_quadratic function with some values
  ans1 := solve_quadratic(a, b, c)
  fmt.Println("Ans: ", ans1)
  
  // call the function again with different values
  ans2 := solve_quadratic(-10.5, 3.99, -8.475)
}

```

{% endcode %}

{% hint style="info" %}
The solution above only returns one answer, even though the quadratic formula should return two answers. We will see how to return multiple values next.
{% endhint %}

#### 2. Functions that return multiple values

The example above only returned one value. However, we can modify the function to return two (or more values) as follows

{% code lineNumbers="true" %}

```go
package main

import "math"

// set the return type of the values
func solve_quadratic(a, b, c float64) (float64, float64) {
  bb := b * b
  q1 := (-1 * b) + math.Sqrt((bb - (4 * a * c)))
  q2 := (-1 * b) - math.Sqrt((bb - (4 * a * c)))
  divisor := 2 * a
  x1 := q1 / divisor
  x2 := q2 / divisor
  // return both x1 and x2
  return x1, x2
}

func main() {
  // we can later call the function as follows
  a, b := solve_quadratic(1.0, -3.0, -4.0)
  // if we are only interested in one value, we can use the underscore
  // to ignore the other. For exmaple
  _, b := solve_quadratic(2.0, -3.5, 5.0)
}
  
```

{% endcode %}

#### 3. Anonymous Functions

Anonymous functions do not have a name. They can be useful if/when we need to apply a function to some values, but we don't necessarily want to write out a named function for the task. Here is an example:

{% code lineNumbers="true" %}

```go
package main

import "fmt"

func main() {
  mul := func(a, b, c int) int {
    return a * b * c
  }(19, 11, 7)
  fmt.Println("19 * 11 * 7 = ", mul)
  // prints: 19 * 11 * 7 = 1463
}
```

{% endcode %}

#### 4. Variadic functions

A variadic function is one that can be called with any number of parameters. The function also accepts an arbitrary number of arguments. We've already seen a function of this type, the `fmt.Println()` function, which can take an arbitrary number of arguments. Here is how we can define our own in golang

{% code overflow="wrap" lineNumbers="true" %}

```go
package main

import "fmt"

// adds all the numbers passed as parameters and returns a total
func adder(nums ...int) int {
  fmt.Print(nums, " ")
  sum := 0
  for _, num := range nums {
    sum += num
  }
  return sum
}

func main() {
 fmt.Println(adder(1, 2, 3, 4))     // prints: 10
 fmt.Println(adder(99, 13))         // prints: 112
 scores := []int{4, 5, 19, 6, 2, 11}
 fmt.Println(adder(scores...))      // prints: 47
}
 
```

{% endcode %}

If you already have multiple args in a slice (as in the case of line 18 above), we can apply them to a variadic function using `func(slice...)` . We will cover slices in detail in the [Slices](https://golang.collingrimm.com/data-structures/slices) section

#### 5. Closure

The last thing related to functions we would look at is closures. A closure is a concept in programming languages where a function returns another function. In other words, a closure gives you access to an outer function's scope (lexicological environment) from an inner function. (See this [Wikipedia article ](https://en.wikipedia.org/wiki/Closure_\(computer_programming\))to get an in-depth definition of closures). Here is how golang closures work:

{% code title="closure\_function.go" lineNumbers="true" %}

```go
package main

import "fmt"

// a simple program that takes a seed, and increments the seed
// number by one every time the closure function is called
func incrementor(init int) func() int {
  i := init
  return func() int {
    i++
    return i
  }
}

func main() {
  randSequence := incrementor(23)
  fmt.Println(randSequence())
  fmt.Println(randSequence())
  fmt.Println(randSequence())
  
  anotherSequence := incrementor(2412)
  fmt.Println(randSequence())
  fmt.Println(randSequence())
}
```

{% endcode %}

```shell-session
$ go run closure_function.go
24
25
26
2413
2414
```

Functions in golang are very flexible and allow for extensibility as shown above. In golang, we can define our own type for a function, pass functions as arguments into other functions, and return functions as closures. This level of flexibility in functions is known as first-class functions. To learn more about first-class functions and further ideas in golang, see: <https://golangbot.com/first-class-functions/>
