I’m writing a web server to handle websockets in Go, so, I have the following code:
func StartComunication(
ctx context.Context,
userID string,
connectionRepo ports.ConnectionRepository,
) {
ctx, cancel := context.WithCancel(ctx)
redisClient := redis.GetRedisClient()
sub := redisClient.Subscribe(ctx, userID)
ch := sub.Channel()
defer func() {
connectionRepo.Close()
sub.Close()
cancel()
}()
go func() {
defer cancel()
for {
_, message, err := connectionRepo.Read()
if err != nil {
config.GetLogger().Error().Err(err).Msg("Error reading message")
return
}
fmt.Println("Message received: ", string(message))
}
}()
ticker := time.NewTicker(5 * time.Second)
for {
select {
case <-ctx.Done():
return
case msg := <-ch:
if err := connectionRepo.Write(websocket.TextMessage, []byte(msg.Payload)); err != nil {
config.GetLogger().Error().Err(err).Msg("Error writing message")
return
}
case <-ticker.C:
if err := connectionRepo.Write(websocket.PingMessage, nil); err != nil {
config.GetLogger().Error().Err(err).Msg("Error writing ping message")
return
}
}
}
}
It is clear to me that if there is any error in the goroutine it is launched and is executing
_, message, err := connectionRepo.Read()...
Due to the defer cancel() the main goroutine will also die.
What I’m not sure is what happens when the error occurs in this section:
ticker := time.NewTicker(5 * time.Second)
for {
select {
case <-ctx.Done():
return
case msg := <-ch:
if err := connectionRepo.Write(websocket.TextMessage, []byte(msg.Payload)); err != nil {
config.GetLogger().Error().Err(err).Msg("Error writing message")
return
}
case <-ticker.C:
if err := connectionRepo.Write(websocket.PingMessage, nil); err != nil {
config.GetLogger().Error().Err(err).Msg("Error writing ping message")
return
}
}
}
What will happen to the child goroutine? Does it stay active? How should I handle this?