こんにちは。KOUKIです。
Go言語を勉強していますが、本業で使用する機会が中々なく、時間が経つに従い、色々と忘れてしまいます^^;
そこで、勉強したことを備忘として残していきたいと思っています。
今回は、指定したIDを元にStructから特定のデータを抜き出す処理を実装しようと思います。
<目次>
実装
早速、実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
package main import ( "encoding/json" "log" "net/http" "strconv" "github.com/gorilla/mux" ) type Post struct { ID int Title string } var ( posts []Post router = mux.NewRouter() ) func createModel() { posts = append(posts, Post{ID: 1, Title: "First Blog"}, Post{ID: 2, Title: "Second Blog"}, Post{ID: 3, Title: "Third Blog"}, Post{ID: 4, Title: "Forth Blog"}, Post{ID: 5, Title: "Fifth Blog"}, ) } func getPost(w http.ResponseWriter, r *http.Request) { // パラメータを取得 // map[id:1]のように取得できる params := mux.Vars(r) id, err := strconv.Atoi(params["id"]) if err != nil { log.Fatal(err) } for _, post := range posts { if post.ID == id { json.NewEncoder(w).Encode(&post) } } } func main() { createModel() // ***/posts/1 -> 特定のデータを取得 router.HandleFunc("/posts/{id}", getPost).Methods("GET") // サーバーを8080で起動 log.Println("Start Server...") log.Fatal(http.ListenAndServe(":8080", router)) } |
確認しやすさを優先して、gorilla/muxを使ってAPI化しました。
解説は後回しにして、ひとまず実行してみましょう。
1 2 |
$ go run main.go 2020/06/20 11:23:08 Start Server... |
ローカルサーバーが起動したら「localhost:8080/1」をブラウザ上で叩いてみてください。

ID=1のデータが取得できましたね。
「localhost:8080/1」の1は、IDを指しているのです。
続いて、「localhost:8080/2」を叩いてみましょう。

OKですね。
検索プログラムの解説
実装したプログラムについて、解説していきます。
Postモデル
1 2 3 4 5 6 7 8 9 |
type Post struct { ID int Title string } var ( posts []Post ... ) |
こちらは、StructでPostモデルを実装しました。それをスライスでpostsと定義してます。
Postに仮のデータを入れる必要があるので、createModelにてデータを作成してます。
1 2 3 4 5 6 7 8 9 10 |
func createModel() { posts = append(posts, Post{ID: 1, Title: "First Blog"}, Post{ID: 2, Title: "Second Blog"}, Post{ID: 3, Title: "Third Blog"}, Post{ID: 4, Title: "Forth Blog"}, Post{ID: 5, Title: "Fifth Blog"}, ) } |
HttpRouterの作成
routerは、gorilla/muxのrouterを宣言してます。
1 2 3 4 |
var ( ... router = mux.NewRouter() ) |
このrouterを使うとリクエストハンドリングを実装できます。
例えば、「router.HandleFunc(“/posts/{id}”, getPost).Methods(“GET”)」では、「localhost:8080/<post_id>」にGETメソッドでアクセスするという記述になります。
また、第二引数のgetPostにて、アクセスした先の処理を実装することが可能です。
1 2 3 4 5 6 7 8 9 10 |
func main() { ... // ***/posts/1 -> 特定のデータを取得 router.HandleFunc("/posts/{id}", getPost).Methods("GET") ... } |
最後に、このrouterを起動する処理を追加します。
1 2 3 4 5 6 7 8 |
func main() { ... // サーバーを8080で起動 log.Println("Start Server...") log.Fatal(http.ListenAndServe(":8080", router)) } |
これで、
をterminal上で打ち込むとサーバーが起動するようになります。go run main.go
Structの検索(本題)
ようやく本題の処理です。
Go言語では、Struct内のデータをどのように検索すれば一番綺麗に実装できるでしょうか?
正直、やり方は色々あると思います。
私の場合は、rangeを併用して検索するのが好きです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
func getPost(w http.ResponseWriter, r *http.Request) { // パラメータを取得 // map[id:1]のように取得できる params := mux.Vars(r) id, err := strconv.Atoi(params["id"]) if err != nil { log.Fatal(err) } for _, post := range posts { if post.ID == id { json.NewEncoder(w).Encode(&post) } } } |
では、「localhost:8080/posts/<この部分>」の”この部分”をmapで取得できるメソッドです。例えば、mux.Vars(r)
を取得できます。map[id:1]
取得したデータは、Stringで格納しているので、strconv.Atoiメソッドでint型にしてからid変数に格納しました。
そして、posts(スライス)はrange関数でループできるので、これによりstruct内を検索しています。
おわりに
いざ実装しようとすると、手が止まる時があります。
「あれ?どうやって実装するんだっけ?」みたいな感じになるのです。
しかし、このようにメモ程度でも書き留めておくと、後々見返せて便利ですね^^
それでは、また!
コメントを残す
コメントを投稿するにはログインしてください。