Functions in Go
Functions are the building blocks of Go programs. They encapsulate code that performs a specific task, allowing you to organize and reuse your code effectively.
Function Declaration#
A function in Go is declared using the func keyword:
func functionName(parameter1 type1, parameter2 type2) returnType {string">"comment">// Function bodyreturn value}
Here's a simple example:
func add(a int, b int) int {return a + b}
Calling Functions#
To use a function, you call it with appropriate arguments:
sum := add(5, 3)fmt.Println(sum) string">"comment">// Outputs: 8
Function Parameters#
Basic Parameters#
Go requires you to specify the type for each parameter:
func greet(name string, age int) {fmt.Printf(string">"Hello, %s! You are %d years old.\n", name, age)}
Grouped Parameters#
If multiple parameters have the same type, you can group them:
string">"comment">// Instead of thisfunc add(a int, b int) int {return a + b}string">"comment">// You can write thisfunc add(a, b int) int {return a + b}
Variadic Parameters#
Go supports variadic functions that can take a variable number of arguments:
func sum(numbers ...int) int {total := 0for _, num := range numbers {total += num}return total}string">"comment">// Can be called with any number of argumentsresult1 := sum(1, 2) string">"comment">// 3result2 := sum(1, 2, 3, 4, 5) string">"comment">// 15
Return Values#
Single Return Value#
A function can return a single value:
func square(n int) int {return n * n}
Multiple Return Values#
Go functions can return multiple values:
func divide(a, b float64) (float64, error) {if b == 0 {return 0, errors.New(string">"division by zero")}return a / b, nil}string">"comment">// When calling this functionresult, err := divide(10, 2)if err != nil {fmt.Println(string">"Error:", err)} else {fmt.Println(string">"Result:", result)}
Named Return Values#
You can name the return values in the function signature:
func split(sum int) (x, y int) {x = sum * 4 / 9y = sum - xreturn string">"comment">// string">"naked" return - returns named return values}
Anonymous Functions and Closures#
Anonymous Functions#
Go supports anonymous functions, which can be assigned to variables or called immediately:
string">"comment">// Assigning to a variablesquare := func(n int) int {return n * n}fmt.Println(square(5)) string">"comment">// Outputs: 25string">"comment">// Immediately invoked functionresult := func(n int) int {return n * n}(5)fmt.Println(result) string">"comment">// Outputs: 25
Closures#
A closure is a function that references variables from outside its body:
func makeCounter() func() int {count := 0return func() int {count++return count}}counter := makeCounter()fmt.Println(counter()) string">"comment">// 1fmt.Println(counter()) string">"comment">// 2fmt.Println(counter()) string">"comment">// 3
Each closure has its own copy of the variables it closes over.
Defer Statement#
The defer statement delays the execution of a function until the surrounding function returns:
func processFile(filename string) error {f, err := os.Open(filename)if err != nil {return err}string">"comment">// This will be executed when processFile returnsdefer f.Close()string">"comment">// Process the file...return nil}
Deferred functions are executed in LIFO (last-in, first-out) order.
Methods#
In Go, you can define methods on types. A method is a function with a special receiver argument:
type Rectangle struct {Width float64Height float64}string">"comment">// Method with a receiver of type Rectanglefunc (r Rectangle) Area() float64 {return r.Width * r.Height}func main() {rect := Rectangle{Width: 10, Height: 5}fmt.Println(string">"Area:", rect.Area()) string">"comment">// Outputs: Area: 50}
Complete Example#
Here's a complete example showing various function concepts:
package mainimport (string">"fmt"string">"errors")string">"comment">// Basic functionfunc add(a, b int) int {return a + b}string">"comment">// Multiple return valuesfunc divide(a, b float64) (float64, error) {if b == 0 {return 0, errors.New(string">"division by zero")}return a / b, nil}string">"comment">// Named return valuesfunc calculate(x, y int) (sum, difference int) {sum = x + ydifference = x - yreturn}string">"comment">// Variadic functionfunc sum(nums ...int) int {total := 0for _, num := range nums {total += num}return total}string">"comment">// Closure that creates a counterfunc makeCounter() func() int {count := 0return func() int {count++return count}}func main() {string">"comment">// Using the basic functionfmt.Println(string">"5 + 3 =", add(5, 3))string">"comment">// Using multiple return valuesresult, err := divide(10, 2)if err != nil {fmt.Println(string">"Error:", err)} else {fmt.Println(string">"10 / 2 =", result)}string">"comment">// Using named return valuessum, diff := calculate(8, 3)fmt.Println(string">"8 + 3 =", sum)fmt.Println(string">"8 - 3 =", diff)string">"comment">// Using the variadic functionfmt.Println(string">"Sum of 1, 2, 3, 4 =", sum(1, 2, 3, 4))string">"comment">// Using a closurecounter := makeCounter()fmt.Println(string">"Count:", counter())fmt.Println(string">"Count:", counter())fmt.Println(string">"Count:", counter())}
Exercise#
- Write a function that takes a slice of integers and returns their average
- Create a function that returns both the minimum and maximum values from a slice
- Implement a simple calculator with functions for add, subtract, multiply, and divide
- Write a function that generates a closure to create a sequence of numbers
In the next module, we'll explore Go's data structures in more detail, starting with arrays and slices.