golang创建一个简单的restfulapi

你如今的气质里,藏着你走过的路,读过的书,和爱过的人。

Webからエンタープライズアプリケーションまで、RESTfulというアーキテクチャーが使われています。ステートレス設計として、別々のソフトウェアコンポーネント間の通信を提供する強力な方法であります。 Web開発者として、RESTful APIを作るために、主にPythonを使いますが、最近Goプログラミング言語に出会い、興味を持ってきました。Goプログラミング言語(golangでも呼ばれる)は、Googleのプロジェクトで、マイクロサービスアーキテクチャに適当な多くの機能も提供するので、人気が増えています。

本記事、golangを使ってシンプルなRESTful APIをどう作るか説明したいと思います。

仕様

RESTful APIは、通常CRUDができます。CRUDとは、データベースの四つの主要な機能、「作成(Create)」「読み出し(Read)」「更新(Update)」「削除(Delete)」ですが、今回は、簡単にするために、読み出しの機能しか作りません。そして、データがJSONの形式で書きます。

そして、このエンドポイントがあります:

  • / -> ホームページですが、とりあえずテキストしかを見せない
  • /items/ -> Itemのリスト、Itemデータを全部見せる
  • /items/{id} -> 特定のItemの情報
    それぞれのItemは、「title」と「description」のデータがあって、簡単にするために、データベースを使用するのではなく、データを事前に定義します。

開発プロセス

最初は、必要なパッケージをインストールします。ルーティングのために、Muxというパッケージを使っていきます。CMD / Terminalを開けて、このコマンドを実行してください:

1
go get -u github.com/gorilla/mux

その後、main.goというファイルを作成して、このコードを入れてください:

1
2
3
4
5
6
7
8
9
package main

import (
"fmt"
"log"
"net/http"

"github.com/gorilla/mux"
)

すべてのgolangを使って作られたプログラムがパッケージで構成されています。この部分では、何のパッケージが必要かが書いてあります。この場合には、四つのパッケージが必要です。

ルーティング

同じファイルで、さっきの書いたコードの下に、このコードを入れてください:

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
// Controller for the / route (home)
func homePage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "This is the home page. Welcome!")
}

// Controller for the /items route
func returnAllItems(w http.ResponseWriter, r *http.Request) {
// Code for returning all items here
}

// Controller for the /items/{id} route
func returnSingleItem(w http.ResponseWriter, r *http.Request) {
// Code for returning a single item here
}

func handleRequests() {
myRouter := mux.NewRouter().StrictSlash(true)
myRouter.HandleFunc("/", homePage)
myRouter.HandleFunc("/items", returnAllItems)
myRouter.HandleFunc("/items/{id}", returnSingleItem)
log.Fatal(http.ListenAndServe(":8000", myRouter))
}

func main() {
handleRequests()
}

main()という関数は、このプログラムをスタートすると、自動的に実行されます。その中に、handleRequests()という関数が実行されます。handleRequests()の関数で、それぞれのエンドポイントがアクセスされると、何が起こるかが書いてあります。例えば、/のエンドポイントがアクセスされると、homePageという関数が実行されるとか、/itemsのエンドポイントがアクセスされると、returnAllItemsという関数が実行されます。

そして、このコード:

1
log.Fatal(http.ListenAndServe(":8000", myRouter))

の意味は、このプログラムが8000のポートで、アクセスできます。これで、もう使えるなので、スタートしてみましょう!

CMD / Terminal で、このコマンドを実行してください:

1
go run main.go

サポート関数

これから、二つのパッケージが必要なので、インポートしましょう。最初のimport部分をこれに変更してください:

1
2
3
4
5
6
7
8
9
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"

"github.com/gorilla/mux"
)

encoding/jsonとstrconvというパッケージを追加しました。もうすぐこの二つを使います。

それから、二つのサポート関数を書きましょう:

1
2
3
4
5
6
7
8
9
10
func respondWithError(w http.ResponseWriter, code int, msg string) {
respondWithJson(w, code, map[string]string{"error": msg})
}

func respondWithJson(w http.ResponseWriter, code int, payload interface{}) {
response, _ := json.Marshal(payload)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
w.Write(response)
}

両方の関数は、JSONの形式でHTTP requestに答える役割があります。

Itemデータ構造

Itemのデータ構造を書きましょう。importの部分の下に、このコードを入れてください:

1
2
3
4
5
// Item representation
type Item struct {
Title string `json:"title"`
Description string `json:"description"`
}

仕様に基づいて、それぞれのItemは、「title」と「description」のデータがあります。そして、その下に、これを入れて下さい:

1
2
3
4
5
// Global, static list of items
var itemList = []Item{
Item{Title: "Item A", Description: "The first item"},
Item{Title: "Item B", Description: "The second item"},
}

今回は、データベースを使わないので、これでデータを事前に定義します。二つのItemだけ書きましたが、自由にいくつでもいいですよ。

コア関数

最後に、コア関数(returnAllItemsとreturnSingleItem)を書きます。

1
2
3
4
// Controller for the /items route
func returnAllItems(w http.ResponseWriter, r *http.Request) {
respondWithJson(w, http.StatusOK, itemList)
}

基本的に、/itemsのエンドポイントをアクセスすると、returnAllItems()という関数がすべてのItemをJSONの形式で答えます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Controller for the /items/{id} route
func returnSingleItem(w http.ResponseWriter, r *http.Request) {
// Get query parameters using Mux
vars := mux.Vars(r)

// Convert {id} parameter from string to int
key, err := strconv.Atoi(vars["id"])

// If {id} parameter is not valid int
if err != nil {
respondWithError(w, http.StatusBadRequest, "Invalid request payload")
return
}

// If Item with ID of {id} does not exist
if key >= len(itemList) {
respondWithError(w, http.StatusNotFound, "Item does not exist")
return
}

respondWithJson(w, http.StatusOK, itemList[key])
}

そして、returnSingleItem()という関数が、idのURLパラメーターに基づいて特定のItemの情報をJSONの形式で答えます。

例えば、localhost:8000/items/1をアクセスしたら、1がidになります。それから、そのidは、indexとしてitemListという配列からデータを取ってJSONの形式で答えます。idは1の場合は、二つ目のデータが取られます。そして、idは0の場合は、一つ目のデータが取られます。

idは、数だけであるべきであり、Itemの数以上になってはいけないので、二つのチェックを書きました。これで、終わりです。作ってみましょう!

テスト

CMD / Terminal で、さっきのrunを閉じて、もう一回実行してください:

1
go run main.go

https://qiita.com/sbenemerito/items/d94b811f14ce0a546a3f