Functions in Go
Functions are the building blocks of any Go program. They help organize code into manageable pieces and promote code reuse.
Function Declaration
The basic syntax for declaring a function in Go is:
func functionName(parameter1 type1, parameter2 type2) returnType { // function body return value}Simple Function Example
func add(x int, y int) int { return x + y}Multiple Parameters of Same Type
func add(x, y int) int { return x + y}Multiple Return Values
Go functions can return multiple values:
func divide(x, y float64) (float64, error) { if y == 0 { return 0, errors.New("cannot divide by zero") } return x / y, nil}Named Return Values
func rectangle(width, height float64) (area, perimeter float64) { area = width * height perimeter = 2 * (width + height) return // naked return}Variadic Functions
Functions that accept a variable number of arguments:
func sum(numbers ...int) int { total := 0 for _, num := range numbers { total += num } return total}
// Usagesum(1, 2) // 3sum(1, 2, 3, 4) // 10Anonymous Functions
Functions that are declared without a name:
func main() { // Anonymous function square := func(x int) int { return x * x }
fmt.Println(square(5)) // 25}Closures
Functions that reference variables from outside their body:
func counter() func() int { count := 0 return func() int { count++ return count }}
// Usagec := counter()fmt.Println(c()) // 1fmt.Println(c()) // 2Defer Statement
Defers the execution of a function until the surrounding function returns:
func readFile(filename string) { file, err := os.Open(filename) if err != nil { return } defer file.Close() // Will be called when readFile returns
// Rest of the function}Methods
Functions associated with a type:
type Rectangle struct { width, height float64}
func (r Rectangle) Area() float64 { return r.width * r.height}
// Usagerect := Rectangle{width: 10, height: 5}fmt.Println(rect.Area()) // 50Function Types
Functions can be used as types:
type Operation func(x, y int) int
func calculate(op Operation, x, y int) int { return op(x, y)}
// Usageadd := func(x, y int) int { return x + y }multiply := func(x, y int) int { return x * y }
fmt.Println(calculate(add, 5, 3)) // 8fmt.Println(calculate(multiply, 5, 3)) // 15Error Handling
Functions often return an error as the last return value:
func divide(x, y float64) (float64, error) { if y == 0 { return 0, errors.New("division by zero") } return x / y, nil}
// Usageresult, err := divide(10, 2)if err != nil { fmt.Println("Error:", err) return}fmt.Println("Result:", result)Best Practices
- Keep functions small and focused
- Use meaningful function names
- Return errors as the last return value
- Use named return values for clarity
- Document exported functions
- Use defer for cleanup operations
Practical Example
Here’s a complete example that demonstrates various function concepts:
package main
import ( "fmt" "errors")
// Custom type for mathematical operationstype MathFunc func(x, y float64) float64
// Function that returns multiple valuesfunc divide(x, y float64) (result float64, err error) { if y == 0 { return 0, errors.New("division by zero") } result = x / y return // naked return}
// Variadic functionfunc average(numbers ...float64) float64 { total := 0.0 for _, num := range numbers { total += num } return total / float64(len(numbers))}
// Method on a custom typetype Calculator struct { brand string}
func (c Calculator) add(x, y float64) float64 { return x + y}
func main() { // Basic function usage result, err := divide(10, 2) if err != nil { fmt.Println("Error:", err) return } fmt.Println("10 ÷ 2 =", result)
// Variadic function avg := average(1, 2, 3, 4, 5) fmt.Println("Average:", avg)
// Method calc := Calculator{brand: "GoCalc"} sum := calc.add(5, 3) fmt.Println("5 + 3 =", sum)
// Anonymous function square := func(x float64) float64 { return x * x } fmt.Println("5² =", square(5))}In the next post, we’ll explore Arrays and Slices in Go!