[Go] http、chunked、切断検知、TimeOut、channelのclose
Push配信するhttpサーバーを目指すサンプル。
盛り込んだ要素は下記の通り。
盛りだくさんだぜ~
盛り込んだ要素は下記の通り。
- httpサーバー
→普通です。すみません。 - Transfer-Encoding: chunked
→しょっぱなにw.WriteHeader(http.StatusOK)、
そして、w.(http.Flusher).Flush() - goroutine&channel
- time.Sleep
→渡す値は、単位を掛ける。 - channelのcloseとその検知方法
→close()は組み込み関数。
そしてchannel受信には2番目の戻り値があることを知れ - timeoutを仕掛ける方法
time.Afterでchannelゲットだぜ - 通信切断の検知方法
→w.(http.CloseNotifier).CloseNotify()でchannelゲットだぜ - 複数channelの同時受信
→selectをforで無限ループだぜ。あとラベル付きbreak。 - ロギング
→log.Println()だぜ。
盛りだくさんだぜ~
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"net/http" | |
"time" | |
) | |
func outln(w http.ResponseWriter, mes string) { | |
w.Write([]byte(mes)) | |
w.Write([]byte("\n")) | |
w.(http.Flusher).Flush() | |
log.Println(mes) | |
} | |
func handler(w http.ResponseWriter, r *http.Request) { | |
// Transfer-Encoding: chunked | |
w.WriteHeader(http.StatusOK) | |
outln(w, "start") | |
// for over | |
times := 5 | |
// for TimeOut | |
//times := 10 | |
// メッセージを送る人 | |
ch := make(chan string) | |
go func() { | |
for i := 0; i < times; i++ { | |
time.Sleep(time.Second * 1) | |
ch <- fmt.Sprintf("hoge:%d", i) | |
} | |
close(ch) | |
}() | |
// 時間制限は10秒 | |
timeout := time.After(time.Second * 10) | |
// 通信切断されたら抜ける | |
closeNotify := w.(http.CloseNotifier).CloseNotify() | |
// 何かしら結果が出るまでループする | |
Loop: | |
for { | |
select { | |
case mes, ok := <-ch: | |
if ok { | |
outln(w, mes) | |
} else { | |
outln(w, "message is over") | |
break Loop | |
} | |
case <-closeNotify: | |
log.Println("session closed") | |
break Loop | |
case <-timeout: | |
outln(w, "process timeout") | |
break Loop | |
} | |
} | |
outln(w, "bye") | |
} | |
func main() { | |
http.HandleFunc("/", handler) | |
http.ListenAndServe(":8085", nil) | |
} |
コメント
コメントを投稿