『Go言語によるWebアプリケーション開発』学習メモ(1日目)
『Go言語によるWebアプリケーション開発』という本での学習の中で、 学んだことを自分用に整理してメモしていきます。
第1章 WebSocketを使ったチャットアプリケーション
package main import ( "github.com/gorilla/websocket" ) type client struct { socket *websocket.Conn send chan []byte room *room }
Channelは、ゴルーチン間で、データの送受信を行うための機構を構築する Channelはバッファを持つことが出来る
バッファのあるChannelでは、指定された容量分、データを保持できる 送信ゴルーチンでは、容量がいっぱいになるまで、データを送信 受信ゴルーチンでは、バッファが空になるまでデータを受信できる
複数の送受信者が、同時に読み書きすることが出来る
バッファとは 一時的にデータを保存する領域のこと サーバーなどで複数のクライアントからリクエストが来た際に、 同時に処理することはできないため、一時的に保存したりする
c.room.forward <- msg
チャネル演算子で値を送受信することができる
並列処理と並行処理 並列処理:複数のタスクを同時に処理する 並行処理:複数のタスクを短時間で切り替える
チャットルームの作成
type room struct { forward chan []byte join chan *client leave chan *client clients map[*client]bool }
なぜmapを使うのか?
const ( socketBufferSize = 1024 messageBufferSize = 256 ) var upgrader = &websocket.Upgrader{ReadBufferSize: socketBufferSize, WriteBufferSize: socketBufferSize} func (r *room) ServeHTTP(w http.ResponseWriter, req *http.Request) { socket, err := upgrader.Upgrade(w, req, nil) if err != nil { log.Fatal("serveHTTP:", err) return } client := &client{ socket: socket, send: make(chan []byte, messageBufferSize), room: r, } r.join <- client defer func() { r.leave <- client }() go client.write() client.read() }
- ServeHTTP関数で、HTTPリクエストを受け取り、WebSocketの接続にアップグレード
- 成功後、Clientを作成し、チャットルームに追加
- ClientはWebSocketの接続、送信用のチャンネル、チャットルームを保持する
- Clientの終了時に退出
- goroutinueで、読み書きを行い、Clientはメッセージの送受信を同時に行う
websocket
クライアントとサーバー間でのリアルタイム通信を実現する通信プロトコル
ターミナルにログを出す
tracer.go type Tracer interface { Trace(...interface{}) } type tracer struct { out io.Writer } func (t *tracer) Trace(a ...interface{}) { t.out.Write([]byte(fmt.Sprint(a...))) t.out.Write([]byte("\n")) } func New(w io.Writer) Tracer { return &tracer{out: w} }
Tracerインターフェースを定義し、Traceメソッドを定義 New関数で、新しいTracerを作る
trace.go func (t *tracer) Trace(a ...interface{}) { t.out.Write([]byte(fmt.Sprint(a...))) t.out.Write([]byte("\n")) }
a ...interface{} 任意の長さの引数を受け取ることが出来る Writeメソッドは2回呼び出され、1回目は、文字列の出力 2回目は、改行を行っている
room.go type room struct { forward chan []byte join chan *client leave chan *client clients map[*client]bool tracer trace.Tracer }
roomは、Tracerインターフェースを持つ 構造体を定義し、フィールドを作る フィールド経由で、Traceメソッドを呼び出すことが出来る
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 本日はここまでで、また後日続きを行います