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:
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
}