美文网首页
kratos数据库和自动生成的接口示例

kratos数据库和自动生成的接口示例

作者: 哆啦在这A梦在哪 | 来源:发表于2021-01-07 17:46 被阅读0次

B站微服务框架Kratos详细教程(7)- 数据库

开始使用

由于kratos使用了wire依赖注入框架,开始使用前,建议先了解相关教程:依赖注入wire使用详解

配置

打开配置文件configs/mysql.toml,修改为自己的服务器配置:

[Client]
    addr = "127.0.0.1:3306"
    dsn = "{user}:{password}@tcp(127.0.0.1:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
    readDSN = ["{user}:{password}@tcp(127.0.0.2:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"]
    active = 20
    idle = 10
    idleTimeout ="4h"
    queryTimeout = "200ms"
    execTimeout = "300ms"
    tranTimeout = "400ms"

在该配置文件中我们可以配置mysql的读和写的dsn、连接地址addr、连接池的闲置连接数idle、最大连接数active以及各类超时。

如果配置了readDSN,在进行读操作的时候会优先使用readDSN的连接,readDSN可以只配一个地址。

初始化

打开文件internal/dao/dao.go
在该文件中的New方法接收外部数据库连接池对象db *sql.DB, 也可以像官方文档说的, 直接在dao中初始化
这里涉及到依赖注入, 具体可以查看di/wire_gen.go文件
依赖注入相关可查看这篇文章: 依赖注入wire使用详解

model/model.go文件中添加结构体

type User struct {
    Uid int32
    Nickname string
    Age int32
    Uptime int32
    Addtime int32
}

dao/dao.go中新增接口

type Dao interface {
    Close()
    Ping(ctx context.Context) (err error)
    // bts: -nullcache=&model.Article{ID:-1} -check_null_code=$!=nil&&$.ID==-1
    Article(c context.Context, id int64) (*model.Article, error)
    //新增接口
    GetUser(c context.Context, uid int64) (user *model.User, err error)
}

新增文件dao/dao.user.go, 实现接口

package dao

import (
    "context"
    "dbserver/internal/model"
    "fmt"
    "github.com/go-kratos/kratos/pkg/database/sql"
    "github.com/go-kratos/kratos/pkg/log"
    "time"
)

//查询用户
func (d *dao)GetUser(c context.Context, uid int64) (user *model.User, err error){
    querySql := fmt.Sprintf("SELECT * FROM `users` WHERE uid=?;")

    user = new(model.User)
    err = d.db.QueryRow(c, querySql, uid).Scan(&user.Uid, &user.Nickname, &user.Age, &user.Uptime, &user.Addtime)
    if err != nil && err != sql.ErrNoRows {
        log.Error("d.QueryRow error(%v)", err)
        return
    }
    return user, nil
}

打开api/api.proto, 增加测试http接口:

syntax = "proto3";

import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "google/protobuf/empty.proto";
import "google/api/annotations.proto";

// package 命名使用 {appid}.{version} 的方式, version 形如 v1, v2 ..
package demo.service.v1;

// NOTE: 最后请删除这些无用的注释 (゜-゜)つロ

option go_package = "api";
option (gogoproto.goproto_getters_all) = false;

service Demo {
  rpc Ping(.google.protobuf.Empty) returns (.google.protobuf.Empty);
  rpc SayHello(HelloReq) returns (.google.protobuf.Empty);
  rpc SayHelloURL(HelloReq) returns (HelloResp) {
    option (google.api.http) = {
      get: "/say_hello"
    };
  };

  rpc GetUser(GetReq) returns (Response) {
    option (google.api.http) = {
      get: "/getuser"
    };
  };
}

message HelloReq {
  string name = 1 [(gogoproto.moretags) = 'form:"name" validate:"required"'];
}

message HelloResp {
  string Content = 1 [(gogoproto.jsontag) = 'content'];
}

message GetReq {
  int64 uid = 1 [(gogoproto.moretags) = 'form:"uid" validate:"required"'];
}

message Response {
  string Content = 1 [(gogoproto.jsontag) = 'content'];
}

打开internal/service/service.go, 增加接口实现:

//获取用户信息
func (s *Service) GetUser(ctx context.Context, req *pb.GetReq) (reply *pb.Response, err error) {
    fmt.Printf("GetUser: %d", req.Uid)
    user, err := s.dao.GetUser(ctx, req.Uid)
    if err != nil {
        fmt.Printf("GetUser %s Error", req.Uid)
        return
    }
    res, _ := json.Marshal(user)
    reply = &pb.Response{
        Content: string(res),
    }
    return
}

进入api目录, 重新生成pb文件

kratos tool protoc

这里需要注意的是,执行完这句话,就会在api.bm.go中实现proto文件里option (google.api.http)中定义的路由,实现在RegisterDemoBMServer方法中,并且在server下的http文件内的New调用。这种方法是直接用他的服务进行api的注册,还可以自己手动在http下的server中initRouter下定义自己的路由。

运行项目:

kratos run

打开浏览器:

获取单个用户信息:

http://localhost:8000/getuser?uid=3

返回信息:

{
    "code": 0,
    "message": "0",
    "ttl": 1,
    "data": {
        "content": "{\"Uid\":3,\"Nickname\":\"soul\",\"Age\":22,\"Uptime\":1608102563,\"Addtime\":1608102563}"
    }
}

到此, 已实现基本的数据库操作

事务

kratos/pkg/database/sql包支持事务操作,具体操作示例如下:

开启一个事务:

tx := d.db.Begin()
if err = tx.Error; err != nil {
    log.Error("db begin transcation failed, err=%+v", err)
    return
}

在事务中执行语句:

res, err := tx.Exec(_demoSQL, did)
if err != nil {
    return
}
rows := res.RowsAffected()

提交事务:

if err = tx.Commit().Error; err!=nil{
    log.Error("db commit transcation failed, err=%+v", err)
}

回滚事务:

if err = tx.Rollback().Error; err!=nil{
    log.Error("db rollback failed, err=%+v", rollbackErr)
}

grpc方式调用
上述那个方法使用proto注册服务的形式写的,所以也能使用grpc的方式调用。



http对应的grpc的服务文件他这里给你注册了。
所以说,你只需要,把api下的proto文件给别人,就可以了
这里我写上自己的测试代码
文件结构:这里直接把pb.go拿过来用了


image.png
package main
import (
    "context"
    "log"
    "test/api"
    "google.golang.org/grpc"
)

func main() {
    conn, err := grpc.Dial("localhost:9000", grpc.WithInsecure())
    if err != nil {
        panic(err)
    }
    defer conn.Close()
    c := api.NewDemoClient(conn) //新建client
    getUser(c)
}

//普通数据传输
func getUser(c api.DemoClient) {
    character, err := c.GetUser(context.Background(), &api.HelloReq{
        Name: "shitingbao",
    })
    if err != nil {
        log.Println("err:", err)
    }
    log.Println("character:", character)
}

相关文章

网友评论

      本文标题:kratos数据库和自动生成的接口示例

      本文链接:https://www.haomeiwen.com/subject/oyoaoktx.html