Skip to content
鼓励作者:欢迎打赏犒劳

kitex代码生成

数据库

sql
CREATE DATABASE IF NOT EXISTS user_db DEFAULT CHARSET utf8mb4;

USE user_db;

CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    age INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com', 25);

代码生成 -- server

thrift文件

idl/user.thrift

text
namespace go user
include "./user_model.thrift"

struct GetUserRequest {
    1: required i64 id
}

struct GetUserResponse {
    1: required i32 code,
    2: optional string msg,
    3: optional user_model.User user  // 注意通过文件名引用
}

service UserService {
    GetUserResponse GetUser(1: GetUserRequest req)
}

user_model.thrift

text
namespace go user.model  # 单独指定 Model 的 namespace
struct User {
    1: optional i64 id,
    2: optional string name,
    3: optional string email,
    4: optional i32 age
}

代码生成命令

shell
kitex --module user-service-rpc --service user_service idl/user.thrift



## 使用 Kitex 的 --service 参数为空(仅生成 Model,不生成服务端代码):
kitex --module user-service-rpc --service "" idl/user_model.thrift
  • --module user-service-rpc 模块名
  • --service user_service 给生成的 RPC 服务指定一个在部署和调用时使用的唯一标识,是服务发现和注册的重要依据

代码结构

代码路径 kitex_gen/user/userservice/ 的由来:

  • user 部分:来自 IDL 开头的 namespace go user,这是 Go 语言的命名空间声明,决定了生成代码的一级包路径。
  • userservice 部分:来自 IDL 中定义的服务名 service UserService,Kitex 会将服务名转为小写(UserServiceuserservice)作为二级包路径。

注意!!!,假如你的thrift文件,将数据库的DO和接口层如果放在一起的话,那么则不会生成model目录,而是统一都在`kitex_gen/user/user.go`

里面定义的。如果你想单独拎出来,则需要将实体类的thrift文件定义,然后就会生成model文件了。

text
E:.
│  build.sh
│  go.mod
│  go.sum
│  handler.go
│  kitex_info.yaml
│  main.go

├─idl
│      user.thrift
│      user_model.thrift

├─kitex_gen
│  └─user
│      │  k-consts.go
│      │  k-user.go
│      │  user.go
│      │
│      ├─model
│      │      k-consts.go
│      │      k-user_model.go
│      │      user_model.go
│      │
│      └─userservice
│              client.go
│              server.go
│              userservice.go

└─script
        bootstrap.sh

如何自测rpc接口是否正常

需要在rpc项目中写代码来自测。新建 client/main.go 文件

go
package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "your-module-name/kitex_gen/user" // 替换为你的实际模块名
    "your-module-name/kitex_gen/user/userservice" // 替换为你的实际模块名

    "github.com/cloudwego/kitex/client"
    "github.com/cloudwego/kitex/client/callopt"
)

func main() {
    // 1. 创建客户端,直连服务端
    cli, err := userservice.NewClient(
        "user-service", // 服务名
        client.WithHostPorts("127.0.0.1:8888"), // 指定服务端地址和端口
    )
    if err != nil {
        log.Fatalf("Failed to create client: %v", err)
    }
    defer func() {
        if err := cli.(*userservice.Client).Close(); err != nil {
            log.Printf("Warning: Failed to close client: %v", err)
        }
    }()

    // 2. 准备请求参数
    req := &user.GetUserRequest{
        ID: 1, // 假设要查询用户ID为1
    }

    // 3. 发起调用
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()

    resp, err := cli.GetUser(
        ctx,
        req,
        callopt.WithRPCTimeout(3*time.Second),
    )
    if err != nil {
        log.Fatalf("RPC call failed: %v", err)
    }
    //打印结果
    fmt.Printf("  result: %+v\n", resp)
}

代码生成 -- client

我们提供的rpc服务最终是要给client提供的,那么就需要有相同的一份thrift文件来定义接口。

生成接口定义

hertz-web/ 目录下,复用 user.thrift 文件,生成客户端:

shell
kitex --client user_service idl/user.thrift

创建 RPC 客户端:client/user.go

go
package client

import (
    "github.com/cloudwego/kitex/client"
    "github.com/cloudwego/kitex/pkg/rpcinfo"
    "github.com/kitex-contrib/registry-nacos/resolver"
    "hertz-web/kitex_gen/user/userservice"
    "hertz-web/kitex_gen/user"
    "net"
)

var UserClient userservice.Client

func Init() {
    c, err := userservice.NewClient("user_service",
        // client.WithResolver(resolver.NewNacosResolver()), Nacos注册中心
        client.WithHostPorts("127.0.0.1:8888"), // 直连模式,不使用注册中心
        client.WithRPCTimeout(3*time.Second),
    )
    if err != nil {
        panic(err)
    }
    UserClient = c
}

调用rpc

Web Handler:handler/user.go

go
package handler

import (
    "context"
    "fmt"
    "hertz-web/client"
    "hertz-web/kitex_gen/user"
    "github.com/cloudwego/hertz/pkg/app"
    "github.com/cloudwego/hertz/pkg/protocol/consts"
)

func GetUser(c context.Context, ctx *app.RequestContext) {
    userId, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
    if err != nil {
        ctx.JSON(consts.StatusBadRequest, map[string]interface{}{
            "msg": "invalid id",
        })
        return
    }

    req := &user.GetUserRequest{Id: userId}
    resp, err := client.UserClient.GetUser(c, req)
    if err != nil {
        ctx.JSON(consts.StatusInternalServerError, map[string]interface{}{
            "msg": "rpc call failed: " + err.Error(),
        })
        return
    }

    if resp.Code != 0 {
        ctx.JSON(consts.StatusNotFound, map[string]interface{}{
            "msg": resp.Msg,
        })
        return
    }

    ctx.JSON(consts.StatusOK, map[string]interface{}{
        "user": resp.User,
    })
}

主函数

go
package main

import (
    "hertz-web/client"
    "hertz-web/handler"
    "github.com/cloudwego/hertz/pkg/app/server"
)

func main() {
    client.Init() // 初始化 Kitex 客户端

    h := server.Default()

    h.GET("/user/:id", handler.GetUser)

    h.Spin()
}

如有转载或 CV 的请标注本站原文地址