Data race issues while reading data from file and sending it simultaneously

So I am trying to read data from a file and send it immediately the chunk read without waiting the other goroutine to complete file read. I have two function

func ReadFile(stream chan []byte, stop chan bool) {
	file.Lock()
	defer file.Unlock()
	dir, _ := os.Getwd()
	file, _ := os.Open(dir + "/someFile.json")
	chunk := make([]byte, 512*4)
	for {
		bytesRead, err := file.Read(chunk)
		if err == io.EOF {
			break
		}
		if err != nil {
            panic(err)
			break
		}
		stream <- chunk[:bytesRead]
	}

	stop <- true
}

First one is responsible for reading the file and sending data chunks to the “stream” channel received from the other function

func SteamFile() {
	stream := make(chan []byte)
	stop := make(chan bool)

	go ReadFile(stream, stop)

L:
	for {
		select {
		case data := <-stream:
			//want to send data chunk by socket here
			fmt.Println(data)
		case <-stop:
			break L
		}
	}
}

Second function creates 2 channel, sends them to the first function and starts to listen to the channels.
The problem is that sometimes data := <-stream is missing. I do not receive for example the first part of the file but receive all the others. When I run the program with -race flag it tells that there is a data race and two goroutines write to and read from the channel simultaneously. To tell the truth I thought that’s the normal way do use channels but now I see that it brings to even more issues.
Can someone please help me to solve this issue?

1 Like

In ReadFile() you need to allocate a new “chunk” for each read so you don’t then try to overwrite a slice in the channel “stream.”

for {
    chunk := make([]byte, 512*4) 
    bytesRead, err := file.Read(chunk)
    ...
}
2 Likes

As an extension to Charles’ fix, you could also add a second chan []byte that gets passed into ReadFile so that SteamFile could send data back into when it’s finished so that ReadFile doesn’t need to keep allocating new byte slices.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.