Kodewick
Start learning →

Online Go Compiler

Free, nothing to install, no sign-in. Run it, then watch each goroutine in its own lane and every channel fill up.

Try:
Online Go CompilerFull screen · your code and output are still here
Go
Examples
pipeline.go
package main

import "fmt"

func main() {
	ch := make(chan int)
	go func() {
		for i := 1; i <= 3; i++ {
			ch <- i * i
		}
		close(ch)
	}()
	for v := range ch {
		fmt.Println(v)
	}
}
Output

Press Run to see the result

Go 1.24Ln 1, Col 1Spaces: 4Learn Go →Change it to keep it in My code
Not just run

Watch your Go run: goroutines, channels and slices

Each goroutine gets a lane, and you can see who is running and who is waiting for what. A channel shows what is in its buffer; slices show the array they share.

▶ Plays right here, no sign-in
Debug & share

Run it, pause it, replay it, share it

As handy as VS Code on your computer, plus what it does not have: every step drawn.

Step

One line at a time, every value beside it

Press Step and the code stops at each line: the lit line runs next, and every variable’s value sits beside it. Go back too, with the ← → keys.

One line at a time, every value beside it
Replay an error

It crashed? See exactly how it went wrong

Under the error, press “See how it went wrong”: the visualizer opens at the failing step, in red, with the reason in plain words. Step back through everything before it.

It crashed? See exactly how it went wrong
Share

A link, a GIF, a picture of the code: post it to X

A link opens this very code. Or export a GIF of it running (light or dark, wide or tall) or a picture of the code, and post it to X, a chat, or embed it in a blog.

A link, a GIF, a picture of the code: post it to X
Examples

12 Go examples: one click runs them above

Each one can be stepped through and visualized. Change it, run it again.

FizzBuzz

A for loop and a switch with no value.

package main

import "fmt"

func main() {
	for i := 1; i <= 15; i++ {
		switch {
		case i%15 == 0:
			fmt.Println("FizzBuzz")
		case i%3 == 0:
			fmt.Println("Fizz")
		case i%5 == 0:
			fmt.Println("Buzz")
		default:
			fmt.Println(i)
		}
	}
}

Slices and append

len and cap as it grows; the visualizer shows the array behind it.

package main

import "fmt"

func main() {
	var s []int
	for i := 1; i <= 5; i++ {
		s = append(s, i*i)
		fmt.Println(s, len(s), cap(s))
	}
}

Counting with a map

How many times each word appears.

package main

import (
	"fmt"
	"sort"
	"strings"
)

func main() {
	text := "go is fun and go is fast"
	count := map[string]int{}
	for _, w := range strings.Fields(text) {
		count[w]++
	}
	keys := make([]string, 0, len(count))
	for k := range count {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	for _, k := range keys {
		fmt.Println(k, count[k])
	}
}

Structs and methods

A pointer receiver changes the struct itself.

package main

import "fmt"

type Account struct {
	Owner   string
	Balance int
}

func (a *Account) Deposit(n int) {
	a.Balance += n
}

func main() {
	acc := Account{"Maya", 100}
	acc.Deposit(50)
	fmt.Println(acc.Owner, acc.Balance)
}

Interfaces

Different shapes, one Area method.

package main

import (
	"fmt"
	"math"
)

type Shape interface {
	Area() float64
}

type Rect struct{ W, H float64 }
type Circle struct{ R float64 }

func (r Rect) Area() float64   { return r.W * r.H }
func (c Circle) Area() float64 { return math.Pi * c.R * c.R }

func main() {
	shapes := []Shape{Rect{3, 4}, Circle{1}}
	for _, s := range shapes {
		fmt.Printf("%.2f\n", s.Area())
	}
}

Errors

A function returns a value and an error.

package main

import (
	"errors"
	"fmt"
)

func divide(a, b int) (int, error) {
	if b == 0 {
		return 0, errors.New("division by zero")
	}
	return a / b, nil
}

func main() {
	for _, b := range []int{2, 0} {
		q, err := divide(10, b)
		if err != nil {
			fmt.Println("error:", err)
			continue
		}
		fmt.Println(q)
	}
}

A closure

A function that keeps its own counter.

package main

import "fmt"

func counter() func() int {
	n := 0
	return func() int {
		n++
		return n
	}
}

func main() {
	next := counter()
	fmt.Println(next(), next(), next())
}

A goroutine and a channel

One goroutine sends squares, main receives them.

package main

import "fmt"

func main() {
	ch := make(chan int)
	go func() {
		for i := 1; i <= 3; i++ {
			ch <- i * i
		}
		close(ch)
	}()
	for v := range ch {
		fmt.Println(v)
	}
}

Wait for everyone

sync.WaitGroup and a Mutex.

package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	var mu sync.Mutex
	total := 0
	for i := 1; i <= 3; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Done()
			mu.Lock()
			total += n
			mu.Unlock()
		}(i)
	}
	wg.Wait()
	fmt.Println("total", total)
}

select and a timeout

Wait for whichever comes first.

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan string)
	go func() {
		time.Sleep(50 * time.Millisecond)
		ch <- "done"
	}()
	select {
	case r := <-ch:
		fmt.Println(r)
	case <-time.After(time.Second):
		fmt.Println("too slow")
	}
}

Sorting with sort.Slice

Sort people by age with a less function.

package main

import (
	"fmt"
	"sort"
)

type Person struct {
	Name string
	Age  int
}

func main() {
	people := []Person{{"Ava", 31}, {"Ben", 25}, {"Cy", 40}}
	sort.Slice(people, func(i, j int) bool {
		return people[i].Age < people[j].Age
	})
	fmt.Println(people)
}

Index out of range

A panic, in Go’s own words, and the step where it happened.

package main

import "fmt"

func main() {
	nums := []int{1, 2, 3}
	for i := 0; i <= len(nums); i++ {
		fmt.Println(nums[i])
	}
}
Three steps

How to run Go online

  1. 1
    Write code, or pick an exampleThe editor works like VS Code: completion, matching brackets, Ctrl+/ to comment.
  2. 2
    Press Run, or Ctrl + EnterThe output shows beside the code; when the program calls fmt.Scan, answer it right there.
  3. 3
    To see how it runs: Step, or VisualizeYour code is kept in this browser; find it again in My code.
What works

Go, running in your browser

✓ Works

  • Go 1.24: structs, methods, interfaces, generics, closures, defer / panic / recover
  • goroutines, channels, select, sync (WaitGroup, Mutex), time
  • fmt, strings, strconv, sort, math, errors …
  • Reading input with fmt.Scan
  • Compile errors and panics in Go’s words; deadlocks found

✕ Not yet

  • Packages outside the standard library (go get)
  • Files on your computer, the network (net/http)
  • reflect, unsafe, cgo
  • Programs that never end (stopped after a while)
FAQ

About the online Go compiler

Is it free? Do I need an account?

No and no. Open the page and write Go; your code stays in your own browser.

How is this different from the Go Playground?

Both run Go in the browser. Here you can also step through it, see each goroutine in its own lane and what every channel holds, read input with fmt.Scan, and keep your files.

Is this the real Go compiler?

It is our own Go engine running in your browser, made to give the same output as Go 1.24 for the standard library it supports.

Can it find a deadlock?

Yes: when every goroutine is waiting it stops, says so as Go does, and the visualizer shows who waits for what.

My program crashed. Can I see why?

Under the error, press “See how it went wrong”: the visualizer opens at the failing step and you can go back through it.

Does it work on a phone?

Yes. Tap the code to write full screen, with keys for Tab, braces and :=.

Where is my code kept?

In this browser, under My code. Share anything important as a link.

How do I share it?

Share → Copy link, or export a GIF of it running, or a picture of the code, and post it to X.

More

Four more languages, the same tools