Created
July 25, 2025 12:19
-
-
Save lalizita/0f53cf9b90d8304f054ecce713a5c3eb to your computer and use it in GitHub Desktop.
Handling with connection errors in goroutines
This file contains hidden or 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" | |
"math/rand" | |
"net" | |
"os" | |
"os/signal" | |
"syscall" | |
"time" | |
) | |
func main() { | |
srvRun := true | |
servers := 10 | |
ctx, cancel := context.WithCancel(context.Background()) | |
defer cancel() | |
var errCh = make(chan error, servers) | |
go handleConnectionErrors(ctx, errCh, cancel) | |
go start(ctx, servers, &srvRun, errCh) | |
quit := make(chan os.Signal, 1) | |
signal.Notify(quit, os.Interrupt, syscall.SIGTERM) | |
<-quit | |
srvRun = false | |
fmt.Println("Shutting down gracefully...") | |
} | |
func handleConnectionErrors(ctx context.Context, errCh chan error, cancelFn context.CancelFunc) { | |
for { | |
select { | |
case <-ctx.Done(): | |
fmt.Println("Context cancelled, shutting down error channel goroutine...") | |
return | |
case err := <-errCh: | |
if err != nil { | |
cancelFn() | |
return | |
} | |
} | |
} | |
} | |
func start(ctx context.Context, total int, srvRun *bool, errCh chan error) { | |
for i := 0; i < total; i++ { | |
fmt.Printf("Starting connection %d...\n", i+1) | |
go connect(ctx, srvRun, errCh) | |
} | |
} | |
func connect(ctx context.Context, srvRun *bool, errCh chan error) { | |
for *srvRun { | |
// Simulate connection logic ... | |
select { | |
case <-ctx.Done(): | |
fmt.Println("Context cancelled, stopping connection...") | |
return | |
default: | |
handleConnection(ctx, errCh) | |
} | |
} | |
} | |
func handleConnection(ctx context.Context, errCh chan error) { | |
// Simulate handling connection ... | |
for { | |
select { | |
case <-ctx.Done(): | |
fmt.Println("Context cancelled, stopping connection handling...") | |
return | |
case <-time.After(100 * time.Millisecond): | |
default: | |
if err := receive(); err != nil { | |
// Handle error ... | |
fmt.Printf("Error receiving data: %v\n", err) | |
errCh <- err | |
return | |
} | |
} | |
} | |
} | |
func receive() error { | |
// Simulate receiving data ... | |
time.Sleep(200 * time.Millisecond) | |
r := rand.Intn(20-1) + 1 | |
if r%2 == 0 { | |
// Simulate an error condition | |
return &net.OpError{Op: "receive", Err: errors.New("simulated error")} | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment