😊

【Go】BunRouterのハンドラ関数作ってみた

2023/09/25に公開

公式

https://bunrouter.uptrace.dev/guide/golang-router.html

なぜBunRouterを触ろうと思ったのか

単純に触ったことがないからですw
これまでGoのAPI開発ではechoやginを使っていました。何か別のも野で良さそうなのがないかなーと探していた時に
XでBunと呼ばれるORMがよさそうだという話を小耳にはさみ調べてみました。
公式ページに行くとORMのほかにGolang HTTP routerも作っていると表示が出てきました。
そこでいろいろと調べてみるうちにBunRouterを魅せてくる表を見つけてしまいました。
img.png
net/httpとの互換性があり、巨大なラッパーを構築することなく最小限のAPIを使用できるところがめちゃくちゃええやんてなりました。

それでは実行ポイントとハンドラ関数のコードを見ていきましょう

コード

main.go

func main() {
	//インスタンス生成しDIする
	db, _ := config.NewDBConnection()
	userRepository := infrastructure.NewUserRepository(db)
	userService := service.NewUserService(userRepository)
	userHandler := _interface.NewUserHandler(userService)
	middleware := middleware.NewMiddleware(userService)
    // ここから下だけ見ればOK
	//bunrouter起動
    r := bunrouter.New()
	//middlewear定義
	r.Use(middleware.RecoverMiddleware())
	r.Use(middleware.CorsMiddleware())
	//エンドポイント定義
	r.POST("/user/create", userHandler.UserCreateHandle())
	r.POST("/user/get", userHandler.UserGetHandle())
	r.POST("/move", userHandler.MoveHandle())
	r.POST("/destroy", userHandler.DestroyHandle())
	r.GET("/users/get", userHandler.UserRankingGetHandle())
    // サーバーをリッスンする
	log.Println("listening on http://localhost:8080")
	log.Println(http.ListenAndServe(":8080", r))
}

handler.go

type UserHandler struct {
	userService service.UserService
}

func NewUserHandler(userService *service.UserService) *UserHandler {
	return &UserHandler{userService: *userService}
}

func (u *UserHandler) UserCreateHandle() bunrouter.HandlerFunc {
	return func(w http.ResponseWriter, req bunrouter.Request) error {
		//リクエストで来る構造体を定義
		var requestData request.UserCreateRequest
		//構造体に合わせてデコード
		if err := json.NewDecoder(req.Body).Decode(&requestData); err != nil {
			http.Error(w, "Failed to parse request", http.StatusBadRequest)
			return err
		}
        //コンテクストを取得
		ctx := req.Context()
		//service層から認証トークンを取得
		authToken, err := u.userService.Add(ctx, requestData.Name)
		if err != nil {
			http.Error(w, "Failed to create user", http.StatusInternalServerError)
			return err
		}
		//クライアントに返すjson構造体を定義
		responseData := &response.UserCreateResponse{Token: authToken}
		//先ほどの構造体をjsonにデコードする
		responseBytes, err := json.Marshal(responseData)
		if err != nil {
			http.Error(w, "Failed to generate response", http.StatusInternalServerError)
			return err
		}
        //クライアントに返す際の属性を付ける
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(responseBytes)
		return nil
	}
}

所感

  • デコードする部分はほぼ"net/http"でやるものとほぼ変わらない感じでした。
  • ミドルウェアの定義が楽になってていいなという感じだった。

まとめ

echoやginなどで使われる必要最低限の部分が利用できるという感じで非常にミニマムなものになっていた感じでありました~

Discussion