6
package main

import(
    "fmt"
    "time"
)

func main(){
    fmt.Println("1")
    defer fmt.Println("-1")
    go func() { 
        fmt.Println("2")
        defer fmt.Println("-2")
        time.Sleep(9 * time.Second)
    }()
    time.Sleep(1 * time.Second)
    fmt.Println("3")
}

出力を生成します: 1 2 3 -1 しかし、ゴルーチンの defer が呼び出されて生成されると思っていたでしょう: 1 2 3 -2 -1

私の実際のコードでは、ゴルーチンが websocket でブロックされています...シャットダウン信号を送信できると思いますが、複数のオブジェクトを待機するようなことを行う方法をまだ理解していません(実際にできる場合) goで行われます)。私は現在、延期された -2 をメインスコープに引き上げることで問題を解決しています。

私が正しくやっていない配置を延期するためのトリックはありますか?

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

4

4 に答える 4

6

(コメントするのに十分な担当者がいませんか?)

はい、問題はゴルーチンのスケジューリングにあり、プラットフォームに依存します。関数の最後で runtime.Gosched を goroutine と共に使用して、ある程度の cputime を取得できるようにします。現在、x86_64 Linux では、以下のコードは "3" を生成しますが、Gosched がないと "1" を生成します:

いいえ、それは問題ではなく、(実装の詳細を介して) 偶然に解決するだけです。メインスコープが終了したときに呼び出されないゴルーチンの deferですでに示唆されているように。あなたのコードは際どいので、ゴルーチンを明示的に同期する必要があります。最も簡単な方法は、チャネルまたは待機グループhttp://golang.org/pkg/sync/#WaitGroupを使用することです。どちらのオプションがより適切かは、何をしているかによって異なります。なんらかの結果を待つことだけが必要な場合は、ゴルーチンにその結果をチャネルに送信させ、単にそれを待ちます。いくつかのゴルーチンを待ちたいだけの場合は、waitgroup を使用してください。

于 2013-11-03T08:56:04.987 に答える
2

プロセスが終了しているため、内部関数は終了します。メインの最後でスリープしてみてください:

func main(){
    fmt.Println("1")
    defer fmt.Println("-1")
    go func() { 
        fmt.Println("2")
        defer fmt.Println("-2")
        time.Sleep(9 * time.Second)
    }()
    time.Sleep(1 * time.Second)
    fmt.Println("3")
    time.Sleep(9 * time.Second)
}

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

編集:コメントで述べたように、これは一般的に正しいアプローチではありません。ゴルーチンを明示的に待機する必要があります。

于 2013-10-27T02:26:39.163 に答える
1

はい、問題はゴルーチン スケジューリングにあり、プラットフォームに依存します。関数の最後でruntime.Goschedを goroutine と共に使用して、ある程度の cputime を取得できるようにします。現在、x86_64 Linux では、以下のコードは "3" を生成しますが、Gosched がないと "1" を生成します:

q = 1
go func() { 
    q = 2
    defer func() { q = 3 }()
}()
runtime.Gosched()
fmt.Println(q)

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

于 2013-10-27T19:53:37.490 に答える
1

WaitGroupは、問題の解決に役立ちます。

package main

import(
    "fmt"
    "sync"
    "time"
)

func main(){
    fmt.Println("-start main-")
    defer fmt.Println("-defer main-")

    wg := sync.WaitGroup{}
    wg.Add(1)

    go func() { 
        fmt.Println("-start goroutine-")
        defer fmt.Println("-defer goroutine-")

        time.Sleep(2 * time.Second)
        wg.Done() 
    }()

    fmt.Println("-end main-")
    wg.Wait()
}

版画:

-start main-
-end main-
-start goroutine-
-defer goroutine-
-defer main-

https://play.golang.org/p/ycmPJJ6pvC

于 2016-10-18T12:00:12.027 に答える