簡體   English   中英

鏈接函數如何作為goroutines執行?

[英]How do chained functions get executed as goroutines?

鑒於這個游樂場

package main

import "fmt"

func main() {
    go oneFunc().anotherFunc()
}

func oneFunc() something {
    fmt.Println("oneFunc")
    return something{}
}

type something struct{}

func (s something) anotherFunc() {
    fmt.Println("anotherFunc")
}

為什么輸出:

oneFunc

並且“anotherFunc”從未打印過?

anotherFunc不執行,直到oneFunc返回一個值。 因此,程序在anotherFunc能夠運行之前退出。 您需要等待anotherFuncmain退出之前運行。

您可以通過Go頻道完成此操作。 例如:

http://play.golang.org/p/dWoLB9afSj

package main

import "fmt"

func main() {
    ch := make(chan int)
    go oneFunc(ch).anotherFunc()
    fmt.Println("Waiting...")
    <-ch
    fmt.Println("Done.")
}

func oneFunc(ch chan int) something {
    fmt.Println("oneFunc")
    return something{ch}
}

type something struct{
    ch chan int
}

func (s something) anotherFunc() {
    fmt.Println("anotherFunc")
    s.ch <- 1
}

評估go關鍵字后面的表達式,然后同時執行該表達式的函數值。

因此,在您的示例中, oneFunc() ,因此oneFunc輸出,並且返回實例上的方法anotherFunc被並發調用。 但是,您的程序會在goroutine運行之前終止,這就是您沒有看到打印了anotherFunc

解決方案:使用sync.WaitGroup或通道進行同步。

要實際(憑經驗)驗證您的go調用同時執行anotherFunc不是 oneFunc您可以在每個函數中打印堆棧並比較輸出。 示例( 正在播放 ):

var wg = sync.WaitGroup{}

func main() {
    wg.Add(1)
    go oneFunc().anotherFunc()
    wg.Wait()
}

func oneFunc() something {
    fmt.Println("oneFunc")

    buf := make([]byte, 4096)
    runtime.Stack(buf, false)
    fmt.Println("Stack of oneFunc:", string(buf))

    return something{}
}

type something struct{}

func (s something) anotherFunc() {
    defer wg.Done()

    buf := make([]byte, 4096)
    runtime.Stack(buf, false)
    fmt.Println("Stack of anotherFunc:", string(buf))

    fmt.Println("anotherFunc")
}

你會看到這樣的事情:

oneFunc
Stack of oneFunc: goroutine 1 [running]:
main.oneFunc()
    /tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:20 +0x118
main.main()
    /tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:11 +0x50

Stack of anotherFunc: goroutine 2 [running]:
main.something.anotherFunc()
    /tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:32 +0xb2
created by main.main
    /tmpfs/gosandbox-342f581d_b6e8aa8b_334a0f88_c8221b7e_20882985/prog.go:11 +0x69

anotherFunc

堆棧跟蹤甚至告訴您這兩個函數在不同的goroutine中運行,不需要比較方法調用。

我喜歡它的方式就是這樣, go -like defer - 在行上消耗最后一次調用或對括號,並且將不按順序調用該函數。 之前的每次調用都是同步的。

go使得調用並發。 defer延遲調用,直到當前函數返回。

Effective Godefer部分中有一個非常好的例子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM