🙆

Go - EchoのContextを利用してデータを伝搬させる

2025/02/17に公開

contextは何か

Go標準のコンテキスト context.Context

下記でまとめて頂いている内容に勝る結論はありません。。。
https://zenn.dev/hsaki/books/golang-context/viewer/intro
ですが。
読み進めていくのが難しいと感じる方もいるかもしれません。

簡単に表現します。
リクエストのキャンセル・タイムアウト・値の伝搬などに使用される。
処理が1つのメソッドで終了することは無いと思います。処理が伝搬していく際に、後続の処理をキャンセルしたり、後続の処理に値を渡していくことが簡単にできるパッケージです。

Echoのコンテキスト echo.Context

Echo フレームワークがリクエストごとに作成し、HTTPリクエストの情報などを保持する。Golangのcontext機能も利用できる。

Echoのコンテキスト echo.Context でログを見る

echo.Contextはハンドラー関数で取得します。ハンドラー関数はecho.HandlerFunc型の関数です。
middlewareの関数・Controllerの関数として実装します。

echo.Contextからhttpリクエストを取得する例

middlewareを利用して、httpリクエストの内容を取得する処理を作ります。
ハンドラー関数は引数に echo.Context を持ちます。

package middleware

import (
	"fmt"
	"github.com/labstack/echo/v4"
)

// リクエストの情報を出力
func PrintRequestMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
		req := c.Request()

		// HTTP メソッド, URI, クエリパラメータ, ヘッダーをログに記録
		fmt.Printf("[Middleware] %s %s?%s\n", req.Method, req.RequestURI, req.URL.RawQuery)
		fmt.Printf("[Middleware] Headers: %v\n", req.Header)

		return next(c) // 次のハンドラーを実行
	}
}

echoに反映

e := echo.New()
e.Use(middleware.PrintRequestMiddleware)

middleware -> controllerへecho.Contextの受け渡し

golangでも、echoでも、contextは、伝搬させる際に有効な手段となります。
echoにおいて、middleware -> controllerにecho.Contextを受け渡す実験をします。

middleware

package middleware

import (
	"fmt"
	"github.com/labstack/echo/v4"
)

// contextに情報を入力
func SetRequestMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
		c.Set("custom_value", "Hello from Middleware")
		return next(c) // 次のハンドラーを実行
	}
}

Controller

package controller

import (
	"fmt"
	"net/http"
	"github.com/labstack/echo/v4"
)

// GetCustomValue は `echo.Context` からデータを取得してレスポンスを返す
func GetCustomValue() echo.HandlerFunc {
	return func(c echo.Context) error {
		// `echo.Context` から値を取得
		value := c.Get("custom_value")

		// ログに出力
		fmt.Printf("[Controller] Retrieved custom_value: %v\n", value)

		// JSON レスポンスを返す
		return c.JSON(http.StatusOK)
	}
}

echo起動

package main

import (
	"github.com/labstack/echo/v4"

	"your_project/controller"
	"your_project/middleware"
)

func main() {
	e := echo.New()

	// ミドルウェアを適用
	e.Use(middleware.SetCustomValueMiddleware)

	// ルートの登録
	e.GET("/custom", controller.GetCustomValue())

	// サーバーを起動
	e.Logger.Fatal(e.Start(":8080"))
}

[Controller] Retrieved custom_value: Hello from Middleware

こちらが出力されます。
Contextを利用することで、レイヤーを超えてデータを伝搬させることが出来ました。

Discussion