【问题标题】:Need understanding of goroutines [duplicate]需要了解 goroutines [重复]
【发布时间】:2017-03-06 23:27:40
【问题描述】:

我是 Go 语言编程的新手,并逐步学习它。
在练习的过程中,我发现了 goroutines 的随机行为。
如果我调用 goroutine(睡眠时间为 1 秒的函数),有时它会成功完成,有时它不会:

package main

import (
    "fmt"
    "time"
)

func t(i int) {
    fmt.Println("In func t")
    time.Sleep(1)
}

func t1(i int) {
    fmt.Println("In func t1")
    time.Sleep(1)
}

func main() {
    fmt.Println("Hello Good Morning")
    go t(1)
    t1(2)
    time.Sleep(5)
    fmt.Println("End of func main")
}

O/p 1:

  Hello Good Morning
  In func t1
  In func t
  End of func main

O/p 2:

  Hello Good Morning
  In func t1
  End of func main

谁能解释一下为什么 goroutine 不能保证 goroutine 函数调用的执行。

【问题讨论】:

    标签: go goroutine


    【解决方案1】:

    Program execution

    当函数main返回时,程序退出。它不等待 供其他(非主)goroutine 完成。

    1-main也是goroutine,需要等待其他goroutine完成,可以使用

    time.Sleep(5 * time.Second)
    

    等待 5 秒,在 The Go Playground 上尝试:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func t(i int) {
        fmt.Println("In func t")
        time.Sleep(1 * time.Second)
    }
    
    func t1(i int) {
        fmt.Println("In func t1")
        time.Sleep(1 * time.Second)
    }
    
    func main() {
        fmt.Println("Hello Good Morning")
        go t(1)
        t1(2)
        time.Sleep(5 * time.Second)
        fmt.Println("End of func main")
    }
    

    输出:

    Hello Good Morning
    In func t1
    In func t
    End of func main
    

    并查看文档:

    // Sleep pauses the current goroutine for at least the duration d.
    // A negative or zero duration causes Sleep to return immediately.
    func Sleep(d Duration)
    

    2- 您可以使用sync.WaitGroup 等待其他goroutine,在The Go Playground 上试试:

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    var w sync.WaitGroup
    
    func say(s string) {
        for i := 0; i < 2; i++ {
            time.Sleep(100 * time.Millisecond)
            fmt.Println(s)
        }
        w.Done()
    }
    
    func main() {
        w.Add(1)
        go say("A")
    
        w.Add(1)
        say("B")
    
        w.Wait()
    }
    

    输出:

    B
    A
    A
    B
    

    【讨论】:

    • 感谢您的详细解释。
    【解决方案2】:

    两件事:

    1. 如果您从main 返回而没有明确等待您的 goroutine 完成,不能保证它会在之前完成 程序退出。
    2. time.Sleep()的参数类型为time.Duration, 单位是纳秒。因为你几乎没有延迟 总而言之,您的结果是随机的也就不足为奇了。如果你睡觉 在main 中的更长时间,您应该同时看到 打印的行数(尽管不能保证)。

    如果您需要等待 goroutine 完成,有多种方法可以做到这一点(例如,通道和 sync.WaitGroup)。

    您可能需要查看A Tour of Go 和/或查看Effective Go

    【讨论】:

    • 感谢您的解释。
    猜你喜欢
    • 1970-01-01
    • 2015-01-12
    • 1970-01-01
    • 2015-11-02
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多