Coming From Another Language: Go
● Beginner6 minBefore this: Coming From Another Language
From Go: try instead of if err != nil, no nil, interfaces a type names, and no garbage collector.
Here is one small program twice: in Go as you would write it, then in Kavach. Orders with a quantity and a price, a total that refuses an order with no quantity, and discount codes that may be missing. Both print the same three lines.
package main
import "fmt"
type Order struct {
Item string
Qty int
Cents int
}
func (o Order) Cost() int {
return o.Qty * o.Cents
}
type BadQty struct {
Item string
}
func (e BadQty) Error() string {
return "no quantity for " + e.Item
}
func total(orders []Order) (int, error) {
sum := 0
for _, o := range orders {
if o.Qty <= 0 {
return 0, BadQty{Item: o.Item}
}
sum += o.Cost()
}
return sum, nil
}
func main() {
codes := map[string]int{"SPRING": 10, "VIP": 25}
orders := []Order{{"pen", 3, 150}, {"cup", 1, 900}}
sum, err := total(orders)
if err != nil {
sum = 0
}
off := codes["SPRING"]
fmt.Printf("total %d, with %d%% off %d\n", sum, off, sum*(100-off)/100)
fmt.Printf("WINTER gives %d%%\n", codes["WINTER"])
broken := []Order{{"kite", 0, 500}}
if t, err := total(broken); err != nil {
if bad, ok := err.(BadQty); ok {
fmt.Printf("refused: no quantity for %s\n", bad.Item)
}
} else {
fmt.Printf("total %d\n", t)
}
}type Order {
item: String
qty: Int
cents: Int
fn cost(self) -> Int {
self.qty * self.cents
}
}
type OrderError = BadQty(item: String)
fn total(orders: [Order]) -> Int ! OrderError {
for o in orders {
if o.qty <= 0 {
fail OrderError.BadQty(item: o.item)
}
}
orders.sum(o => o.cost())
}
fn main() {
const codes = ["SPRING": 10, "VIP": 25]
const orders = [Order(item: "pen", qty: 3, cents: 150), Order(item: "cup", qty: 1, cents: 900)]
const sum = total(orders) catch _ => 0
const off = codes["SPRING"] ?? 0
print("total {sum}, with {off}% off {sum * (100 - off) / 100}")
print("WINTER gives {codes["WINTER"] ?? 0}%")
const broken = [Order(item: "kite", qty: 0, cents: 500)]
match total(broken) {
ok(t) => print("total {t}"),
err(OrderError.BadQty(item)) => print("refused: no quantity for {item}"),
}
}The program ran and printed:
kavach run orders.kav
total 1350, with 10% off 1215WINTER gives 0%refused: no quantity for kite
What changes
| In Go | In Kavach | Learn it |
|---|---|---|
a struct with methods on a receiver | type Order { … }, its methods inside it | Records |
| interfaces met without saying so | a type names the interfaces it implements: type Guard: Drop | Interfaces |
(int, error) and if err != nil | -> Int ! OrderError, and try to pass the error on | try |
nil | none, only in a type that ends in ? | Optionals |
codes["WINTER"] gives 0 when it's missing | codes["WINTER"] is an Int?: you say ?? 0 | Reading a value |
| goroutines | spawn; a task never outlives the function that started it | Tasks Never Leak |
| channels | channels too: put and take | Channels |
| a garbage collector | no collector: a value is freed after its last use | Automatic Memory |
| a capital letter exports a name | pub exports it | pub |
fmt.Printf("%d", n) | print("{n}") | Interpolation |
go.mod | kavach.toml | Packages |
Habits from other languages get a clear error that says what to write instead: see Habits from other languages.