GoLang Goroutines

📢 This article was translated by gemini-3-flash-preview

Golang Series

Hello GoLang: https://blog.yexca.net/archives/154
GoLang (var and const): https://blog.yexca.net/archives/155
GoLang (func): https://blog.yexca.net/archives/156
GoLang (slice and map): https://blog.yexca.net/archives/160
GoLang (OOP): https://blog.yexca.net/archives/162
GoLang (reflect): https://blog.yexca.net/archives/204
GoLang (struct tag): https://blog.yexca.net/archives/205
GoLang (goroutine): This Article
GoLang (channel): https://blog.yexca.net/archives/207


Process -> Thread -> Coroutine

A coroutine is a “lightweight thread.” You can easily spawn tens of thousands of them without exhausting system resources. Multiple coroutines share the resources allocated to their parent thread.

Go has native support for coroutines, which are called goroutines. Concurrency in Go is achieved through goroutines and channels.

Creating a Goroutine

Use the go keyword to start a goroutine.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
    "fmt"
    "time"
)

func newTask() {
    i := 0
    for {
        fmt.Println("newTask goroutine i =", i)
        i++
        time.Sleep(1 * time.Second)
    }
}

func main() {
    go newTask()

    i := 0
    for {
        fmt.Println("main goroutine i =", i)
        i++
        time.Sleep(1 * time.Second)
    }
}

Using Anonymous Functions

You can also use anonymous functions with goroutines.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
    "fmt"
    "time"
)

func main() {
    go func() {
        defer fmt.Println("A.defer")
        func() {
            defer fmt.Println("B.defer")

            fmt.Println("B")
        }() // executes this anonymous function

        fmt.Println("A")
    }()

    time.Sleep(2 * time.Second)
}

Anonymous functions can take parameters and return values. However, to get a return value from a goroutine, you need to use a channel. The example below shows only parameters:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package main

import (
    "fmt"
    "time"
)

func main() {
    go func(a, b int) {
        fmt.Println("a =", a, "b =", b)
    }(10, 20)

    time.Sleep(2 * time.Second)
}

Exiting

When the main goroutine exits, all other worker goroutines are automatically terminated.

You can also use runtime.Goexit() to immediately stop the current goroutine (any defer statements will still execute).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    go func() {
        defer fmt.Println("A.defer")
        func() {
            defer fmt.Println("B.defer")
            runtime.Goexit() // exit the goroutine
            fmt.Println("B")
        }() // executes this anonymous function

        fmt.Println("A")
    }()

    time.Sleep(2 * time.Second)
}

/*
 * Output:
 * B.defer
 * A.defer
 */