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