Skip to main content
LiveCodes supports Go (Golang) execution in the browser using Yaegi (interpreter) and TinyGo (WebAssembly compiler).

Configuration

Language Name: go (Yaegi) or go-wasm (TinyGo)
File Extensions: .go, .golang
Editor: Script editor
Compiler: Yaegi interpreter or TinyGo WASM
Formatter: gofmt

Go with Yaegi

Yaegi is a Go interpreter that runs Go code in the browser:
package main

import (
	"fmt"
	"strings"
)

func main() {
	// Basic output
	fmt.Println("Hello, World!")
	
	// Variables
	name := "Alice"
	age := 30
	fmt.Printf("Name: %s, Age: %d\n", name, age)
	
	// String manipulation
	upper := strings.ToUpper(name)
	fmt.Println(upper)
	
	// Arrays and slices
	numbers := []int{1, 2, 3, 4, 5}
	for i, n := range numbers {
		fmt.Printf("Index %d: %d\n", i, n)
	}
}

Functions

package main

import "fmt"

// Regular function
func greet(name string) string {
	return "Hello, " + name + "!"
}

// Multiple return values
func divide(a, b float64) (float64, error) {
	if b == 0 {
		return 0, fmt.Errorf("division by zero")
	}
	return a / b, nil
}

// Variadic function
func sum(numbers ...int) int {
	total := 0
	for _, n := range numbers {
		total += n
	}
	return total
}

func main() {
	fmt.Println(greet("Alice"))
	
	result, err := divide(10, 2)
	if err != nil {
		fmt.Println("Error:", err)
	} else {
		fmt.Printf("Result: %.2f\n", result)
	}
	
	fmt.Println("Sum:", sum(1, 2, 3, 4, 5))
}

Structs and Methods

package main

import "fmt"

type Person struct {
	Name  string
	Age   int
	Email string
}

// Method on Person
func (p Person) Greet() string {
	return fmt.Sprintf("Hello, I'm %s", p.Name)
}

// Pointer receiver method
func (p *Person) HaveBirthday() {
	p.Age++
}

func main() {
	person := Person{
		Name:  "John Doe",
		Age:   30,
		Email: "john@example.com",
	}
	
	fmt.Println(person.Greet())
	
	person.HaveBirthday()
	fmt.Printf("New age: %d\n", person.Age)
}

Interfaces

package main

import "fmt"

type Shape interface {
	Area() float64
	Perimeter() float64
}

type Rectangle struct {
	Width  float64
	Height float64
}

func (r Rectangle) Area() float64 {
	return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
	return 2 * (r.Width + r.Height)
}

type Circle struct {
	Radius float64
}

func (c Circle) Area() float64 {
	return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
	return 2 * 3.14159 * c.Radius
}

func printShapeInfo(s Shape) {
	fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}

func main() {
	rect := Rectangle{Width: 10, Height: 5}
	circ := Circle{Radius: 7}
	
	printShapeInfo(rect)
	printShapeInfo(circ)
}

Goroutines and Channels

package main

import (
	"fmt"
	"time"
)

func worker(id int, jobs <-chan int, results chan<- int) {
	for j := range jobs {
		fmt.Printf("Worker %d processing job %d\n", id, j)
		time.Sleep(time.Second)
		results <- j * 2
	}
}

func main() {
	jobs := make(chan int, 5)
	results := make(chan int, 5)
	
	// Start workers
	for w := 1; w <= 3; w++ {
		go worker(w, jobs, results)
	}
	
	// Send jobs
	for j := 1; j <= 5; j++ {
		jobs <- j
	}
	close(jobs)
	
	// Collect results
	for a := 1; a <= 5; a++ {
		<-results
	}
}

Error Handling

package main

import (
	"errors"
	"fmt"
)

func validateAge(age int) error {
	if age < 0 {
		return errors.New("age cannot be negative")
	}
	if age > 150 {
		return errors.New("age too high")
	}
	return nil
}

func processUser(name string, age int) error {
	if name == "" {
		return fmt.Errorf("name cannot be empty")
	}
	
	if err := validateAge(age); err != nil {
		return fmt.Errorf("invalid age: %w", err)
	}
	
	fmt.Printf("Processing user: %s, %d\n", name, age)
	return nil
}

func main() {
	if err := processUser("Alice", 30); err != nil {
		fmt.Println("Error:", err)
	}
	
	if err := processUser("", 25); err != nil {
		fmt.Println("Error:", err)
	}
}

DOM Manipulation

Access browser APIs through JavaScript interop:
package main

import (
	"syscall/js"
)

func main() {
	// Get document
	doc := js.Global().Get("document")
	
	// Create element
	div := doc.Call("createElement", "div")
	div.Set("textContent", "Hello from Go!")
	div.Get("classList").Call("add", "container")
	
	// Append to body
	body := doc.Get("body")
	body.Call("appendChild", div)
	
	// Create button
	button := doc.Call("createElement", "button")
	button.Set("textContent", "Click me")
	
	// Add event listener
	callback := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		js.Global().Call("alert", "Button clicked!")
		return nil
	})
	button.Call("addEventListener", "click", callback)
	
	body.Call("appendChild", button)
}

Code Formatting

Automatic formatting with gofmt:
// Before formatting
package main
import "fmt"
func main(){fmt.Println("Hello")}

// After formatting (Ctrl+Shift+F)
package main

import "fmt"

func main() {
	fmt.Println("Hello")
}

Example Projects

Counter

package main

import (
	"fmt"
	"syscall/js"
)

var count = 0

func createCounter() {
	doc := js.Global().Get("document")
	body := doc.Get("body")
	
	// Display
	display := doc.Call("createElement", "div")
	display.Set("id", "display")
	display.Set("textContent", fmt.Sprintf("Count: %d", count))
	body.Call("appendChild", display)
	
	// Increment button
	incBtn := doc.Call("createElement", "button")
	incBtn.Set("textContent", "Increment")
	incBtn.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		count++
		doc.Call("getElementById", "display").Set("textContent", fmt.Sprintf("Count: %d", count))
		return nil
	}))
	body.Call("appendChild", incBtn)
	
	// Decrement button
	decBtn := doc.Call("createElement", "button")
	decBtn.Set("textContent", "Decrement")
	decBtn.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		count--
		doc.Call("getElementById", "display").Set("textContent", fmt.Sprintf("Count: %d", count))
		return nil
	}))
	body.Call("appendChild", decBtn)
}

func main() {
	createCounter()
}

Data Structures

package main

import "fmt"

type Stack struct {
	items []int
}

func (s *Stack) Push(item int) {
	s.items = append(s.items, item)
}

func (s *Stack) Pop() (int, bool) {
	if len(s.items) == 0 {
		return 0, false
	}
	index := len(s.items) - 1
	item := s.items[index]
	s.items = s.items[:index]
	return item, true
}

func (s *Stack) Peek() (int, bool) {
	if len(s.items) == 0 {
		return 0, false
	}
	return s.items[len(s.items)-1], true
}

func main() {
	stack := &Stack{}
	
	stack.Push(1)
	stack.Push(2)
	stack.Push(3)
	
	if top, ok := stack.Peek(); ok {
		fmt.Printf("Top: %d\n", top)
	}
	
	for {
		if item, ok := stack.Pop(); ok {
			fmt.Printf("Popped: %d\n", item)
		} else {
			break
		}
	}
}

Go WebAssembly (TinyGo)

For full WebAssembly compilation, use go-wasm:
package main

import (
	"syscall/js"
)

func fibonacci(n int) int {
	if n <= 1 {
		return n
	}
	return fibonacci(n-1) + fibonacci(n-2)
}

func main() {
	// Export function to JavaScript
	js.Global().Set("fibonacci", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		n := args[0].Int()
		return fibonacci(n)
	}))
	
	// Keep program running
	select {}
}
TinyGo WebAssembly produces smaller binaries optimized for the browser but with some standard library limitations.

Supported Packages

Yaegi supports many standard library packages:
  • fmt - Formatted I/O
  • strings - String manipulation
  • math - Mathematical functions
  • time - Time and duration
  • errors - Error handling
  • sort - Sorting algorithms
  • encoding/json - JSON encoding/decoding
package main

import (
	"encoding/json"
	"fmt"
	"time"
)

type User struct {
	Name      string    `json:"name"`
	Email     string    `json:"email"`
	CreatedAt time.Time `json:"created_at"`
}

func main() {
	user := User{
		Name:      "Alice",
		Email:     "alice@example.com",
		CreatedAt: time.Now(),
	}
	
	data, _ := json.MarshalIndent(user, "", "  ")
	fmt.Println(string(data))
}

Best Practices

Always handle errors explicitly:
result, err := someFunction()
if err != nil {
    fmt.Println("Error:", err)
    return
}
// Use result
Pass large structs by pointer:
// Good
func processUser(u *User) {
    // modify user
}

// Inefficient for large structs
func processUser(u User) {
    // creates copy
}
Use defer for resource cleanup:
func processFile() error {
    f, err := os.Open("file.txt")
    if err != nil {
        return err
    }
    defer f.Close()
    
    // process file
    return nil
}

Limitations

Limited Packages: Yaegi supports a subset of the Go standard library. Some packages may not be available.
No CGo: C interop is not supported in browser environments.
For full standard library support, consider using go-wasm with TinyGo, though it has different trade-offs.

Python

Alternative dynamic language

Rust

Systems programming language

WebAssembly

WASM compilation target

TypeScript

Typed JavaScript alternative