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()移到函数调用后即可。在这种情况下,不需要使用延迟。可能重复