iT邦幫忙

2024 iThome 鐵人賽

DAY 15
1
Software Development

可以Go一輩子嗎?系列 第 15

Day15. Go語言中的Goroutine介紹與使用

  • 分享至 

  • xImage
  •  

Day15. Go語言中的Goroutine介紹與使用

前言

基礎概念的部份到此結束,接下來就比較偏向講解語言特色以及Package的使用與概念,今天的主題是Goroutine,是Go語言的並發處理的核心機制。因為我是第一次接觸這個概念,所以可能不會講得很深入,但我會盡量讓大家了解這個概念。

介紹

Go語言以其內建的並發處理能力著稱,其中最具代表性的功能就是Goroutine。
Goroutine是Go語言實現並發處理的核心機制,本質上是一個輕量級的執行緒(Thread)。由Runtime管理,可以在一個OS執行緒上同時運行多個Goroutine,而不需要額外的程式碼來管理。與傳統的執行緒相比,Goroutine的優勢在於其低成本的創建和管理,以及自動伸縮的stack大小(從2KB開始,最大可達1GB)使得資源消耗更具彈性。

以Java 8為例,執行一個Thread 預設需要分配1MB 記憶體,而Golang只需要2kB 範例程式

除此之外,你可以把任何函數都變成Goroutine來執行,只需要在呼叫函數前加上 go 關鍵字即可。這樣就可以讓函數在背景執行,不會阻塞主程式的執行。(類似於你在Linux shell中透過&符號讓指令在背景執行)

使用方式

package main

import (
	"fmt"
	"time"
)

const (
	_ = 2 << (10 * iota)
	GiB
)

func sayHelloWithSize(size int) {
	fmt.Println("Hello, Goroutine!", size)
}

func main() {
	go sayHelloWithSize(GiB)
	fmt.Println("Gonna Say~~ GoodBye")
}

Image
怎麼沒有Print出結果?
Image

以我們的程式來說,造成這個bug的原因其實是因為主程式在啟動Goroutine後就立即結束了,而Goroutine並不會阻止主程式的結束。而是跟著主程式一起隨風而去。因此為了讓主程式等待Goroutine執行完畢,最簡單的方式是使用time.Sleep()函數來暫停主程式的執行,讓Goroutine有足夠的時間執行。

package main

import (
    "fmt"
    "time"
)

const (
    _ = 2 << (10 * iota)
    KiB
)

func sayHelloWithSize(size int) {
    fmt.Println("Hello, Goroutine!", size)
}

func main() {
    go sayHelloWithSize(KiB)


    time.Sleep(2 * time.Second)
    fmt.Println("Gonna Say~~ GoodBye")
}

使用匿名函數作為Goroutine

有時候我們想要在程式中即時定義Goroutine,但又不想額外定義函數。在這種情況下,可以透過go func() { ... }()的方式來執行匿名函數。

package main

import (
    "fmt"
    "time"
)

func main() {
    go func() {
        fmt.Println("Hello from anonymous Goroutine!")
    }()

    time.Sleep(1 * time.Second)
    fmt.Println("Main function finished.")
}

這段程式碼直接將匿名函數作為Goroutine執行,這樣可以避免定義過多的小函數。

Goroutine與多個任務的並發執行

你也可以在同一個程式中同時執行多個Goroutine以提昇效率
注意: 最多不可超過1048576個平行運算同時執行

package main

import (
    "fmt"
    "time"
)

func main() {
    for i := 0; i < (1 << 16); i++ {
        go func(i int) {
            fmt.Println("Hello from anonymous Goroutine!", i)
        }(i)
    }
    time.sleep(4 * time.Second)
    fmt.Println("Gonna Say~~ GoodBye")
}

那麼今天的文章就到這告一段落,如果我的文章有任何地方有錯誤請在留言區反應
明天將會介紹Go語言的Channel介紹與使用
time

REF


上一篇
Day14. 指標(pointer)的基本概念與操作
下一篇
Go語言中的Channel介紹與使用
系列文
可以Go一輩子嗎?31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言