基本構造
-
プロジェクトのセットアップ
- Goモジュールの初期化
go mod init example.com/myapi
- Goモジュールの初期化
メインファイルの作成
以下は、標準ライブラリのみを使った簡単なCRUD操作を含むRestAPIの例です。
package main
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
)
type Item struct {
ID int `json:"id"`
Name string `json:"name"`
}
var items []Item
func main() {
http.HandleFunc("/items", itemsHandler)
http.HandleFunc("/items/", itemHandler)
fmt.Println("Server listening on port 8000")
http.ListenAndServe(":8000", nil)
}
func itemsHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
json.NewEncoder(w).Encode(items)
case "POST":
var item Item
_ = json.NewDecoder(r.Body).Decode(&item)
item.ID = len(items) + 1
items = append(items, item)
json.NewEncoder(w).Encode(item)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
func itemHandler(w http.ResponseWriter, r *http.Request) {
idStr := strings.TrimPrefix(r.URL.Path, "/items/")
id, err := strconv.Atoi(idStr)
if err != nil {
http.NotFound(w, r)
return
}
switch r.Method {
case "GET":
for _, item := range items {
if item.ID == id {
json.NewEncoder(w).Encode(item)
return
}
}
http.NotFound(w, r)
case "PUT":
for i, item := range items {
if item.ID == id {
var newItem Item
_ = json.NewDecoder(r.Body).Decode(&newItem)
newItem.ID = id
items[i] = newItem
json.NewEncoder(w).Encode(newItem)
return
}
}
http.NotFound(w, r)
case "DELETE":
for i, item := range items {
if item.ID == id {
items = append(items[:i], items[i+1:]...)
break
}
}
json.NewEncoder(w).Encode(items)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
認証の追加
認証を追加するには、JWTを利用するのが一般的です。以下に簡単な例を示します。
-
JWTライブラリのインストール
go get -u github.com/golang-jwt/jwt/v4
-
JWT認証の実装
import (
"github.com/golang-jwt/jwt/v4"
// その他のインポート
)
var jwtKey = []byte("my_secret_key")
type Claims struct {
Username string `json:"username"`
jwt.RegisteredClaims
}
func JwtVerify(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
tokenString := r.Header.Get("Authorization")
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
if err != nil || !token.Valid {
w.WriteHeader(http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
}
}
// ルートの使用例
// http.HandleFunc("/items", JwtVerify(itemsHandler))