Beginner · Control flow and functions · topic 9 of 46 · 35 min
Variadic functions, function values and closures
Explanation
Variadic functions: any number of arguments
Sometimes you do not know how many values the caller will pass: total of 2 prices or of 20. Put ... before the type of the last parameter. Inside the function it is a slice of that type.
func total(prices ...int) int {
sum := 0
for _, p := range prices {
sum += p
}
return sum
}
func main() {
fmt.Println(total()) // 0
fmt.Println(total(40, 25)) // 65
cart := []int{120, 80, 300}
fmt.Println(total(cart...)) // 500: spread a slice with ...
}Functions are values
In Go a function can be stored in a variable, passed to another function and returned from one, just like an int. Its type is written like func(int) int: a function that takes an int and returns an int.
func apply(nums []int, f func(int) int) []int {
out := make([]int, 0, len(nums))
for _, n := range nums {
out = append(out, f(n))
}
return out
}
func double(n int) int { return n * 2 }
func main() {
fmt.Println(apply([]int{1, 2, 3}, double)) // [2 4 6]
fmt.Println(apply([]int{1, 2, 3}, func(n int) int {
return n * n
})) // [1 4 9]
}Closures: functions that remember
A closure is a function value that uses variables from outside its own body. It keeps those variables alive, even after the outer function has returned. Each closure created gets its own set of remembered variables.
func tokenCounter(prefix string) func() string {
n := 0
return func() string {
n++
return fmt.Sprintf("%s-%03d", prefix, n)
}
}
func main() {
next := tokenCounter("OPD")
fmt.Println(next()) // OPD-001
fmt.Println(next()) // OPD-002
other := tokenCounter("LAB")
fmt.Println(other()) // LAB-001
fmt.Println(next()) // OPD-003
}Where you will see these
- sort.Slice and slices.SortFunc take a function that compares two items.
- HTTP handlers are functions with the type func(http.ResponseWriter, *http.Request) (module 7).
- Middleware returns a new handler that wraps another one, which is a closure (module 8).
- go func() { ... }() starts an anonymous function as a goroutine (module 6).
people := []string{"Ravi", "Asha", "Zoya", "Bala"}
sort.Slice(people, func(i, j int) bool {
return people[i] < people[j]
})
fmt.Println(people) // [Asha Bala Ravi Zoya]Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Variadic functions, function values and closures · 1/7
Let us look at three powerful function ideas: variadic functions, function values and closures.
Prefer a video by a teacher? Find free videos on “golang closures anonymous functions variadic functions” on YouTube ↗
In real life: Discount rules for a sale
An online store runs different discount rules during a festival sale. Each rule is a function value, so the store can switch rules from config without changing the checkout code. A closure builds "flat X percent off" rules for any percentage.
package main
import "fmt"
func percentOff(p int) func(int) int {
return func(price int) int {
return price - price*p/100
}
}
func main() {
rules := map[string]func(int) int{
"diwali": percentOff(20),
"regular": percentOff(5),
}
price := 1500
fmt.Println(rules["diwali"](price)) // 1200
fmt.Println(rules["regular"](price)) // 1425
}Practice (0/4 done)
func count(xs ...string) int { return len(xs) }. What is count("a", "b", "c")?
What does this print? func counter() func() int { c := 0 return func() int { c++; return c } } ... a := counter() a() a() b := counter() fmt.Println(a(), b())
nums := []int{1, 2}. Which call to func sum(xs ...int) int compiles?
Write func makeMultiplier(m int) func(int) int and use it to make triple and tenTimes. Then write func filter(nums []int, keep func(int) bool) []int and use it to keep only even numbers.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- defer: clean up at the endControl flow and functions · same module
- Loops: for is the only loopControl flow and functions · same module
- ClosuresRust Programming · Closures, iterators and smart pointers
- Scope, hoisting and closuresFrontend Web Development · JavaScript in depth
- Scope and closuresJavaScript Programming (language in depth) · Functions and closures
- FunctionsFlutter and Dart · Dart basics
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Inside func f(names ...string), what is the type of names?
Answer: []string
A variadic parameter is a slice inside the function.
What is a closure?
Answer: A function value that remembers variables from where it was created
A closure captures and keeps alive the outer variables it uses.
Which is a valid function type for "takes two ints and returns a bool"?
Answer: func(int, int) bool
Function types are written func(params) results.
Can a function have two variadic parameters?
Answer: No, only the last parameter can be variadic
Only the final parameter may use ...
A function calls its closure parameter many times, and the closure may change its captured state. Which bound fits?Related
What is a closure?Related
Answer: A function together with the outer variables it remembers
A closure is a function plus the variables from where it was created, which stay alive as long as the function does.
What is a closure?Related
Answer: A function plus the variables from where it was created that it remembers
Closures keep access to the variables of the scope where the function was defined.
From Scope and closures
What is a closure?Related
Answer: A function that remembers variables from where it was created
Closures capture their surroundings.
From Functions
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “Control flow and functions” before its exam: defer: clean up at the end.
- Module 2 exam: Control flow and functions · 13 questions · 20 min, without help. 5 topics of this module still to finish first.
- Then the next module, Collections and structs. 46 topics left in the course before the final exam.