goroutine没有输出

goroutine没有输出,go,concurrency,goroutine,Go,Concurrency,Goroutine,当SayHello()按预期执行时,goroutine不会打印任何内容 package main import "fmt" func SayHello() { for i := 0; i < 10 ; i++ { fmt.Print(i, " ") } } func main() { SayHello() go SayHello() } 主程序包 输入“fmt” func SayHello(){ 对于i:=0;i

SayHello()
按预期执行时,goroutine不会打印任何内容

package main

import "fmt"

func SayHello() {
    for i := 0; i < 10 ; i++ {
        fmt.Print(i, " ")
    }
}

func main() {
    SayHello()
    go SayHello()
}
主程序包
输入“fmt”
func SayHello(){
对于i:=0;i<10;i++{
格式打印(i,“”)
}
}
func main(){
你好
去打招呼
}
main()
函数结束时,程序也会结束。它不会等待其他goroutine完成

引述:

程序执行首先初始化主包,然后调用函数
main
。当函数调用返回时,程序退出。它不会等待其他(非
main
)goroutine完成

有关更多详细信息,请参阅

您必须告诉您的
main()
函数等待作为goroutine启动的
SayHello()
函数完成。您可以将它们与通道同步,例如:

func SayHello(done chan int) {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
    if done != nil {
        done <- 0 // Signal that we're done
    }
}

func main() {
    SayHello(nil) // Passing nil: we don't want notification here
    done := make(chan int)
    go SayHello(done)
    <-done // Wait until done signal arrives
}
package main

import (
    "fmt"
    "runtime"
    "time"
)

func f() {
    for i := 0; ; i++ {
        fmt.Println(i)
        time.Sleep(10 * time.Millisecond)
    }
}

func main() {
    go f()
    runtime.Goexit()
}
package main

import (
    "fmt"
    "os"
    "runtime"
    "time"
)

func f() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
        time.Sleep(10 * time.Millisecond)
    }
    os.Exit(0)
}

func main() {
    go f()
    runtime.Goexit()
}
其次,您必须首先以goroutine的形式启动
SayHello()
,因为当前代码首先在主goroutine中执行
SayHello()
,并且仅在完成后才启动另一个goroutine:

runtime.GOMAXPROCS(2)
done := make(chan struct{})
go SayHello(done) // FIRST START goroutine
SayHello(nil) // And then call SayHello() in the main goroutine
<-done // Wait for completion
runtime.GOMAXPROCS(2)
完成:=make(chan结构{})
go SayHello(完成)//第一次开始goroutine
SayHello(nil)//然后在主goroutine中调用SayHello()
或者(根据icza的回答),您可以使用
sync
包中的
WaitGroup
和匿名功能来避免更改原始
SayHello

package main

import (
    "fmt"
    "sync"
)

func SayHello() {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
}

func main() {
    SayHello()

    var wg sync.WaitGroup
    wg.Add(1)

    go func() {
        defer wg.Done()
        SayHello()
    }()

    wg.Wait()
}
主程序包
进口(
“fmt”
“同步”
)
func SayHello(){
对于i:=0;i<10;i++{
格式打印(i,“”)
}
}
func main(){
你好
var wg sync.WaitGroup
工作组.添加(1)
go func(){
推迟工作组完成()
你好
}()
wg.Wait()
}
为了同时打印数字,请在单独的例程中运行每个打印语句,如下所示

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(fnScopeI int) {
            defer wg.Done()

            // next two strings are here just to show routines work simultaneously
            amt := time.Duration(rand.Intn(250))
            time.Sleep(time.Millisecond * amt)

            fmt.Print(fnScopeI, " ")
        }(i)
    }

    wg.Wait()
}
主程序包
进口(
“fmt”
“数学/兰德”
“同步”
“时间”
)
func main(){
var wg sync.WaitGroup
对于i:=0;i<10;i++{
工作组.添加(1)
go func(fnScopeI int){
推迟工作组完成()
//下面的两个字符串只是为了显示例程同时工作
金额:=持续时间(兰特国际(250))
time.Sleep(time.毫秒*amt)
格式打印(fnScopeI,“”)
}(一)
}
wg.Wait()
}

main
函数返回时,Go程序退出

一个选项是使用类似于
sync.WaitGroup
的东西来等待
main
生成的其他goroutine,然后再从
main
返回

另一个选项是在
main
中调用
runtime.Goexit()。从:

Goexit终止了称之为goroutine的goroutine。没有其他goroutine受到影响。Goexit在终止goroutine之前运行所有延迟调用。因为Goexit不是恐慌,所以这些延迟函数中的任何recover调用都将返回nil

从主goroutine调用Goexit将终止该goroutine,而不返回func main。由于func main尚未返回,程序将继续执行其他goroutine。如果所有其他goroutine退出,程序将崩溃

这允许主goroutine在后台例程继续执行时停止执行。例如:

func SayHello(done chan int) {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
    if done != nil {
        done <- 0 // Signal that we're done
    }
}

func main() {
    SayHello(nil) // Passing nil: we don't want notification here
    done := make(chan int)
    go SayHello(done)
    <-done // Wait until done signal arrives
}
package main

import (
    "fmt"
    "runtime"
    "time"
)

func f() {
    for i := 0; ; i++ {
        fmt.Println(i)
        time.Sleep(10 * time.Millisecond)
    }
}

func main() {
    go f()
    runtime.Goexit()
}
package main

import (
    "fmt"
    "os"
    "runtime"
    "time"
)

func f() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
        time.Sleep(10 * time.Millisecond)
    }
    os.Exit(0)
}

func main() {
    go f()
    runtime.Goexit()
}
这比在主函数中永远阻塞更干净,特别是对于无限的程序。一个缺点是,如果进程的所有goroutine返回或退出(包括主goroutine),Go会将其检测为错误和恐慌:

fatal error: no goroutines (main called runtime.Goexit) - deadlock!
为了避免这种情况,至少必须有一个goroutine在返回之前调用
os.Exit
。调用
os.Exit(0)
会立即终止程序,并表明它这样做没有错误。例如:

func SayHello(done chan int) {
    for i := 0; i < 10; i++ {
        fmt.Print(i, " ")
    }
    if done != nil {
        done <- 0 // Signal that we're done
    }
}

func main() {
    SayHello(nil) // Passing nil: we don't want notification here
    done := make(chan int)
    go SayHello(done)
    <-done // Wait until done signal arrives
}
package main

import (
    "fmt"
    "runtime"
    "time"
)

func f() {
    for i := 0; ; i++ {
        fmt.Println(i)
        time.Sleep(10 * time.Millisecond)
    }
}

func main() {
    go f()
    runtime.Goexit()
}
package main

import (
    "fmt"
    "os"
    "runtime"
    "time"
)

func f() {
    for i := 0; i < 10; i++ {
        fmt.Println(i)
        time.Sleep(10 * time.Millisecond)
    }
    os.Exit(0)
}

func main() {
    go f()
    runtime.Goexit()
}
主程序包
进口(
“fmt”
“操作系统”
“运行时”
“时间”
)
func f(){
对于i:=0;i<10;i++{
fmt.Println(一)
时间。睡眠(10*时间。毫秒)
}
操作系统退出(0)
}
func main(){
go f()
runtime.Goexit()
}

是的,我刚看懂你的编辑:永远发送给
nil
频道块,永远接收
nil
频道块。@dinespanchananam你所说的“无序”时尚是什么意思?您希望看到2个运行的
SayHello()
函数中随机出现混合数?@dinespanchananam我编辑了我的答案以解决这个问题。但简言之,你无法保证观察到这种行为(即使你观察到,也不会是确定性的)。@DineshPanchananam你想在单独的例程中打印每个数字吗?不,我希望是“平行的”“。但我认为我错了。@DineshPanchananam检查回答的第二部分。另外,当只有一个函数调用时,请不要使用延迟(第一个代码示例)-只需将wg.Done()移到函数调用后即可。在这种情况下,不需要使用延迟。可能重复