go - 奇怪的协程行为

标签 go goroutine

如有错误请指正。据我所知,goroutine 的工作原理与线程大致相似。所以如果我用不同的参数生成相同的函数,并以 go 为前缀。它应该工作得很好吗?

package main

import "fmt"


func f(from string) {
    for i := 0; i < 3; i++ {
        fmt.Println(from, ":", i)
    }
}

func main() {
    go f("direct")
    go f("redirect")
    //var input string
    //fmt.Scanln(&input)

}

实际输出:

rahul@g3ck0:~/programs/go$ go run goroutine.go 
rahul@g3ck0:~/programs/go$ 

我只是得到提示。

预期输出:

direct : 0
direct : 1
direct : 2
redirect : 0
redirect : 1
redirect : 2

不一定是同一个顺序。
无法理解这种奇怪的行为。我错过了什么吗?

编辑:添加 Scan 语句可以解决它。但是有更好的方法吗?

最佳答案

当 main 退出时,无论其他 goroutines 的状态如何,程序都会终止。您可以通过在主函数末尾添加 select{} 来测试它。这将导致 main 永远不会退出,您将看到其他 goroutines 运行。

如果你希望你的程序在两个 goroutines 完成时干净地退出(没有死锁),你需要使用类似 channel 或 sync.Waitgroup 的东西来协调主要结束时一切都完成。

使用 sync.Waitgroup 的例子:

package main

import (
    "fmt"
    "sync"
)

func f(from string, wg *sync.WaitGroup) {
    for i := 0; i < 3; i++ {
        fmt.Println(from, ":", i)
    }

    wg.Done()
}

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(2)

    go f("direct", wg)
    go f("redirect", wg)

    wg.Wait()
}

使用 channel 的例子:

package main

import (
    "fmt"
)

func f(from string, ch chan<- bool) {
    for i := 0; i < 3; i++ {
        fmt.Println(from, ":", i)
    }

    ch <- true
}

func main() {
    ch := make(chan bool)

    go f("direct", ch)
    go f("redirect", ch)

    <-ch
    <-ch
}

关于go - 奇怪的协程行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17904882/

相关文章:

golang x509.MarshalPKIXPublicKey 与 x509.MarshalPKCS1PublicKey()

algorithm - 如何将 CLI 客户端实现到 golang 守护进程?

cryptography - Golang 使用 ecdsa 和来自 SHA224 摘要的私钥进行签名

go - 如何修复 Mac 上的 dep ensure 错误 'cannot stat file'?

go - 为什么不能通过同时计算 slice 的不同部分来加速程序?

design-patterns - Go - 为什么调度 goroutine background workers 也需要自己的 goroutine?

go - 在没有接收方的情况下,是否可以保留数据打开的缓冲 channel ?

pointers - 在接收器方法中分配给 nil 指针

go - conn.Read 在通过其他 go 例程关闭 conn 时进入无限循环

Golang 工作池实现意外工作