英文:
What will happen to a golang blocking function if the invoker of this function has done?
问题
我想知道如果interruptable_call
是不可中断的,并且在上下文完成后返回,会发生什么。调用堆栈已经被销毁了,返回操作会执行什么?当一个case返回而另一个case仍在运行时,select
会如何执行?那个case函数调用会被终止吗?以什么方式?
package main
import (
"context"
"fmt"
"time"
)
func interruptable_call() <-chan time.Time {
return time.After(1 * time.Second)
}
func A(ctx context.Context) int {
for {
select {
case <-ctx.Done():
fmt.Println("func done")
return 1
case <-interruptable_call():
fmt.Println("blocking")
}
}
return 0
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
fmt.Println("go A")
go A(ctx)
fmt.Println("go A done")
select {
case <-ctx.Done():
fmt.Println("main done")
break
}
}
以下是翻译好的代码部分:
package main
import (
"context"
"fmt"
"time"
)
func interruptable_call() <-chan time.Time {
return time.After(1 * time.Second)
}
func A(ctx context.Context) int {
for {
select {
case <-ctx.Done():
fmt.Println("函数完成")
return 1
case <-interruptable_call():
fmt.Println("阻塞中")
}
}
return 0
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
fmt.Println("启动 A")
go A(ctx)
fmt.Println("A 完成")
select {
case <-ctx.Done():
fmt.Println("主函数完成")
break
}
}
英文:
I wonder what will happen if the interruptable_call is uninterruptable and return after the context is done. The call stack would have been already destroyed. What would the return action perform? How would select
perform when one case return while another case is still running. Would that case function call be terminated? in what way?
package main
import (
"context"
"fmt"
"time"
)
func interruptable_call() <-chan time.Time {
return time.After(1 * time.Second)
}
func A(ctx context.Context) int {
for {
select {
case <-ctx.Done():
fmt.Println("func done")
return 1
case <-interruptable_call():
fmt.Println("blocking")
}
}
return 0
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
fmt.Println("go A")
go A(ctx)
fmt.Println("go A done")
select {
case <-ctx.Done():
fmt.Println("main done")
break
}
}
答案1
得分: 1
我不确定你所说的"synchronisation problem"是什么意思,因为这里没有同步。如果你想确保你的生成的goroutine执行了任务,你需要使用通道、等待组或其他方式来同步你的goroutine。
无论goroutine中发生了什么,如果它没有与主goroutine同步,那么在主goroutine退出后它将停止存在。
异步调用的函数的返回值对你来说是不可用的。
你可以自己查看阻塞调用的工作原理:
package main
import (
"context"
"fmt"
"time"
)
func interruptable_call(sleep time.Duration) <-chan time.Time {
fmt.Println("sleeping for ", sleep*time.Second)
time.Sleep(sleep * time.Second)
return time.After(0 * time.Second)
}
func A(ctx context.Context) int {
for {
select {
case <-ctx.Done():
fmt.Println("func done")
return 1
case <-interruptable_call(2):
fmt.Println("blocking")
case <-interruptable_call(3):
fmt.Println("blocking")
case <-interruptable_call(4):
fmt.Println("blocking")
case <-interruptable_call(5):
fmt.Println("blocking")
}
}
return 0
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
fmt.Println("go A")
go A(ctx)
fmt.Println("go A done")
select {
case <-ctx.Done():
fmt.Println("main done")
break
}
}
希望对你有帮助!
英文:
I am not sure what you mean by "synchronisation problem", since there is no synchronization here.. You need to synchronise your goroutines using channels, waitgroups or any other means if you want to be sure that your spawned goroutines performed their task.
It doesn't really matter what happens in the goroutine - if it's not synchronised with main gouroutine it will cease to exist after main exits.
Return value from function called asynchronously in goroutine won't be available to you anyway.
You can check out how blocking calls work for yourself:
package main
import (
"context"
"fmt"
"time"
)
func interruptable_call(sleep time.Duration) <-chan time.Time {
fmt.Println("sleeping for ", sleep*time.Second)
time.Sleep(sleep * time.Second)
return time.After(0 * time.Second)
}
func A(ctx context.Context) int {
for {
select {
case <-ctx.Done():
fmt.Println("func done")
return 1
case <-interruptable_call(2):
fmt.Println("blocking")
case <-interruptable_call(3):
fmt.Println("blocking")
case <-interruptable_call(4):
fmt.Println("blocking")
case <-interruptable_call(5):
fmt.Println("blocking")
}
}
return 0
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
fmt.Println("go A")
go A(ctx)
fmt.Println("go A done")
select {
case <-ctx.Done():
fmt.Println("main done")
break
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论