RPC 服务使用 GORM:在 GO-ZERO 框架中实现高效数据持久化

目录

RPC 服务使用 GORM:在 GO-ZERO 框架中实现高效数据持久化

一、项目结构创建

二、编写 proto 文件

三、配置数据库连接

四、生成代码

五、编写模型结构体和操作方法(Model 层)

六、编写服务逻辑

七、配置服务

八、启动服务


在 GO-ZERO 框架中,RPC 服务常常需要与数据库进行交互以实现数据的持久化。GORM 是一个强大的 Go 语言 ORM 库,将其与 RPC 服务结合使用可以提高开发效率。本文将详细介绍如何在 RPC 服务中使用 GORM,包括创建项目结构、编写 proto 文件、配置数据库连接、生成代码、编写服务逻辑以及进行数据操作等步骤,并附上完整的代码示例。

一、项目结构创建

  1. 新建项目目录
    • 创建一个新的目录,例如rpc_gorm_demo,作为项目的根目录。
    • rpc_gorm_demo目录下创建rpc目录,用于存放 RPC 相关的文件。
  2. 创建内部目录结构
    • rpc目录下创建user目录,用于存放用户相关的 RPC 服务文件(这里以用户服务为例,可根据实际需求创建多个不同的服务目录)。
    • user目录下创建etcinternalmodel目录。etc目录用于存放服务的配置文件,internal目录用于存放服务的内部逻辑代码,model目录用于存放与数据库表对应的模型结构体和操作方法。

二、编写 proto 文件

  1. 创建 user.proto 文件
    • rpc/user目录下创建user.proto文件。
    • 定义服务接口,例如创建一个名为UserRpc的服务,包含一个GetUser方法,该方法接收一个UserRequest类型的参数(包含id字段),并返回一个UserResponse类型的结果(包含idname等字段)。
    • 示例代码如下:

syntax = "proto3";

service UserRpc {
    rpc GetUser (UserRequest) returns (UserResponse);
}

message UserRequest {
    int32 id = 1;
}

message UserResponse {
    int32 id = 1;
    string name = 2;
}

三、配置数据库连接

  1. 安装 GORM 依赖
    • 在终端中执行go get gorm.io/gorm命令安装 GORM 库,同时可能还需要安装相应的数据库驱动,例如对于 MySQL 数据库,执行go get gorm.io/driver/mysql
  2. 编写连接函数(initGorm)
    • 在项目中创建一个用于初始化 GORM 连接的函数,例如在main.go文件中(或者根据项目结构创建一个专门的数据库连接文件)。
    • 示例代码如下:

package main

import (
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    "rpc_gorm_demo/config" // 假设配置文件在config目录下,根据实际情况调整
)

func initGorm() *gorm.DB {
    // 获取配置文件中的MySQL连接信息
    mysqlStr := config.Config.Mysql.DataSource
    // 连接数据库
    db, err := gorm.Open(mysql.Open(mysqlStr), &gorm.Config{})
    if err!= nil {
        panic(err)
    }
    return db
}

  • 在上述代码中,首先从配置文件中获取 MySQL 的连接字符串,然后使用gorm.Open函数建立与 MySQL 数据库的连接。如果连接失败,程序将抛出panic异常,因为数据库连接是整个服务运行的基础,如果连接失败,服务启动也没有意义。

四、生成代码

  1. 执行生成命令
    • 在终端中,进入rpc目录(确保已安装goctl工具)。
    • 执行以下命令将user.proto文件转换为对应的 GO 代码:

goctl proto -I. --go_out=. --go-grpc_out=. user.proto

  • 此命令会在rpc目录下生成一系列文件,包括user.pb.gouser_grpc.pb.go等,这些文件包含了 RPC 服务的客户端和服务端的基本代码结构,以及与 proto 文件中定义的消息和服务对应的 Go 结构体和接口。

五、编写模型结构体和操作方法(Model 层)

  1. 创建 user 模型结构体(user/model/usermodel.go)
    • rpc/user/model目录下创建usermodel.go文件。
    • 定义User结构体,与数据库中的用户表字段对应。
    • 示例代码如下:

package model

import "gorm.io/gorm"

type User struct {
    ID   int32  `gorm:"primaryKey"`
    Name string `gorm:"size:50"`
}

  1. 编写 User 模型的操作方法(user/model/usermodel.go)
    • usermodel.go文件中,为User模型编写基本的操作方法,如FindUserByID用于根据用户 ID 查询用户信息。
    • 示例代码如下:

func (u *User) FindUserByID(db *gorm.DB, id int32) (*User, error) {
    var user User
    result := db.Where("id =?", id).First(&user)
    if result.Error!= nil {
        return nil, result.Error
    }
    return &user, nil
}

六、编写服务逻辑

  1. 在 internal 目录下编写逻辑代码(user/internal/logic/userrpcgetuserlogic.go)
    • rpc/user/internal/logic目录下创建userrpcgetuserlogic.go文件(文件名根据生成的代码结构和实际需求而定)。
    • 实现GetUser方法的逻辑,在逻辑中调用User模型的操作方法从数据库获取用户信息并返回。
    • 示例代码如下:

package logic

import (
    "context"

    "rpc_gorm_demo/rpc/internal/svc"
    "rpc_gorm_demo/rpc/types/demo"
    "rpc_gorm_demo/rpc/user/model"
)

type UserRpcGetUserLogic struct {
    ctx    context.Context
    svcCtx *svc.ServiceContext
}

func NewUserRpcGetUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserRpcGetUserLogic {
    return &UserRpcGetUserLogic{
        ctx:    ctx,
        svcCtx: svcCtx,
    }
}

func (l *UserRpcGetUserLogic) GetUser(in *demo.UserRequest) (*demo.UserResponse, error) {
    // 获取数据库连接
    db := l.svcCtx.DB
    // 创建User模型实例
    userModel := model.User{DB: db}
    // 调用模型方法查询用户信息
    user, err := userModel.FindUserByID(db, in.Id)
    if err!= nil {
        return nil, err
    }
    return &demo.UserResponse{Id: user.ID, Name: user.Name}, nil
}

七、配置服务

  1. 在 etc 目录下创建配置文件(user/etc/user.yaml)
    • rpc/user/etc目录下创建user.yaml文件。
    • 配置服务的相关信息,如服务名称、监听地址和端口等,同时配置数据库连接信息(这里假设使用 MySQL 数据库)。
    • 示例配置如下:

Name: userrpc
Host: 0.0.0.0
Port: 8080
Mysql:
  DataSource: root:root@tcp(127.0.0.1:3306)/your_database?charset=utf8mb4&parseTime=True&loc=Local

  • your_database替换为实际的数据库名,根据实际情况修改用户名、密码和端口号等。

八、启动服务

  1. 创建 main 文件(user/main.go)
    • rpc/user目录下创建main.go文件(如果goctl生成代码时已包含则无需重复创建)。
    • 编写启动服务的代码,例如:

package main

import (
    "flag"
    "fmt"

    "github.com/zeromicro/go-zero/core/conf"
    "github.com/zeromicro/go-zero/core/service"
    "rpc_gorm_demo/rpc/internal/config"
    "rpc_gorm_demo/rpc/internal/server"
    "rpc_gorm_demo/rpc/internal/svc"
    "rpc_gorm_demo/rpc/types/demo"
)

var configFile = flag.String("f", "etc/user.yaml", "the config file")

func main() {
    flag.Parse()

    var c config.Config
    conf.MustLoad(*configFile, &c)

    ctx := svc.NewServiceContext(c)
    srv := server.NewUserRpcServer(ctx)

    defer srv.Stop()

    fmt.Printf("Starting rpc server at %s:%d...\n", c.Host, c.Port)
    service.Group{}.Add(srv)
    if err := service.Run(); err!= nil {
        fmt.Printf("start rpc server error: %v\n", err)
    }
}

  1. 启动服务
    • 在终端中,进入rpc/user目录。
    • 执行go run main.go(或者go run user.go,根据实际文件名而定)启动 RPC 服务。

通过以上步骤,我们成功地在 RPC 服务中使用了 GORM 进行数据库操作。在实际项目中,还可以进一步扩展和优化,如添加更多的数据库操作方法、实现事务处理、进行数据库连接池的配置等,以满足复杂的业务需求。同时,结合 GO-ZERO 框架的其他特性,如服务治理、熔断限流等,可以构建出更加稳定、高效的分布式系统。希望本文能够帮助大家更好地理解和应用 RPC 服务与 GORM 的结合。

Go-Zero框架实现用户登录功能通常会包含以下几个步骤: 1. **安装依赖**: 首先,你需要安装`gorilla/mux`库,它是一个HTTP请求路由包,用于处理URL到函数的映射。可以使用go mod来添加依赖: ``` go get github.com/gorilla/mux ``` 2. **创建结构体和数据库模型**: 创建一个表示用户的结构体,比如User,并定义字段如ID、用户名、密码等。如果你计划使用SQL数据库,还需要创建对应的数据库表。 3. **注册认证中间件**: 使用`github.com/gorilla/handlers`库的BasicAuth或JWT(JSON Web Tokens)中间件来实现登录验证。你可以设置一个函数来检查提供的凭据是否有效。 4. **编写登录API**: 创建一个处理POST请求的路由,接收用户输入的用户名和密码,然后通过查询数据库验证用户信息。如果验证成功,返回一个token或其他验证凭证。 5. **保护资源访问**: 使用认证中间件保护需要登录权限的API。例如,在处理敏感操作的路由前,检查传入的token是否有效。 6. **错误处理**: 对于无效的登录尝试或令牌验证失败,返回适当的HTTP状态码和错误消息。 以下是简化版的示例代码片段: ```go package main import ( "net/http" "github.com/gorilla/mux" "golang.org/x/crypto/bcrypt" ) type User struct { ID uint `gorm:"primary_key"` Username string `json:"username"` Password []byte `json:"-"` } func basicAuthHandler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { username := r.Header.Get("Authorization") if username == "admin:password" { // 这里只是一个简单的示例 next.ServeHTTP(w, r) return } http.Error(w, "Unauthorized", http.StatusUnauthorized) }) } func loginHandler(w http.ResponseWriter, r *http.Request) { // 实现登录逻辑,这里省略了数据库交互 } func main() { router := mux.NewRouter() router.Use(basicAuthHandler) router.HandleFunc("/login", loginHandler).Methods("POST") // 登录端点 http.ListenAndServe(":8000", router) } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值