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 body
return 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 this
func add(a int, b int) int {
return a + b
}
string">"comment">// You can write this
func 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 := 0
for _, num := range numbers {
total += num
}
return total
}
string">"comment">// Can be called with any number of arguments
result1 := sum(1, 2) string">"comment">// 3
result2 := 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 function
result, 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 / 9
y = sum - x
return 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 variable
square := func(n int) int {
return n * n
}
fmt.Println(square(5)) string">"comment">// Outputs: 25
string">"comment">// Immediately invoked function
result := 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 := 0
return func() int {
count++
return count
}
}
counter := makeCounter()
fmt.Println(counter()) string">"comment">// 1
fmt.Println(counter()) string">"comment">// 2
fmt.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 returns
defer 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 float64
Height float64
}
string">"comment">// Method with a receiver of type Rectangle
func (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 main
import (
string">"fmt"
string">"errors"
)
string">"comment">// Basic function
func add(a, b int) int {
return a + b
}
string">"comment">// Multiple return 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">// Named return values
func calculate(x, y int) (sum, difference int) {
sum = x + y
difference = x - y
return
}
string">"comment">// Variadic function
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
string">"comment">// Closure that creates a counter
func makeCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
string">"comment">// Using the basic function
fmt.Println(string">"5 + 3 =", add(5, 3))
string">"comment">// Using multiple return values
result, err := divide(10, 2)
if err != nil {
fmt.Println(string">"Error:", err)
} else {
fmt.Println(string">"10 / 2 =", result)
}
string">"comment">// Using named return values
sum, diff := calculate(8, 3)
fmt.Println(string">"8 + 3 =", sum)
fmt.Println(string">"8 - 3 =", diff)
string">"comment">// Using the variadic function
fmt.Println(string">"Sum of 1, 2, 3, 4 =", sum(1, 2, 3, 4))
string">"comment">// Using a closure
counter := 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.