Functions
Functions
Introduction
In this lesson, you'll learn about functions in Go. Coming from TypeScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In TypeScript, you're familiar with functions.
Go has its own approach to functions, which we'll explore step by step.
The Go Way
Let's see how Go handles this concept. Here's a typical example:
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
result, err := divide(10, 2)
// Higher-order function
func apply[T, U any](fn func(T) U, value T) U {
return fn(value)
}
double := func(x float64) float64 { return x * 2 }Comparing to TypeScript
Here's how you might have written similar code in TypeScript:
function divide(a: number, b: number): [number, Error | null] {
if (b === 0) return [0, new Error("division by zero")];
return [a / b, null];
}
const [result, err] = divide(10, 2);
// Higher-order function
function apply<T, U>(fn: (v: T) => U, value: T): U {
return fn(value);
}
const double = (x: number) => x * 2;You may be used to different syntax or behavior.
Go functions can return multiple values natively — no need for tuples or Result types
You may be used to different syntax or behavior.
The second return value is conventionally error (nil if no error)
You may be used to different syntax or behavior.
Go function types: func(T) U instead of TypeScript's (v: T) => U
You may be used to different syntax or behavior.
Go generics (1.18+) use [T any] instead of <T>
Step-by-Step Breakdown
1. Multiple Return Values
Go natively supports multiple return values. The error-last convention (value, error) replaces TypeScript's Result<T, E> pattern or try/catch.
function findUser(id: number): User | null {
return db.get(id) ?? null;
}func findUser(id int) (*User, error) {
user, ok := db[id]
if !ok {
return nil, fmt.Errorf("user %d not found", id)
}
return &user, nil
}2. Function Types
Go function types use func(params) returns syntax. Anonymous functions work like arrow functions.
const greet = (name: string): string => `Hello, ${name}!`;
type Transformer = (s: string) => string;greet := func(name string) string {
return "Hello, " + name + "!"
}
type Transformer func(string) string3. Named Return Values
Go functions can name their return values. This documents intent and allows bare return statements — useful for complex functions.
function minMax(arr: number[]): { min: number; max: number } {}func minMax(arr []float64) (min, max float64) {
min, max = arr[0], arr[0]
for _, v := range arr {
if v < min { min = v }
if v > max { max = v }
}
return // bare return — returns named values
}4. defer — Cleanup Functions
defer schedules a function to run when the surrounding function returns. It's the Go way to handle cleanup (close files, release locks) — similar to try/finally.
try {
const f = openFile();
process(f);
} finally {
f.close();
}f, err := os.Open("file.txt")
if err != nil { return err }
defer f.Close() // runs when function returns
process(f)Common Mistakes
When coming from TypeScript, developers often make these mistakes:
- Go functions can return multiple values natively — no need for tuples or Result types
- The second return value is conventionally error (nil if no error)
- Go function types: func(T) U instead of TypeScript's (v: T) => U
Key Takeaways
- Go supports multiple return values — the (value, error) pattern replaces try/catch
- Function types use func(T) U syntax
- Named return values document intent and enable bare returns
- defer schedules cleanup to run on function exit — replaces try/finally