# Declaring Functions
Functions are declared with func. Parameters have their type after the name, and the return type comes after the parameter list.
package main
import "fmt"
func greet(name string) string {
return "Hello, " + name + "!"
}
func main() {
msg := greet("Gopher")
fmt.Println(msg)
}# Multiple Return Values
Go functions can return multiple values. The most common pattern is returning a result and an error:
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, 3)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Result: %.2f\n", result)
}# Variadic Functions
Use ...Type to accept a variable number of arguments. Inside the function, it becomes a slice:
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
fmt.Println(sum(1, 2, 3)) // 6
fmt.Println(sum(10, 20)) // 30
nums := []int{4, 5, 6}
fmt.Println(sum(nums...)) // spread a slice# Anonymous Functions & Closures
Functions are first-class values in Go. You can assign them to variables, pass them as arguments, and return them:
func makeCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
counter := makeCounter()
fmt.Println(counter()) // 1
fmt.Println(counter()) // 2
fmt.Println(counter()) // 3
}# defer — Cleanup on Exit
defer schedules a function to run when the enclosing function returns. Deferred calls execute in LIFO (stack) order:
func readFile(path string) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close() // always runs on return
// ... work with file ...
return nil
}⚡ Key Takeaways
- Functions return multiple values — the
(result, error)pattern is idiomatic - Functions are first-class values — assign, pass, return them freely
- Closures capture variables by reference, not by value
deferruns on function exit, in LIFO order — great for cleanup- Use
...Typefor variadic parameters (becomes a slice inside)