package main
import (
"fmt"
"log"
"net/http"
"time"
)
var ch chan bool
func testTimer1() {
go func() {
log.Println("test timer 1")
ch <- true
}()
}
func timer1() {
timer1 := time.NewTicker(2 * time.Second)
select {
case <-timer1.C:
testTimer1()
}
}
func myhandler(w http.ResponseWriter, r *http.Request) {
for {
go timer1()
a := <-ch
log.Println("get a: ", a)
fmt.Fprintf(w, "hello world!!!!", a)
}
log.Println("test for break")
}
func main() {
ch = make(chan bool)
http.HandleFunc("/", myhandler)
http.ListenAndServe(":8080", nil)
}
I wrote the above code, put a channel into "myhandler", channel will be given a bool data when the
timer task executed.
then I get the data from channel and write "hello world" into http writer
but I found the client couldn't receive the "hello world", the writer has been blocked!!!!!
Any one knows about this?
looks the running pic on my cmd: enter image description here
The for
loop is an infinite loop so printing to the ResponseWriter
is not "scheduled" to happen. If you want a comet-like approack (or long-polling URL) you may want to try this method.
There's also a leak of tickers in timer1()
. According to the Go Docs:
Stop the ticker to release associated resources.
You're always creating a new ticker every time you call go timer1()
and the ticker is never closed so every new ticker just adds-up.
Avoid buffering
Use curl with --no-buffer
set
curl http://localhost:8080 --no-buffer
Flush after every fmt.Fprint
w.(http.Flusher).Flush()
The biggest problem when implementing HTTP streaming is understanding the effect of buffering. Buffering is the practice of accumulating reads or writes into a temporarily fixed memory space. The advantages of buffering include reducing read or write call overhead. For example, instead of writing 1KB 4096 times, you can just write 4096KB at once. This means your program can create a write buffer holding 4096KB of temporary data (which can be aligned to the disk block size), and once the space limit is reached, the buffer is flushed to disk.
Here the above mentioned HTTP
component include two components Server
(go server) and Client(Curl
).Each one of these components can possess adjustable and varied buffering styles and limits.
An unrelated issue, n the program given it has one more problem ie, not stopping timer always stop the ticker to release associated resources.
Here is an implementation with some corrections
Code
package main
import (
"fmt"
"log"
"net/http"
"time"
)
var ch chan bool
func testTimer1() {
go func() {
log.Println("test timer 1")
ch <- true
}()
}
func timer1() {
timer1 := time.NewTicker(2 * time.Second)
defer timer1.Stop()
<-timer1.C
testTimer1()
}
func myhandler(w http.ResponseWriter, r *http.Request) {
for {
go timer1()
a := <-ch
log.Println("get a: ", a)
fmt.Fprintf(w, "hello world!!!! - %v", a)
w.(http.Flusher).Flush()
}
}
func main() {
ch = make(chan bool)
http.HandleFunc("/", myhandler)
http.ListenAndServe(":8080", nil)
}
curl http://localhost:8080 --no-buffer