Odin is a systems programming language designed as a practical alternative to C — with modern features like tagged unions, defer, built-in SIMD, and zero hidden control flow.
Why Odin Matters
C is 50 years old. Its footguns (undefined behavior, manual memory management, preprocessor macros) cause most security vulnerabilities. Odin provides C-level performance with modern safety features and no hidden complexity.
What you get for free:
- C-level performance with no hidden costs
- Tagged unions and pattern matching
- Built-in array programming (SIMD)
- defer statement for resource cleanup
- No undefined behavior by design
- No preprocessor, no macros, no header files
- Zero-cost abstractions
- Cross-compilation built in
Quick Start
# Install (from GitHub releases)
# https://github.com/odin-lang/Odin/releases
# Build and run
odin run main.odin -file
# Build optimized
odin build . -o:speed
# Cross compile
odin build . -target:windows_amd64
The Basics
package main
import "core:fmt"
import "core:strings"
main :: proc() {
// Variables
name := "Odin"
age : int = 3
pi :: 3.14159 // Compile-time constant
fmt.printf("Hello from %s! Age: %d, Pi: %f\n", name, age, pi)
// Multiple return values
quot, rem := divmod(17, 5)
fmt.printf("%d / %d = %d remainder %d\n", 17, 5, quot, rem)
}
divmod :: proc(a, b: int) -> (int, int) {
return a / b, a % b
}
Tagged Unions
package main
import "core:fmt"
import "core:math"
Shape :: union {
Circle,
Rectangle,
Triangle,
}
Circle :: struct {
radius: f64,
}
Rectangle :: struct {
width, height: f64,
}
Triangle :: struct {
a, b, c: f64,
}
area :: proc(shape: Shape) -> f64 {
switch s in shape {
case Circle:
return math.PI * s.radius * s.radius
case Rectangle:
return s.width * s.height
case Triangle:
p := (s.a + s.b + s.c) / 2
return math.sqrt(p * (p - s.a) * (p - s.b) * (p - s.c))
case:
return 0
}
}
main :: proc() {
shapes := []Shape{
Circle{radius = 5},
Rectangle{width = 3, height = 4},
Triangle{a = 3, b = 4, c = 5},
}
for shape in shapes {
fmt.printf("Area: %.2f\n", area(shape))
}
}
Defer (Resource Cleanup)
package main
import "core:os"
import "core:fmt"
read_file :: proc(path: string) -> ([]byte, bool) {
fd, err := os.open(path)
if err != os.ERROR_NONE {
return nil, false
}
defer os.close(fd) // Guaranteed cleanup
data, ok := os.read_entire_file(fd)
return data, ok
}
Array Programming (Built-in SIMD)
package main
import "core:fmt"
main :: proc() {
// SIMD operations on arrays
a := [4]f32{1, 2, 3, 4}
b := [4]f32{5, 6, 7, 8}
sum := a + b // [6, 8, 10, 12]
product := a * b // [5, 12, 21, 32]
scaled := a * 2 // [2, 4, 6, 8]
fmt.println("Sum:", sum)
fmt.println("Product:", product)
fmt.println("Scaled:", scaled)
// Matrix-style operations
dot := a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]
fmt.println("Dot product:", dot) // 70
}
Allocators (No Hidden malloc)
package main
import "core:mem"
import "core:fmt"
main :: proc() {
// Arena allocator — free everything at once
arena: mem.Arena
mem.arena_init(&arena, make([]byte, 1024 * 1024))
defer mem.arena_destroy(&arena)
arena_allocator := mem.arena_allocator(&arena)
// All allocations use the arena
data := make([]int, 100, arena_allocator)
for i in 0..<100 {
data[i] = i * i
}
// No need to free individual allocations
}
Useful Links
Building high-performance data tools? Check out my developer tools on Apify for ready-made web scrapers, or email spinov001@gmail.com for custom solutions.
Top comments (0)