请求取消或超时时如何从http处理程序返回

I'm doing sse, the important code is:

   var clientes=new(sync.Map)
    type canalesStruct struct{
        sender chan []byte
        close chan bool
    }
    func (broker *brokerStruct) ServeHTTP(w http.ResponseWriter, r *http.Request) {
flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")
    var ID string
    //Get the ID somehow
    canales:=new(canalesStruct)
    canales.sender=make(chan []byte)
    canales.close=make(chan bool)
    clientes.store(ID,canales)
    notify := w.(http.CloseNotifier).CloseNotify()
    defer func() {
        clientes.Delete(ID)
    }()
    for {
         select {
            case <-notify:
                return
            case <-canales.close:
                return  
            case data:= <-canales.sender:
                fmt.Fprintf(w, "data: %s

",data)
                flusher.Flush()
            }
      }
}

    func sendDataToChanelID(ID string,data []byte){
        canalesRaw,_:=clientes.Load(ID)
        canales,_:=canalRaw(*canalesStruct)
        canales.sender <-data
    }

So I have two question over there:

  1. If connection drops WHILE is being receiving data, will fmt.Fprintf continue waiting endless or it will return immediately?
  2. In case it returns immediately there is not problem, but in case it continues waiting how can I wrapp "fmt.Fprintf" in order to return if timeout exceed?

A simple way to return different values depending on timing is to wait on a channel.

func F() int {
    // channel to receive info
    c := make(chan int)
    // start timeout goroutine
    go func() {
        time.Sleep(TIMEOUT)
        c <- -1
    }()
    // start work goroutine
    go func() {
        c <- GetValue()
    }()
    // receive value
    x := <-c
    // start goroutine to discard late value
    go func() {
        _ = <-c
    }()
    // return received value
    return x
}

So, the two goroutines are racing each other. If the timeout gets there first, the value is -1.

I beleive a call to fmt.Fprintf() will just fail when the underlying HTTP request closes.

"To fail" here means it will return a non-nil error.

So, to properly handle the case of HTTP request being shut down, check the error return of fmt.Fprintf(), like in

_, err := fmt.Fprintf(w, ...)
if err != nil {
   // We have failed to write to the underlying connection
}