Gert Cuykens
Gert Cuykens

Reputation: 7175

How to deal with io.EOF in a bytes.Buffer stream?

https://play.golang.org/p/JKXKa7Pvjd

I am trying to figure out how I can test my background function where there can be random io.EOF in a stream using a bytes.Buffer?

Example:

package main

import (
    "fmt"
    "io"
    "bytes"
    "time"
)

func main() {
    buffer := new(bytes.Buffer)
    go background(buffer)
    i := 0
    for i < 5 {
        i++
        fmt.Fprintf(buffer, "%d)teststring\n", i)
        time.Sleep(1 * time.Second) // generates a io.EOF

    }
    time.Sleep(1 * time.Second)
}

func background(r io.Reader) {
    buf := make([]byte, 64)
    for {   
        n, err := r.Read(buf)
        if err != nil {
            fmt.Print(err.Error())
            return // removing `return` will result in race condition
        }
        fmt.Print(string(buf[:n]))
    }
}

The result I am looking for is:

1)teststring
2)teststring
3)teststring
4)teststring
5)teststring

How can I achieve this using time.Sleep(1 * time.Second) to simulate latency?

Upvotes: 4

Views: 3803

Answers (1)

Darigaaz
Darigaaz

Reputation: 1500

Are you sure you want to use bytes.Buffer? It is not a stream and it is not thread safe, thats why you get race condition. Use io.Pipe().

https://play.golang.org/p/c0fLEI350w

package main

import (
    "fmt"
    "io"
    "time"
)

func main() {
    pr, pw := io.Pipe()
    go background(pr)
    i := 0
    for i < 5 {
        i++
        fmt.Fprintf(pw, "%d)teststring\n", i)
        time.Sleep(1 * time.Second)

    }
    time.Sleep(1 * time.Second)
}

func background(r io.Reader) {
    buf := make([]byte, 64)
    for {
        n, err := r.Read(buf)
        if err != nil {
            fmt.Print(err.Error())
            //return
        }
        fmt.Print(string(buf[:n]))
    }
}

Upvotes: 7

Related Questions