チャット部分編オライリーから出版されているGo言語によるWebアプリケーション開発を読みました。1章から3章までがWebsocketを使用したチャットアプリケーション開発となるのですが、その部分を読んだまとめ・感想を書いていきます。www.oreilly.co.jpgithub.comwebサーバ公開の基本アクセスパスと処理を結びつけます。パスは完全一致ではなく前方一致となるため、注意が必要となります。/を登録した場合は/appとアクセスしても関連付けた処理が実行されます。結びつけたあとに、ListenAndServeメソッドを使ってWebサーバを開始します。http.HundleFuncでパスと関数を紐づけるこの後に挙げるhttp.Handleとは違い、Handlerのインターフェースを実装した構造体を用意する必要がありません。その代わり、状態などを持たせることが出来ないため注意です。http.HandleでパスとHandlerを紐づけるHandlerのインターフェースを実装した構造体を用意した上で、http.Handle関数の第二引数に渡してあげる。*http.Request)メソッドのみを持つインターフェースになっている。http.Handle関数にて指定したリクエストパスにマッチするリクエストが来た場合に、ServeHTTPメソッドの中に書いた処理が実行される。下の例は、返却するhtmlファイルに埋め込むデータオブジェクトを作成し、そのデータオブジェクトをコンパイル済のHtmlテンプレートにapplyする処理。初回リクエストが来たときにテンプレートファイルをコンパイルする。初回だけの実行を保証するための実装としては、sync.Onceを使用している。起動時にコンパイルしないこの方法を、遅延初期化として本では取り上げられており、セットアップ処理に時間がかかる場合や利用頻度の低い機能では効果的と説明されています。ファイルが無いなどの状態を検知できないため、template.Mustを使用してグルーバル変数にセットする方法が好まれることもあるとのこと。テンプレートの読込と出力を受け持つ型。テンプレートのコンパイルは一度で良い。複数のgoroutineが呼び出したとしても、引数として渡した関数が一度しか実行されない。data)}template.Mustを使用してグルーバル変数にセットする方法は以下。この方法使用すると、もしエラーがある場合にはpanicを起こし起動しなくなるため、エラーに気づかない事象を避けることができる。"login.html")))以下のコマンドでWebサーバを開始する。err)}HTTP2をつかった通信をしたいのであれば、以下のようになる。err)}実装としては割れるのは、http.HandleFuncを使うかhttp.Handleを使うかというところだと思うが、遅延初期化を使わない場合には、http.HandleFuncで事足りるのではと私は感じている。チャットアプリケーションのモデル化ここでのチャットアプリケーションの要件は、一つの公開されたチャットルームにクライアントは自動的にログインして会話をするというもの。クライアントとの通信を管理するclientとという構造体とクライアントの入退出の管理やメッセージをブロードキャストする役割を持つroomという構造体で構成する。clientClient構造体は、各クライアントごとに必要となるwebsocketのコネクションと他クライアントからのメッセージを格納するチャネルを持つ。ブラウザから送信されるメッセージをRoomに送るためにRoomへの参照を持っている。clientのメソッドは各クライアントに対応するため、ServeHTTPメソッドの中で実行される。他クライアントからのメッセージを格納するチャネルをクライアント側で持つのは、言わずもがなWebsocketに書き出すWriteメソッドをクライアント側で持つため(おそらくsocketのコネクションを他ソースコードに使わせずチャネルでやり取りしたかった)。チャネルが閉じられるまで、チャネルから値を繰り返し受信し続ける。channelがクローズされれば、ループから抜ける。Websocketが閉じられる。c.socket.Close()}roomroom構造体は他のクライアントに転送するためのメッセージを保持するチャネルと入退出を受け取るチャネル、クライアント全体のデータを持つ。外部から利用しやすいように、newRoom()という関数を作る。run()メソッドはgoルーチンでWEBサーバと並列で実行される。チャネルへのメッセージの処理には、selectを使用している。}}Roomでの処理をHTTPハンドラ化HTTPハンドラ化するにあたり、room構造体はServeHTTPメソッドを実装する必要がある。Upgraderメソッドによりhttp通信はWebsocket通信へアップグレードされます。変数socketにwebcsocket通信のコネクションが入ってきます。client.readはソケット通信でエラーになったらbreakし、そのclientをleaveチャンネルに通知する。client.read()}main関数の流れは以下のようになります。認証機能HTTPハンドラのdecoratorパターン認証機能を作るにあたり、/roomにアクセスした際の処理を認証用のHTTPハンドラを用意しラップします。次に実行する処理を持つハンドラを認証ハンドラの構造体にフィールドに登録できるようにしておきます。認証用のハンドラは、認証が正常に完了したら、認証用ハンドラの次に実行するハンドラのServeHTTP()メソッドを実行することで処理を渡します。ラップしたハンドラ呼び出し。}}このWrapするパターンですが、以下のようにWrapperをhttp.HandleFuncを使って記述することも可能です。})}wrapする側もされる側もHandleFuncにするなら以下のような形です。stringというgomiauthの中で使用されているライブラリの中で落ちるという現象にあい、ここで時間をとるのも...と思い、golang.org/x/oauth2というパッケージを利用しました。処理の流れとしては、以下の記事を参考にいたしました。認可コードを得ることができたためアクセストークンを要求し、そのアクセストークンを使用しリソースサーバにアクセスできる。}}アバターSNSから取得するパターン、Gravatarから取得するパターン、画像のアップロードしてもらうパターンの3種ありましたが、前の2つは実装自体は難しくなかったため3つ目の画像のアップロード・提供について書いていきます。具体的な処理から抽象化していく工程も書いていきたかったのですが、言語化するのが難しかった...。"success!!")}提供するときには組み込みのファイルサーバ機能を使います。ScripPrefixもFileServerもhttp.Handler型を返す。本の2章で紹介されたDecoratorパターン。パスの中から接頭辞(/avatars/の部分を削除)。静的ファイルの提供ができるまとめ本自体は原本が2014年の出版でかなり古いので、新しい情報とかも見つつ整理していくのが大事だなと思いました。普通WEBアプリケーションを作成するときは標準パッケージではなくGinとか使われていくのだろうなとは思っているのですが...。メルカリさんのAPIサーバのように、net/httpパッケージだけを見て作成されるパターンもあるので、実際は用途によっての使い分けなんですかね。practices月別アーカイブはてなブログをはじめよう!jrywm121さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。