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.

references微服务开发微服务开发.md

≈2.9k tokens on demand. Your agent reads this file only when SKILL.md points to it.

基本介绍

GoFrame 框架从 v2.4 版本开始全面支持微服务模式开发,提供了常用的微服务组件、开发工具和开发教程,帮助开发团队快速实现微服务架构转型。

简单示例

GoFrame 的微服务组件采用低耦合和通用化设计,组件化的使用方式支持大部分的微服务通信协议。在官方文档中,我们以 HTTP 和 gRPC 协议为示例,介绍微服务的开发以及组件工具的使用。由于 HTTP Web 开发已经有比较丰富完善的独立章节介绍,因此微服务章节主要以 gRPC 为例进行讲解。

HTTP 微服务示例

https://github.com/gogf/gf/tree/master/example/registry/file

server.go
package main

import (
    "github.com/gogf/gf/contrib/registry/file/v2"
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/net/ghttp"
    "github.com/gogf/gf/v2/net/gsvc"
    "github.com/gogf/gf/v2/os/gfile"
)

func main() {
    gsvc.SetRegistry(file.New(gfile.Temp("gsvc")))

    s := g.Server(`hello.svc`)
    s.BindHandler("/", func(r *ghttp.Request) {
        g.Log().Info(r.Context(), `request received`)
        r.Response.Write(`Hello world`)
    })
    s.Run()
}

可以看到,一个 HTTP 微服务端和普通的 Web Server 基本一致,但是顶部多了一行代码:

gsvc.SetRegistry(file.New(gfile.Temp("gsvc")))

这行代码用于启用并配置当前服务使用的服务注册发现组件。在该示例中使用的 file.New(gfile.Temp("gsvc")) 是基于本地文件系统的服务注册发现组件,其中的 gfile.Temp("gsvc") 指定了存放服务信息文件的路径。例如在 Linux/ MacOS 系统下,该路径指向 /tmp/gsvc 目录。

:::warning 基于文件系统的注册发现组件仅适用于本地开发和测试,不支持跨节点通信。 :::

在生产环境中,我们需要使用分布式的服务注册发现组件,例如 etcd、 polaris、 zookeeper 等。框架的社区组件库中已经提供了这些常用服务注册发现组件的实现。

在该示例中,我们为 Server 设置了名称 hello.svc,这是该服务在微服务架构中的唯一标识。服务名称用于服务间的识别和通信,是微服务治理的基础。当启用服务注册组件后, HTTP Server 在运行时会自动将自己的访问地址(IP和端口)注册到服务注册中心,使得其他服务能够通过服务名称发现并访问该服务。

client.go
package main

import (
    "time"

    "github.com/gogf/gf/contrib/registry/file/v2"
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/net/gsvc"
    "github.com/gogf/gf/v2/os/gctx"
    "github.com/gogf/gf/v2/os/gfile"
)

func main() {
    gsvc.SetRegistry(file.New(gfile.Temp("gsvc")))

    client := g.Client()
    for i := 0; i < 10; i++ {
        ctx := gctx.New()
        res, err := client.Get(ctx, `http://hello.svc/`)
        if err != nil {
            panic(err)
        }
        g.Log().Debug(ctx, res.ReadAllString())
        res.Close()
        time.Sleep(time.Second)
    }
}

客户端通过 g.Client() 创建一个 HTTP Client 对象,并通过 http://hello.svc/ 地址访问服务端。其中的 hello.svc 是之前服务端绑定的微服务名称。当客户端使用微服务名称进行访问时,服务注册发现组件会自动在底层进行服务发现,查询该服务名称对应的实际服务地址,然后建立连接进行通信。

执行结果

先执行 server.go 启动服务端,然后再执行 client.go 通过服务名称请求服务。

执行后,客户端输出:

$ go run client.go
2023-03-14 20:22:10.006 [DEBU] {8054f3a48c484c1760fb416bb3df20a4} Hello world
2023-03-14 20:22:11.007 [DEBU] {6831cae08c484c1761fb416b9d4df851} Hello world
2023-03-14 20:22:12.008 [DEBU] {9035761c8d484c1762fb416b1e648b81} Hello world
2023-03-14 20:22:13.011 [DEBU] {a05a32588d484c1763fb416bc19ff667} Hello world
2023-03-14 20:22:14.012 [DEBU] {40fdea938d484c1764fb416b8459fc43} Hello world
2023-03-14 20:22:15.014 [DEBU] {686c9acf8d484c1765fb416b3697d369} Hello world
2023-03-14 20:22:16.015 [DEBU] {906a470b8e484c1766fb416b85b9867e} Hello world
2023-03-14 20:22:17.017 [DEBU] {28c7fd468e484c1767fb416b86e5557f} Hello world
2023-03-14 20:22:18.018 [DEBU] {90d2ad828e484c1768fb416bfcde738f} Hello world
2023-03-14 20:22:19.019 [DEBU] {d05559be8e484c1769fb416baad06f23} Hello world

服务端输出:

$ go run server.go
2023-03-14 20:20:06.364 [INFO] pid[96421]: http server started listening on [:61589]
2023-03-14 20:20:06.364 [INFO] openapi specification is disabled
2023-03-14 20:20:06.364 [DEBU] service register: &{Head: Deployment: Namespace: Name:hello.svc Version: Endpoints:10.35.12.81:61589 Metadata:map[insecure:true protocol:http]}

   SERVER   | DOMAIN  | ADDRESS | METHOD | ROUTE |                             HANDLER                             |    MIDDLEWARE
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  hello.svc | default | :61589  | ALL    | /     | main.main.func1                                                 |
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
  hello.svc | default | :61589  | ALL    | /*    | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------

2023-03-14 20:22:10.006 [INFO] {8054f3a48c484c1760fb416bb3df20a4} request received
2023-03-14 20:22:11.007 [INFO] {6831cae08c484c1761fb416b9d4df851} request received
2023-03-14 20:22:12.008 [INFO] {9035761c8d484c1762fb416b1e648b81} request received
2023-03-14 20:22:13.010 [INFO] {a05a32588d484c1763fb416bc19ff667} request received
2023-03-14 20:22:14.012 [INFO] {40fdea938d484c1764fb416b8459fc43} request received
2023-03-14 20:22:15.013 [INFO] {686c9acf8d484c1765fb416b3697d369} request received
2023-03-14 20:22:16.015 [INFO] {906a470b8e484c1766fb416b85b9867e} request received
2023-03-14 20:22:17.016 [INFO] {28c7fd468e484c1767fb416b86e5557f} request received
2023-03-14 20:22:18.017 [INFO] {90d2ad828e484c1768fb416bfcde738f} request received
2023-03-14 20:22:19.019 [INFO] {d05559be8e484c1769fb416baad06f23} request received

GRPC 微服务示例

https://github.com/gogf/gf/tree/master/example/rpc/grpcx/basic

helloworld.proto

gRPC 和 HTTP 协议的一个显著区别是, gRPC 需要通过 protobuf 来定义 API 接口和数据结构。 Protobuf 是一种语言无关、平台无关的可扩展序列化数据结构,相比 JSON 和 XML 更小更快,是 gRPC 的核心特性。

syntax = "proto3";

package protobuf;

option go_package = "github.com/gogf/gf/grpc/example/helloworld/protobuf";

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

以上 protobuf 文件通过以下命令执行编译(请提前安装 protoc 工具):

gf gen pb

将会生成对应的 proto go 数据结构文件以及 grpc 接口文件:

helloworld.pb.go
helloworld_grpc.pb.go
controller.go

控制器用于实现 proto 文件中定义的接口方法。如果使用框架的标准化工程目录结构,该控制器代码文件也可以由框架的 gf gen pb 工具自动生成,开发者只需要填充对应方法的具体实现逻辑即可。

type Controller struct {
    protobuf.UnimplementedGreeterServer
}

func Register(s *grpcx.GrpcServer) {
    protobuf.RegisterGreeterServer(s.Server, &Controller{})
}

// SayHello implements helloworld.GreeterServer
func (s *Controller) SayHello(ctx context.Context, in *protobuf.HelloRequest) (*protobuf.HelloReply, error) {
    return &protobuf.HelloReply{Message: "Hello " + in.GetName()}, nil
}
config.yaml

服务端配置文件,在该配置文件中指定了微服务的名称为 demo。微服务名称是服务间通信的唯一标识符。当未显式配置服务端的监听端口时,服务端会自动监听一个可用的本地端口。在微服务模式下,由于使用服务名称进行通信,服务端端口通常不需要显式指定,采用随机监听即可。

grpc:
  name:            "demo"
  logPath:          "./log"
  logStdout:        true
  errorLogEnabled:  true
  accessLogEnabled: true
  errorStack:       true
server.go

gRPC 服务端的启动代码。当未显式指定服务端使用的服务注册发现组件时,服务端默认使用基于文件系统的注册发现组件,该组件仅适用于单机测试。其中的 controller.Register(s) 调用了我们通过工具生成的控制器注册方法,将具体的接口实现注册到服务端中。

package main

import (
    "github.com/gogf/gf/contrib/rpc/grpcx/v2"
    "github.com/gogf/gf/example/rpc/grpcx/basic/controller"
)

func main() {
    s := grpcx.Server.New()
    controller.Register(s)
    s.Run()
}
client.go

gRPC 客户端的调用代码。在创建连接时需要指定服务端服务的名称。这里的服务名称为 demo,对应的是上面配置文件中设置的微服务名称。当未显式指定客户端使用的服务注册发现组件时,客户端默认使用基于文件系统的注册发现组件,该组件仅适用于单机测试。

package main

import (
    "github.com/gogf/gf/contrib/rpc/grpcx/v2"
    "github.com/gogf/gf/example/rpc/grpcx/basic/protobuf"
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/os/gctx"
)

func main() {
    var (
        ctx    = gctx.New()
        conn   = grpcx.Client.MustNewGrpcClientConn("demo")
        client = protobuf.NewGreeterClient(conn)
    )
    res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"})
    if err != nil {
        g.Log().Error(ctx, err)
        return
    }
    g.Log().Debug(ctx, "Response:", res.Message)
}
执行结果

服务端输出:

可以看到,服务端输出了一些 DEBU 级别的调试信息,用于显示服务注册的详细信息。由于没有显式指定服务端的监听端口,这里随机监听了本地端口 64517。

$ go run server.go
2023-03-14 20:50:58.465 [DEBU] set default registry using file registry as no custom registry set
2023-03-14 20:50:58.466 [DEBU] service register: &{Head: Deployment: Namespace: Name:demo Version: Endpoints:10.35.12.81:64517 Metadata:map[protocol:grpc]}
2023-03-14 20:50:58.466 [INFO] pid[98982]: grpc server started listening on [:64517]
2023-03-14 20:52:37.059 {9898c809364a4c17da79e47f3e6c3b8f} /protobuf.Greeter/SayHello, 0.003ms, name:"World", message:"Hello World"

客户端输出:

客户端通过微服务名称访问,并成功接收到了服务端的响应。需要注意的是,客户端和服务端日志中的链路跟踪 ID( TraceID)是相同的( 9898c809364a4c17da79e47f3e6c3b8f),这表明它们属于同一个请求链路。 GoFrame 框架的微服务特性默认开启了链路跟踪能力,方便开发者进行请求链的追踪和问题排查。

$ go run client.go
2023-03-14 20:52:37.060 [DEBU] {9898c809364a4c17da79e47f3e6c3b8f} Response: Hello World

相关文档

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.