Functions in Go - Complete Guide
Functions are the building blocks of Go programs. They let you write code once and use it many times. Learning functions is essential - let's master them together!
What is a Function?
A function is a block of code that performs a specific task. You give it input, it does something, and optionally returns output.
Basic Function Syntax
func functionName() {
// Code here
}Simple Example
package main
import "fmt"
func greet() {
fmt.Println("Hello, World!")
}
func main() {
greet() // Call the function
}Functions with Parameters
Functions can take input values called parameters:
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
func main() {
greet("John") // Hello, John!
greet("Jane") // Hello, Jane!
}Multiple Parameters
func add(a int, b int) {
sum := a + b
fmt.Println(sum)
}
// Shorter syntax (same types)
func multiply(a, b int) {
product := a * b
fmt.Println(product)
}Functions with Return Values
Functions can return values:
func add(a int, b int) int {
return a + b
}
func main() {
result := add(5, 3)
fmt.Println(result) // 8
}Multiple Return Values
Go can return multiple values - this is very useful!
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("cannot divide by zero")
}
return a / b, nil
}
func main() {
result, err := divide(10, 2)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println(result) // 5
}
}Named Return Values
You can name return values:
func calculate(a, b int) (sum int, product int) {
sum = a + b
product = a * b
return // Naked return - uses named values
}
func main() {
s, p := calculate(3, 4)
fmt.Println(s, p) // 7 12
}Variadic Functions
Functions that accept any number of arguments:
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
func main() {
fmt.Println(sum(1, 2, 3)) // 6
fmt.Println(sum(1, 2, 3, 4, 5)) // 15
}Function as Values
Functions are first-class citizens in Go - you can assign them to variables:
func add(a, b int) int {
return a + b
}
func main() {
operation := add
result := operation(5, 3)
fmt.Println(result) // 8
}Anonymous Functions
Functions without names:
func main() {
greet := func(name string) {
fmt.Printf("Hello, %s!\n", name)
}
greet("John") // Hello, John!
}Immediately Invoked Functions
func main() {
func() {
fmt.Println("This runs immediately!")
}()
}Closures
Functions that capture variables from outer scope:
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
c := counter()
fmt.Println(c()) // 1
fmt.Println(c()) // 2
fmt.Println(c()) // 3
}Methods (Functions on Types)
Go doesn't have classes, but you can add methods to types:
type Rectangle struct {
width float64
height float64
}
// Method on Rectangle
func (r Rectangle) area() float64 {
return r.width * r.height
}
func main() {
rect := Rectangle{width: 10, height: 5}
fmt.Println(rect.area()) // 50
}Pointer Receivers
Use pointers to modify the original value:
func (r *Rectangle) scale(factor float64) {
r.width *= factor
r.height *= factor
}
func main() {
rect := Rectangle{width: 10, height: 5}
rect.scale(2)
fmt.Println(rect.width) // 20
}Defer Statement
Defer runs a function after the surrounding function returns:
func main() {
defer fmt.Println("This runs last")
fmt.Println("This runs first")
fmt.Println("This runs second")
}
// Output:
// This runs first
// This runs second
// This runs lastCommon use case - closing files:
file, err := os.Open("file.txt")
if err != nil {
return err
}
defer file.Close() // Always closes, even if error occursVisual Explanation: Function Flow
Here's how functions work:
Function Call Flow:
┌─────────────────────────────┐
│ main() │
│ │ │
│ ├─► greet("John") │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────┐ │
│ │ │ greet() │ │
│ │ │ executes │ │
│ │ └──────┬───────┘ │
│ │ │ │
│ │ ▼ │
│ │ Returns control │
│ │ │
│ └─► Continue in main() │
└─────────────────────────────┘Frequently Asked Questions (FAQ)
Q1: What's the difference between a function and a method?
A:
- Function - Standalone, not attached to a type
- Method - Attached to a type (has a receiver)
Methods are functions with receivers!
Q2: Can functions return multiple values?
A: Yes! Go supports multiple return values, which is very common:
func getData() (string, int, error) {
return "name", 25, nil
}Q3: What's a variadic function?
A: A function that accepts any number of arguments:
func sum(numbers ...int) int {
// numbers is a slice
}Q4: When should I use a pointer receiver?
A: Use pointer receivers when:
- You need to modify the value
- The struct is large (for efficiency)
- You want to share the same instance
Q5: What does defer do?
A: Defer schedules a function to run after the current function returns. It's great for cleanup tasks like closing files.
Q6: Can I pass functions as parameters?
A: Yes! Functions are first-class in Go:
func apply(fn func(int) int, x int) int {
return fn(x)
}Q7: What's a closure?
A: A function that captures variables from its outer scope. The inner function "closes over" the outer variables.
Q8: Can I have optional parameters?
A: Not directly, but you can use variadic parameters or structs with default values to achieve similar results.
Q9: What's the difference between value and pointer receivers?
A:
- Value receiver - Works on a copy, doesn't modify original
- Pointer receiver - Works on original, can modify it
Q10: How do I handle errors in functions?
A: Return error as the last return value:
func doSomething() (result string, err error) {
// If error occurs:
return "", fmt.Errorf("something went wrong")
// If success:
return "success", nil
}Next Steps
Now that you understand functions, here's what to learn next:
- Next: Learn about Go Packages - Organize your code
- Explore Go Structs - Create custom types
- Understand Go Interfaces - Define behavior contracts
- Master Go Error Handling - Handle errors properly
Functions are essential in Go. Practice writing different types of functions to get comfortable!