首頁 > 後端開發 > Golang > 主體

為什麼在 Go 中共享變數會根據匿名函數中的範圍導致不同的輸出?

Barbara Streisand
發布: 2024-11-07 02:40:02
原創
551 人瀏覽過

Why does sharing variables in Go lead to different outputs depending on their scope within anonymous functions?

Go 中共享變數:了解兩種情況的區別

在Go 中,goroutines 是輕量級的並發任務,可以共享記憶體並使用以下方式進行通訊管道。 Goroutines 之間的變數共享需要小心處理,以避免資料競爭問題。

考慮以下Go 程式:

<code class="go">package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)

        x := i

        go func() {
            defer wg.Done()
            fmt.Println(x)
        }()

    }

    wg.Wait()
    fmt.Println("Done")
}</code>
登入後複製

執行時,程式會列印預期的輸出:

4
0
1
3
2
登入後複製

在這種情況下,每個goroutine 都有自己的變數x 副本,該副本在建立goroutine 時使用i 的當前值進行初始化。這是因為 x 是在匿名函數中聲明的,並且其範圍僅限於該函數。

現在,考慮對程式進行輕微修改:

<code class="go">package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)

        go func() {
            defer wg.Done()
            fmt.Println(i)
        }()

    }

    wg.Wait()
    fmt.Println("Done")
}</code>
登入後複製

這次,輸出變成:

5
5
5
5
5
登入後複製

解釋在於變數i 在goroutine 中使用的方式。由於 i 是在匿名函數外部聲明的,因此它在所有 goroutine 之間共用。在這種情況下,當每個 goroutine 執行 fmt.Println(i) 時,它會列印 i 的最終值,即 5。

為了驗證這一點,我們可以在其中添加 x 和 i 的記憶體位址的列印goroutine。輸出顯示x 對於每個goroutine 有不同的位址,而i 對於所有goroutine 有相同的位址:

0xc0420301e0
0xc0420301f8
0xc0420301e8
0xc0420301f0
0xc042030200
0xc042030208
登入後複製

綜上所述,兩種情況之間變數共享的差異源自於變數的範圍在匿名函數中聲明。當一個變數在匿名函數中宣告時,它對於該 goroutine 是私有的。另一方面,在匿名函數外部宣告的變數在所有 goroutine 之間共用。

以上是為什麼在 Go 中共享變數會根據匿名函數中的範圍導致不同的輸出?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!