Getting the goroutine freezing once recieving data from channel

I go have the below code that is working fine, and the goroutine is running 5 times as requested.

package main

import (
	"fmt"
	"log"
	"sync"
	pb "walistner/proto"

	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/peer"
	"google.golang.org/protobuf/types/known/emptypb"
)

// type server pb.StreamServiceServer
type server struct {
	pb.UnimplementedStreamServiceServer
}

func (s server) WaMessageStreame(_ *emptypb.Empty, srv pb.StreamService_WaMessageStreameServer) error {
	if p, ok := peer.FromContext(srv.Context()); ok {
		fmt.Println("Client ip is:", p.Addr.String())
	}
	md := metadata.New(map[string]string{"Content-Type": "text/event-stream", "Connection": "keep-alive"})
	srv.SetHeader(md)
	//use wait group to allow process to be concurrent
	var wg sync.WaitGroup

	for i := 0; i < 5; i++ {

		wg.Add(1)
		go func(count int64) {

			defer wg.Done()
     
			resp := myData

			if err := srv.Send(&resp); err != nil {
				log.Printf("send error %v", err)
			}
			log.Printf("finishing request number : %d", count)
		}(int64(i))
	}

	wg.Wait()
	return nil
}

I wanted to make slight change, so instead of running 5 times only, I want it to run upon recieving input data from channel, so I changed it to be:

	for { // removed the count

		wg.Add(1)
		go func() {

			defer wg.Done()
     
			resp := <- myData  // I changed mydata to be from channel

			if err := srv.Send(&resp); err != nil {
				log.Printf("send error %v", err)
			}
		}()

But with this change I got the app hang/freezed.

What mistake I made?

Looks like you are creating goroutines without limit.
Is what do you want?

Change post title to “Infinite loop runs forever”. The behavior has nothing to do with receiving data from a channel.

I was having 2 mistakes in my code:

  1. I’m listining for the same channel at 2 different places, so the data sometimes is consumed before it reached this channel.

  2. I’m listening to the channel inside the goroutine, while I should be listening to it before the goroutine, but inside the same for loop.

The correct code became:

	var wg sync.WaitGroup

	for {

		resp := <- myData

		wg.Add(1)

		go func() {
			defer wg.Done()

			if err := srv.Send(&resp); err != nil {
				log.Printf("send error %v", err)
			}

		}()
	}

	wg.Wait()

The WaitGroup is pointless because there is no exit from the infinite loop. wg.Wait() will never get called, so the wg.Add and wg.Done don’t make any sense.

1 Like

Thanks for your clarification, appreciated.