当我在函数中添加延迟时,我希望它在函数结束时始终被调用。我注意到当函数超时时它不会发生。
package main
import (
"context"
"fmt"
"time"
)
func service1(ctx context.Context, r *Registry) {
ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
defer func() {
r.Unset("service 1")
}()
r.Set("service 1")
go service2(ctx, r)
select {
case <-ctx.Done():
cancel()
break
}
}
func service2(ctx context.Context, r *Registry) {
defer func() {
r.Unset("service 2")
}()
r.Set("service 2")
time.Sleep(time.Millisecond * 300)
}
type Registry struct {
entries map[string]bool
}
func (r *Registry)Set(key string) {
r.entries[key] = true
}
func (r *Registry)Unset(key string) {
r.entries[key] = false
}
func (r *Registry)Print() {
for key, val := range r.entries {
fmt.Printf("%s -> %v\n", key, val)
}
}
func NewRegistry() *Registry {
r := Registry{}
r.entries = make(map[string]bool)
return &r
}
func main() {
r := NewRegistry()
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*200)
go service1(ctx, r)
// go service3(ctx, r)
select {
case <-ctx.Done():
fmt.Printf("context err: %s\n", ctx.Err())
cancel()
}
r.Print()
}
在上面的示例中,永远不会调用 defer in service2(),这就是输出的原因:
service 1 -> false
service 2 -> true
代替
service 1 -> false
service 2 -> false
我知道超时意味着“停止执行”,但对我来说执行延迟代码是合理的。我找不到对此行为的任何解释。
问题的第二部分 - 如何修改服务或Registry抵抗这种情况?
手掌心
相关分类