All skills
gogf avatar

/goframe-v2

@911705d
by GoFramegogf/skills81 stars
3

GoFrame v2 development skill. Use only when the target Go project uses or is explicitly adopting GoFrame v2: the nearest go.mod requires github.com/gogf/gf/v2, existing Go files import github.com/gogf/gf/v2 or any github.com/gogf/gf/v2/... component package, or the user asks to scaffold, migrate, or build with GoFrame. Trigger for GoFrame-backed Go work such as APIs/controllers/services, middleware, routing/config, ORM/DAO/DO/entity/database operations, gf CLI/codegen, HTTP/gRPC services, and microservice conventions. Do not trigger for generic Go projects without GoFrame evidence, frontend-only work, shell scripts, or unrelated infrastructure tasks.

Use this Skill: https://skilld.dev/gh/gogf/skills/goframe-v2

This session only. Nothing lands on disk.

referencesWEB服务开发路由管理路由管理-中间件拦截器中间件拦截器-基本介绍.md

GoFrame 提供了优雅的中间件请求控制方式, 该方式也是主流的 WebServer 提供的请求流程控制方式, 基于中间件设计可以为 WebServer 提供更灵活强大的插件机制。经典的中间件洋葱模型:

中间件定义

中间件的定义和普通HTTP执行方法 HandlerFunc 一样,但是可以在 Request 参数中使用 Middleware 属性对象来控制请求流程。

我们拿一个跨域请求的中间件定义来示例说明一下:

func MiddlewareCORS(r *ghttp.Request) {
    r.Response.CORSDefault()
    r.Middleware.Next()
}

可以看到在该中间件中执行完成跨域请求处理的逻辑后,使用 r.Middleware.Next() 方法进一步执行下一个流程;如果这个时候直接退出不调用 r.Middleware.Next() 方法的话,将会退出后续的执行流程(例如可以用于请求的鉴权处理)。

中间件类型

中间件的类型分为两种:前置中间件和后置中间件。前置即在路由服务函数调用之前调用,后置即在其后调用。

前置中间件

其定义类似于:

func Middleware(r *ghttp.Request) {
    // 中间件处理逻辑
    r.Middleware.Next()
}

后置中间件

其定义类似于:

func Middleware(r *ghttp.Request) {
    r.Middleware.Next()
    // 中间件处理逻辑
}

中间件注册

中间件的注册有多种方式,参考接口文档: https://pkg.go.dev/github.com/gogf/gf/v2/net/ghttp

全局中间件

func (s *Server) Use(handlers ...HandlerFunc)

全局中间件是可以 独立使用 的请求拦截方法,通过路由规则的方式进行注册,绑定到 Server 上,由于中间件需要执行请求拦截操作,因此往往是使用"模糊匹配"或者"命名匹配"规则。 :::tip 全局中间件仅对动态请求拦截有效,无法拦截静态文件请求。 :::

分组路由中间件

func (g *RouterGroup) Middleware(handlers ...HandlerFunc) *RouterGroup

分组路由中注册的中间件绑定到当前分组路由中的所有的服务请求上,当服务请求被执行前会调用到其绑定的中间件方法。 分组路由仅有一个 Middleware 的中间件注册方法。分组路由中间件与全局中间件不同之处在于, 分组路由中间件无法独立使用,必须在分组路由注册中使用,并且绑定到当前分组路由中所有的路由上作为路由方法的一部分。

执行优先级

全局中间件

由于全局中间件也是通过路由规则执行,那么也会存在执行优先级:

  1. 首先,由于全局中间件是基于模糊路由匹配,因此 当同一个路由匹配到多个中间件时,会按照路由的深度优先规则执行,具体请查看路由章节;
  2. 其次, 同一个路由规则下,会按照中间件的注册先后顺序执行,中间件的注册方法也支持同时按照先后顺序注册多个中间件;
  3. 最后,为避免优先级混淆和后续管理,建议将所有中间件放到同一个地方进行先后顺序注册来控制执行优先级; :::tip 这里的建议来参考于 gRPC 的拦截器设计,没有过多的路由控制,仅在一个地方同一个方法统一注册。往往越简单,越容易理解,也便于长期维护。 :::

分组路由中间件

分组路由中间件是绑定到分组路由上的服务方法,不存在路由规则匹配,因此只会按照注册的先后顺序执行。参考后续示例或如下代码的执行结果。

展开源码

package main

import (
    "context"
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/net/ghttp"
    "github.com/gogf/gf/v2/os/glog"
)

type HelloReq struct {
    g.Meta `path:"/hello" method:"get"`
}
type HelloRes struct {
}

type Hello struct{}

func (Hello) Say(ctx context.Context, req *HelloReq) (res *HelloRes, err error) {
    glog.Debug(ctx, "中")
    return
}

func RequestHandle1(r *ghttp.Request) {
    glog.Debug(r.GetCtx(), "前1")
    r.Middleware.Next()
}

func RequestHandle2(r *ghttp.Request) {
    glog.Debug(r.GetCtx(), "前2")
    r.Middleware.Next()
}

func RequestHandle3(r *ghttp.Request) {
    glog.Debug(r.GetCtx(), "前3")
    r.Middleware.Next()
}

func RequestHandle4(r *ghttp.Request) {
    glog.Debug(r.GetCtx(), "前4")
    r.Middleware.Next()
}

func ResponseHandle1(r *ghttp.Request) {
    r.Middleware.Next()
    glog.Debug(r.GetCtx(), "后1")
}

func ResponseHandle2(r *ghttp.Request) {
    r.Middleware.Next()
    glog.Debug(r.GetCtx(), "后2")
}

func ResponseHandle3(r *ghttp.Request) {
    r.Middleware.Next()
    glog.Debug(r.GetCtx(), "后3")
}

func ResponseHandle4(r *ghttp.Request) {
    r.Middleware.Next()
    glog.Debug(r.GetCtx(), "后4")
}

func main() {
    s := g.Server()
    s.Use(ghttp.MiddlewareHandlerResponse)
    s.Group("/", func(group *ghttp.RouterGroup) {
        // 前置中间件
        group.Middleware(RequestHandle1)
        group.Middleware(RequestHandle2)

        // 后置中间件
        group.Middleware(ResponseHandle1)
        group.Middleware(ResponseHandle2)

        group.Group("/sub", func(group *ghttp.RouterGroup) {
            // 前置中间件
            group.Middleware(RequestHandle3)
            group.Middleware(RequestHandle4)

            // 后置中间件
            group.Middleware(ResponseHandle3)
            group.Middleware(ResponseHandle4)

            group.Bind(new(Hello))
        })
    })
    s.Run()
}

执行结果如下:

执行中断

在 分组路由中间件 中,我们可以在 前置中间件 的 Next() 调用之前通过 return 对本次请求进行中断,在打断后, 后续 所有 的 前置中间件、 同级及子级 的 后置中间件、 请求处理方法 将不会被执行。

如上面用来展示分组路由中间件优先级的代码中:

  • 在 RequestHandle1 的 Next() 调用前进行中断,则只会执行 RequestHandle1
  • 在 RequestHandle2 的 Next() 调用前进行中断,则只会执行 RequestHandle1、 RequestHandle2
  • 在 RequestHandle3 的 Next() 调用前进行中断,则会执行 RequestHandle1、 RequestHandle2、 RequestHandle3 以及 ResponseHandle2、 ResponseHandle1
  • 在 RequestHandle4 的 Next() 调用前进行中断,则会执行 RequestHandle1、 RequestHandle2、 RequestHandle3、 RequestHandle4 以及 ResponseHandle2、 ResponseHandle1

上述的中断实例都不会执行 请求处理方法。

除了常见的return 在 中间件中终端后续处理流程大方式外,框架还提供了 Exit 相关的方法来在代码执行处强制中断执行流程,具体可参考章节: 数据返回-Exit控制

Source: SKILL.md on GitHub

1 alert16d5 checks · Risk MEDIUM
  • Gen Agent Trust Hub16d

    The skill provides a comprehensive development guide and code examples for the GoFrame v2 framework. While highly informative for Go developers, it contains several examples with hardcoded placeholder secrets, tokens, and specific local file paths to sensitive configuration files (like Kubernetes credentials). These elements are provided for demonstration purposes but represent insecure practices if used in production without modification.

  • Socket16d

    5 alerts: gptSecurity, gptAnomaly

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    227/949 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 911705d. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 4 months ago.

Steadyupdated 4 months ago
  • Go
  • Database
  • goframe
  • orm
  • http
  • grpc
  • microservices
  • crud
  • scaffolding
  • middleware

README badge

README badge for gogf/skills

Provides instruction and conventions for developing with GoFrame v2, a modular Go framework for building HTTP and gRPC services, microservices, and database operations using its ORM, CLI tooling, and project scaffolding. Use this skill when the target project has GoFrame v2 as a dependency or when the user requests scaffolding, migrations, or service development with GoFrame conventions.

Generated from the current SKILL.md.

When should I use this skill?
Use this skill only when your Go project uses GoFrame v2, indicated by github.com/gogf/gf/v2 in go.mod or imports. Do not use for generic Go projects, frontend work, or infrastructure tasks unrelated to GoFrame.
Should I manually set created_at and updated_at fields?
No. GoFrame automatically writes created_at on insert and updated_at on insert/update/save. Manually setting these fields is redundant and violates project conventions.
What should I use for database operations instead of g.Map?
Always use DO objects from internal/model/do/. DO struct fields are interface{}, unset fields remain nil and are automatically ignored by the ORM.
How does soft delete work in GoFrame?
Call Delete() on the DAO; GoFrame automatically converts it to UPDATE SET deleted_at = NOW(). Queries automatically filter out soft-deleted rows without requiring manual WhereNull conditions.
Where should I implement business logic?
Implement business logic directly in the service/ directory. Do not use the logic/ directory unless explicitly requested.

Generated from the current SKILL.md. These answers refresh after source changes.