核心
先取得模組:go get github.com/yshengliao/gortexa@v0.27.0。以下片段皆對 v0.27.0 編譯驗證過。
kernel
Section titled “kernel”composition root:App 擁有單一 h2c listener(多工 gRPC、HTTP/JSON、MCP)、gRPC server、health registry、in-process loopback 與 graceful shutdown。用 kernel.New(opts...) 建立,options 有 WithConfig、WithLogger、WithInterceptors(吃 interceptor.Set 值,非指標)、WithStatsHandler、WithHTTPWrap、WithGateway、WithMCPHandler、WithShutdownHook、WithServerOptions(append gRPC ServerOption,讓你加自己的 interceptor/stats,接在框架鏈之後)、WithAdminListener(opt-in 獨立 ops 埠只服務 /healthz+/readyz)、WithExtraListener(在 caller 自有 listener 上服務任意 handler)。主 h2c 埠始終單埠多工不變;app.AdminAddr() 可查 admin 埠實綁位址。
import ( "context" "github.com/yshengliao/gortexa/config" "github.com/yshengliao/gortexa/health" "github.com/yshengliao/gortexa/kernel")
cfg := config.MustBuild()app, err := kernel.New(kernel.WithConfig(cfg))if err != nil { return err}// 在此把 gRPC service 註冊到 app.GRPCServer()app.Health().Register("self", func(context.Context) health.State { return health.Healthy })return app.Run(ctx) // /healthz、/readyz 內建App 的方法:GRPCServer()、Health()、Loopback()、Logger()、SetGateway()、SetMCPHandler()、Run(ctx)、Shutdown(ctx)。
config
Section titled “config”固定優先序:內建預設 < YAML 檔 < .env 檔 < 環境變數(GORTEXA_ 前綴、__ 表巢狀)。入口是 MustBuild(fail-loud,jwt_secret 為空/預設 placeholder/< 32 bytes 或 issuer 空會 panic)與 BuildUnvalidated。沒有 Load。
import "github.com/yshengliao/gortexa/config"
cfg := config.MustBuild(config.WithConfigFile("etc/config.yaml"))dsn := cfg.DB.DSN.Reveal() // Secret 只在使用點還原secret 型別 config.Secret 的 String()/log/JSON 一律遮罩成 ****,要真值用 Reveal()。Config 的子結構:Server、Auth、DB、Cache、MQ、Log、Observ(全欄位見設定)。
interceptor
Section titled “interceptor”NewSet(Config) 產出八段固定順序的鏈(recover → request-id → logger → load-shed → rate-limit → circuit-breaker → auth → validation),交給 kernel.WithInterceptors。
import ( "time" "github.com/yshengliao/gortexa/auth" "github.com/yshengliao/gortexa/interceptor")
set, err := interceptor.NewSet(interceptor.Config{ Verifier: auth.MustNewVerifier([]byte(secret), "gortexa"), RateLimit: interceptor.RateLimitConfig{RPS: 200, Burst: 100, TTL: 10 * time.Minute},})// set 傳給 kernel.WithInterceptors(set)Config 另有 Logger、AuthSkip、CircuitBreaker、LoadShedding、Metrics 欄位。Set 提供 UnaryChain()/StreamChain()。
auth 段可插拔:Verifier 走內建 HS256 JWT;非 JWT 方案改設 Authenticator(一個 auth.Authenticator,Authenticate(ctx) (ctx, error)),例如 static bearer/mTLS/API-key。兩者都設時 Authenticator 優先。JWT 也可用 auth.NewJWTAuthenticator(v) 顯式取得。
HS256 JWT 驗證/簽發與 context helper。secret 須 ≥ 32 bytes。
import "github.com/yshengliao/gortexa/auth"
v := auth.MustNewVerifier([]byte(secret), "gortexa")tok, err := v.Sign("user-123", []string{"admin"}, time.Hour)// 在 handler 內取回驗證過的 claims:if claims, ok := auth.ClaimsFrom(ctx); ok { _ = claims.Subject // "user-123"}Verify(token) 回 *Claims(含 Roles 與內嵌的 jwt.RegisteredClaims);BearerToken(header) 從 Authorization header 取 token。
apperr
Section titled “apperr”單一對應表驅動 gRPC status、HTTP status 與 MCP error envelope。*apperr.Error 實作了 GRPCStatus(),handler 直接回傳即可。
import "github.com/yshengliao/gortexa/apperr"
func (s *svc) GetThing(ctx context.Context, req *pb.GetThingRequest) (*pb.Thing, error) { t, err := s.repo.Find(ctx, req.GetId()) if err != nil { return nil, apperr.Wrap(apperr.CatNotFound, "thing not found", err) } return t, nil}只有 CatInvalidArgument 與 CatUnauthenticated 會把開發者訊息轉給呼叫端;其餘 category 只露出 registry 的 SafeMessage,內部原因不外洩。category 常數涵蓋 gRPC 的完整清單(CatNotFound、CatPermissionDenied、CatFailedPrecondition、CatInternal 等)。