Skip to content

Instantly share code, notes, and snippets.

@horpto
Created April 24, 2023 10:19
Show Gist options
  • Save horpto/3c53240d173a126c971a70e730575f53 to your computer and use it in GitHub Desktop.
Save horpto/3c53240d173a126c971a70e730575f53 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"fmt"
"time"
)
// LongProcess refers to a long network request
func LongProcess(ctx context.Context, duration time.Duration, msg string) {
c1 := make(chan string, 1)
go func() {
fmt.Printf("%v started\n", msg)
select {
case <-time.After(duration):
fmt.Printf("%v done\n", msg)
case <-ctx.Done():
fmt.Printf("ctx done for %v\n", msg)
}
c1 <- msg
}()
select {
case m := <-c1:
fmt.Println(m)
case <-ctx.Done():
}
}
// An ShieldCtx is never canceled, has values, and has no deadline.
// it's like asyncio.shield but for go
type ShieldCtx struct {
parent context.Context
}
func (*ShieldCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func (*ShieldCtx) Done() <-chan struct{} {
return nil
}
func (*ShieldCtx) Err() error {
return nil
}
func (ctx *ShieldCtx) Value(key any) any {
return ctx.parent.Value(key)
}
func (e *ShieldCtx) String() string {
return "Shield Context"
}
func WithShield(ctx context.Context) context.Context {
return &ShieldCtx{parent: ctx}
}
func main() {
parent := context.Background()
ctx1, cancel := context.WithTimeout(parent, 2 * time.Second)
defer cancel()
now := time.Now()
ctxShielded := WithShield(ctx1)
LongProcess(ctxShielded, 5*time.Second, "first process")
fmt.Printf("time: %v\n", time.Now().Sub(now))
now = time.Now()
fmt.Printf("time: %v\n", time.Now().Sub(now))
LongProcess(ctxShielded, 5*time.Second, "second process")
fmt.Printf("time: %v\n", time.Now().Sub(now))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment