Full Go Interoperability

GALA transpiles to Go. Every Go package, type, and function is available in GALA code with zero friction. Your existing Go modules, third-party libraries, and tooling all work out of the box.


Importing Go Packages

Standard Go imports work directly in GALA:

import "strings"
import "fmt"
import "net/http"
import "encoding/json"

Grouped imports are supported:

import (
    "strings"
    "net/http"
    "os"
)

Aliased and dot imports work too:

import mystrings "strings"
import . "martianoff/gala/std"

Calling Go Functions

Call any Go function with GALA’s syntax:

import "strings"

val upper = strings.ToUpper("hello")        // "HELLO"
val parts = strings.Split("a,b,c", ",")     // []string{"a","b","c"}
val contains = strings.Contains("hello", "ell")  // true

Go functions that return (T, error) work naturally:

import "os"

val file, err = os.Open("data.txt")
if err != nil {
    Println(s"Error: ${err.Error()}")
}

Or wrap them in Try for monadic error handling:

import "os"
import . "martianoff/gala/std"

val result = Try(() => os.Getwd())
val dir = result.GetOrElse("/tmp")

Using Go Types

Define and use Go struct types with GALA syntax:

import "net/http"

// Go struct types work in GALA
var client = &http.Client{}

GALA structs are Go structs under the hood, so they interoperate seamlessly:

type Config struct {
    var Host string
    var Port int
}

// Pass to any Go function expecting this struct
val jsonBytes, _ = json.Marshal(Config{Host: "localhost", Port: 8080})

Type Conversions

GALA supports Go-style type conversions:

// Numeric conversions
val n = int64(42)
val f = float64(10)
val i = int(3.14)           // truncates to 3

// Rune/string conversions
val r = rune(65)            // int to rune: 'A'
val s = string(r)           // rune to string: "A"

For byte and rune slice conversions, use the go_interop helpers:

import . "martianoff/gala/go_interop"

val bytes = ToBytes("hello")   // string to []byte
val str = ToString(bytes)      // []byte to string
val runes = ToRunes("hello")   // string to []rune

Slices: Go []T Interop

GALA collections (Array, List) are preferred for general programming. When you need Go’s native []T — for passing data to Go libraries or variadic arguments — use the go_interop package:

import . "martianoff/gala/go_interop"

val goSlice = SliceOf(1, 2, 3, 4, 5)    // Go []int
val empty = SliceEmpty[int]()            // Go []int{}
val withCap = SliceWithCapacity[int](10) // []int with capacity 10

Convert between GALA collections and Go slices:

import . "martianoff/gala/collection_immutable"
import . "martianoff/gala/go_interop"

// GALA Array → Go slice
val arr = ArrayOf(1, 2, 3)
val goSlice = arr.ToGoSlice()

// Go slice → GALA Array
val backToArray = ArrayFromSlice(goSlice)

When to Use What

Use Case Recommendation
General programming Array or List from collection_immutable
Need Map/Filter/FoldLeft Array or List (full functional API)
Passing data to Go libraries SliceOf from go_interop, or .ToGoSlice()
Variadic function arguments Go slices with SliceOf

Available Slice Functions

Function Description
SliceOf(elements...) Create Go slice from values
SliceEmpty[T]() Create empty Go slice
SliceWithCapacity[T](cap) Empty slice with capacity
SliceCopy(slice) Copy a slice
SliceAppendAll(dst, src) Append all elements
SlicePrepend(s, value) Insert at front
SliceTake(s, n) Take first n elements
SliceDrop(s, n) Drop first n elements

Maps: Go map[K]V Interop

GALA’s HashMap is preferred for most use cases. When you need Go-native map[K]V for interoperability:

import . "martianoff/gala/std"

// Create and populate
var goMap = MapEmpty[string, int]()
goMap = MapPut(goMap, "key", 42)

// Query
val value, ok = MapGet(goMap, "key")
val exists = MapContains(goMap, "key")

// Iterate
MapForEach(goMap, (k string, v int) => {
    Println(s"$k: $v")
})

Convert between HashMap and Go map:

import "martianoff/gala/collection_immutable"

val hashMap = collection_immutable.HashMapFromGoMap(goMap)
val backToGoMap = hashMap.ToGoMap()

Available Map Functions

Function Description
MapEmpty[K, V]() Create empty map
MapPut(m, k, v) Add/update entry, returns map
MapGet(m, k) Get value and existence flag
MapContains(m, k) Check if key exists
MapDelete(m, k) Remove key, returns map
MapLen(m) Number of entries
MapForEach(m, f) Iterate all entries

Go Built-in Functions

Go’s built-in functions are available directly:

val length = len("hello")         // 5
val sliceCap = cap(mySlice)       // slice capacity
val ch = make(chan int, 10)       // buffered channel

// Println and Print are available without importing fmt
Println("hello world")
Print("no newline")

Further Reading