In Go, how do I close a long read?

It seems impossible to have two-way communication through channels with goroutine that perform file operations, unless you block the channel's communication with file operations. How can I get around the limitations that this imposes?

Another way to tell this question ...

If I have a loop similar to the next run in goroutine, how can I tell it to close the connection and exit without blocking on the next Read?

func readLines(response *http.Response, outgoing chan string) error {
    defer response.Body.Close()
    reader := bufio.NewReader(response.Body)

    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            return err
        }
        outgoing <- line
    }
}

It is impossible to read it from a channel that tells it when to close it, because it blocks reading on the network (in my case, this can take several hours).

It doesn't seem safe to just call Close () due to goroutine, as the Read / Close methods are not completely thread safe.

response.Body, / , , , .

+4
1

, io.ReadCloser Read Close, Close .

, net/http Transport, . .

, Transport CancelRequest.

, , close :

func readLines(response *http.Response, outgoing chan string, done chan struct{}) error {
    cancel := make(chan struct{})
    go func() {
       select {
       case <-done:
          response.Body.Close()
       case <-cancel:
          return
    }()

    defer response.Body.Close()
    defer close(cancel) // ensure that goroutine exits

    reader := bufio.NewReader(response.Body)
    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            return err
        }
        outgoing <- line
    }
}

() goroutine .

+4

All Articles