Cached at:
08/04/26, 07:45 AM
# Soppo
Source: [https://soppolang.dev/](https://soppolang.dev/)
Go, with the features it's missing\.
Type safety and ergonomics, with full interop\.
[Take the tour](https://tour.soppolang.dev/)
## Familiar syntax
Soppo uses Go syntax wherever possible\. If you know Go, you already know most of Soppo\. Use any Go library directly, keep your existing tooling, and introduce Soppo gradually into existing projects\.
```
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", handleHome)
http.HandleFunc("/hello", handleHello)
fmt.Println("Server starting on :8080")
http.ListenAndServe(":8080", nil)
}
```
## Enums and pattern matching
Tagged unions with struct variants, and pattern matching that ensures you handle every case\. The compiler catches missing branches before your code ever runs, so you can refactor with confidence\.
```
type Shape enum {
Circle struct { radius float64 }
Rectangle struct { width, height float64 }
}
func area(s Shape) float64 {
match s {
case Shape.Circle{radius: r}:
return 3.14159 * r * r
case Shape.Rectangle{width: w, height: h}:
return w * h
}
}
```
## Error handling with`?`
No more repetitive`if err \!= nil`blocks\. The`?`operator propagates errors concisely while keeping error handling explicit and visible\. Add custom handling when you need it\.
```
func processFile(path string) error {
data := os.ReadFile(path) ?
result := parse(data) ? err {
return fmt.Errorf("parse failed: {err}")
}
fmt.Println("Processed {len(result)} items")
return nil
}
```
## Nil safety
Nil pointer dereferences are a common source of runtime panics in Go\. Soppo tracks nilability at compile time, so you catch these bugs before they reach production\. After a nil check, the type narrows automatically\.
```
func findUser(id int) ?*User {
if id == 0 {
return nil
}
return &User{name: "Alice"}
}
func greet(id int) {
user := findUser(id)
if user != nil {
fmt.Println("Hello {user.name}")
}
}
```
## Clear error messages
When something goes wrong, Soppo tells you exactly what happened and where\. Error messages show the relevant code, highlight the problem, and suggest how to fix it\. Debugging should be straightforward, not a guessing game\.
```
× Non-exhaustive match
╭─[main.sop:11:5]
10 │ var message string
11 │ ╭─▶ match colour {
12 │ │ case Colour.Red:
13 │ │ message = "Stop"
14 │ │ case Colour.Yellow:
15 │ │ message = "Wait"
16 │ ├─▶ }
· ╰──── missing variants: Green
17 │ }
╰────
help: Ensure all enum variants are handled, or add a `default` case
```
## Get started
The recommended way to install Soppo is through[SOPMOD](https://github.com/halcyonnouveau/sopmod), a version manager that handles installing, updating, and switching between versions\. It also manages Go, which Soppo uses internally for compilation\.
curl \-fsSL https://soppolang\.dev/install\.sh \| sh
Then add to your PATH and install:
export PATH="$HOME/\.sopmod/bin:$PATH" sopmod install sop latest
Or install just the`sop`binary using Cargo, without SOPMOD \(requires[Rust](https://www.rust-lang.org/tools/install)and[Go](https://go.dev/doc/install)\):
cargo install soppo