20211015のGoに関する記事は4件です。

【Go】mongo-go-driverでコレクションの全件を取得する

概要 MongoDBで全件検索したい時、[Mongo] findメソッドのいろいろな使い方(MySQLと比較)の記事にある通り単純にfindメソッドを使えばOKです。では、GolangでMongoDBを使用する際に使う、mongo-go-driverで全件取得するにはどうすれば良いのか。 [Mongo] findメソッドのいろいろな使い方(MySQLと比較)の記事を見ると、FindメソッドはFind(context.Context, 検索条件, Find オプション)とあり、検索条件の部分はnilを設定すれば良いのかなと思いnilを設定したところ、エラーとなりました。 対応 こちらのドキュメントを読むと、 The filter parameter must be a document containing query operators and can be used to select which documents are included in the result. It cannot be nil. An empty document (e.g. bson.D{}) should be used to include all documents. とある通り、検索条件にはnilは許可されておらず空のドキュメントを設定する必要があるとのこと。 ちなみに、nilを設定するとs: "document is nil"という不親切なエラーが発生します。 ドキュメントをちゃんと読めば気づけたのですが、この記述に気付かずエラーの原因を探すのに手間取ったので、今回記事にしました。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GoでWebSocketを使いチャットサーバー構築

はじめに 使わない日はないくらい仕事でもプライベートでも、チャットサービスが日常的に使われていますが、チャット機能を実装したことがなかったので、 今回はGo(1.17)でWebSocketを使いチャットサーバーを構築していきます。 なぜGoを使うかと言うと、最近仕事で使っていて、私の中でブームなのと、 そして何よりマスコットキャラクターのGopherがかわいいからです(笑) The Go gopher was designed by Renée French. 余談ですが、2022/2リリース予定のバージョン1.18ではgo getのバイナリインストールの機能が削除されるため、 バージョンアップの際は手順書やスクリプトを修正する必要があります。皆さんお気をつけください。 システムイメージ クライアントがチャットサーバーにWebSocketで接続し、そのコネクションをgoroutineでハンドリングし、メッセージの送信を受け付けます。 送信されたメッセージはchannel型の変数に送り、別のgoroutineでメッセージを拾い、それをすべてのクライアントに送信します。 goroutineは、Goのランタイムに管理される軽量なスレッドで、並行処理を可能にします。 channelは、送受信する値の型を定義することで、goroutine間で値を送受信できるようにします。 以下のリンクからそれぞれ動きを確認できます。 Goroutines Channels 実装 さっそくチャットサーバーの実装を進めていきます。 WebSocketを利用するために、今回はWebツールキットのgorillaを使います。? まずはWebSocket、ブロードキャストするためのchannel宣言と、チャットメッセージ用に構造体を宣言します。 // 接続されるクライアント var clients = make(map[*websocket.Conn]bool) // メッセージブロードキャストチャネル var broadcast = make(chan Message) // アップグレーダ var upgrader = websocket.Upgrader{} // メッセージ用構造体 type Message struct { Username string `json:"username"` Message string `json:"message"` } main関数では、静的ファイルを参照するファイルサーバーとWebSocketのルーティングを行います。 ※今回は割愛しますが、ファイルサーバー(public配下)にフロントで動かすHTML,JS,CSSを配置します。 func main() { // ファイルサーバー fs := http.FileServer(http.Dir("./public")) http.Handle("/", fs) // WebSocket http.HandleFunc("/ws", handleConnections) go handleMessages() err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal("ListenAndServe: ", err) } } 次にコネクションハンドラとして動くhandleConnectionsの中身を実装します。 処理としては GETリクエストをWebSocketにアップグレード 受け取ったリクエストをクライアントとして登録し、コネクションを確立 メッセージを待つ メッセージを受け取ったらチャネルに送りブロードキャスト といった感じです。 このhandleConnectionsをgoステートメントで呼び出して並行実行しています。 そしてchannelを使用し、並行実行されるgoroutine間で値(チャットメッセージ)を送受信します。 func handleConnections(w http.ResponseWriter, r *http.Request) { // 送られてきたGETリクエストをWebSocketにアップグレード ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Fatal(err) } defer ws.Close() // クライアントを登録 clients[ws] = true for { var message Message // 新しいメッセージをJSONとして読み込み、Message構造体にマッピング err := ws.ReadJSON(&message) if err != nil { log.Printf("error: %v", err) delete(clients, ws) break } // 受け取ったメッセージをbroadcastチャネルに送る broadcast <- message } } 最後にbroadcastチャネルにメッセージが送信された時、 接続している全てのクライアントメッセージを送信します。 func handleMessages() { for { // broadcastチャネルからメッセージを受け取る message := <-broadcast // 接続中の全クライアントにメッセージを送る for client := range clients { err := client.WriteJSON(message) if err != nil { log.Printf("error: %v", err) client.Close() delete(clients, client) } } } } まとめ これでWebSocketを使ったチャットサーバーの完成です! 簡単ですね!フロントの実装は割愛しますが、こんな感じでチャットができます。 今回Goでチャットサーバーを作ることで、 WebSocket、goroutine、channelの理解を少し深められたと思います。 普段あまり触れていなかった部分ですが、実際に書いて動かしてみると理解しやすかったです。 皆さんも是非トライしてみてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Marshalの本当の意味知ってる?

背景 Go言語を触っていると、よく構造体をJSONに変換するために以下のように Marshal という関数を使いますよね。何気なく使っていていましたが、Marshal の意味とは何か知りたくなったので調べてみました。 json.Marshal使用例 type Person struct { Name string `json:"name"` Age int `json:"age"` } func main() { p := Person{ Name: "hoge", Age: 30, } s, err := json.Marshal(p) if err != nil { panic(err) } fmt.Println(string(s)) } Marshaling とは まずはWikipediaからの情報です。 In computer science, marshalling or marshaling (US spelling) is the process of transforming the memory representation of an object into a data format suitable for storage or transmission. Google翻訳をかけると、Marshalingとは、 オブジェクトのメモリ表現をストレージまたは送信に適したデータ形式に変換するプロセスです。 上記のプログラム例で言うと、 「オブジェクトのメモリ表現」が Person構造体であるp 「送信に適したデータ形式」が JSON形式 ということになります。 結論 Marshal とは、JSON形式に変換することではなく、あくまでも「オブジェクトのメモリ表現を送信に適したデータ形式に変換する」ということです。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでGO,Gin環境構築

前提条件 Dockerがインストール済み 手順 フォルダ構成の作成 go - web - Dockerfile - main.go - docker-compose.yml Dockerfileの記述 Dockerfile FROM golang:latest WORKDIR /go/src docker-compose.yml version: '3' services: web: build: ./web tty: true volumes: - ./web:/go/src ports: - "3000:3000" Docker起動~サーバーの起動まで VSCodeのDocker拡張を使ってる場合は1,2番はGUIでもできます。 1.docker起動 docker-compose up 2.コンテナに入る(別ターミナルで) docker-compose exec web bash 3.ginモジュールの追加 go mod init go get github.com/gin-gonic/gin 4.main.goの記述 main.go package main import ( "github.com/gin-gonic/gin" ) func main() { router := gin.Default() router.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello World", }) }) router.Run(":3000") } 5.サーバーの起動 go run main.go 確認 ブラウザで「localhost:3000」にアクセス jsonの内容が表示されれば完了です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む