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?
This is the connectionRepo.Read() function:
type GorillaClient struct {
httpReq *models.HTTPRequest
conn *websocket.Conn
}
func (c *GorillaClient) Read() (messageType int, content []byte, err error) {
messageType, content, err = c.conn.ReadMessage()
if err != nil {
return 0, nil, err
}
return messageType, content, nil
}
3