Last active
February 22, 2024 18:19
-
-
Save dmh2000/8e2151d6d06ed8817bf9a8a613c65514 to your computer and use it in GitHub Desktop.
Is this idiomatic Go for handling nested goroutines with context
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"errors" | |
"fmt" | |
"time" | |
) | |
/* | |
main -> A | |
-> B | |
*/ | |
// main runs 'A' | |
func A(ctx context.Context, result chan error) { | |
// A must run B first, B has its own timeout | |
y, ycancel := context.WithCancel(ctx) | |
defer ycancel() | |
r := make(chan error, 1) | |
go B(y, r) | |
if err := <-r; err != nil { | |
// B failed, return an error | |
result <- err | |
fmt.Println("B error:", err) | |
return | |
} | |
// Now run the body of A, it also has a timeout | |
x, xcancel := context.WithTimeout(ctx, 3*time.Second) | |
defer xcancel() | |
// then do A operation | |
//for { | |
select { | |
case <-x.Done(): | |
// context timeout | |
fmt.Println("A Done") | |
result <- errors.New("A timeout") | |
return | |
case <-time.After(2 * time.Second): | |
// process | |
fmt.Println("A") | |
result <- nil | |
return | |
} | |
//} | |
} | |
// A runs B | |
func B(ctx context.Context, result chan error) { | |
x, cancel := context.WithTimeout(ctx, 4*time.Second) | |
defer cancel() | |
select { | |
case <-x.Done(): | |
// context timeout | |
fmt.Println("B Done") | |
result <- errors.New("B timeout") | |
return | |
case <-time.After(3 * time.Second): | |
// process | |
fmt.Println("B") | |
result <- nil | |
return | |
} | |
} | |
func main() { | |
result := make(chan error, 1) | |
ctx := context.Background() | |
go A(ctx, result) | |
if err := <-result; err != nil { | |
fmt.Println("main error:", err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment