• go-kratos v2 + gorm 实现增删改查demo


    go-kratos v2 + gorm 实现增删改查demo

    由于正在学习Bilibili的go开源框架 go-kratos,简单学习的过程中有一些摸索过程,现在根据go-kratos v2 + gorm 实现增删改查demo实现用户的增删改查

    mysql用户表

    #sql
    
    CREATE TABLE `user` (
      `id` int unsigned NOT NULL AUTO_INCREMENT,
      `name` char(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '名称',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
    

    项目初始化

    0.文档地址

    1.创建项目模板

    kratos new user
    
    cd user
    

    2.拉取项目依赖

    go mod download
    

    3.生成proto模板

    kratos proto add api/user/user.proto
    

    这个时候我们去修改api/user/user.proto, 先仅仅实现用户新增功能,代码如下

    syntax = "proto3";
    
    package api.user.v1;
    
    option go_package = "users/api/user/v1;v1";
    option java_multiple_files = true;
    option java_package = "api.user.v1";
    
    import "google/api/annotations.proto";
    // the validate rules:
    // https://github.com/envoyproxy/protoc-gen-validate
    import "validate/validate.proto";
    
    service user {
      
        // 用户创建
        rpc CreateUser(CreateUserRequest) returns (CreateUserReply){
            option (google.api.http) = {
                post: "/v1/user"
                body: "*"
            };
        }
    
    
    message User {
        int64 id = 1;
        string name = 2;
    }
    
    message CreateUserRequest {
        string name = 1 [(validate.rules).string = {min_len : 5, max_len: 50}];
    }
    
    message CreateUserReply {
        User User = 1;
    }
    

    proro文件中有参数校验,使用 proto-gen-validate 文档地址

    4.生成proto源码 文档地址

    kratos proto client api/user/user.proto
    

    5.生成server模板

    kratos proto server api/user/user.proto -t internal/service
    

    coding阶段

    打开 internal/service/user.go,代码如下:

    package service
    
    import (
    	"context"
    	"github.com/go-kratos/kratos/v2/log"
    	"users/internal/biz"
    
    	pb "users/api/user/v1"
    )
    
    type UserService struct {
    	pb.UnimplementedUserServer
    	uc *biz.UserUseCase
    	log *log.Helper
    }
    
    func NewUserService(uc *biz.UserUseCase, logger log.Logger) *UserService {
    	return &UserService{uc:uc, log: log.NewHelper(logger)}
    }
    
    // 用户创建
    func (s *UserService) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserReply, error) {
    	s.log.WithContext(ctx).Infof("CreateUser Received: %v", req)
    	user := biz.User{
    		Id:   0,
    		Name: req.Name,
    	}
    	return &pb.CreateUserReply{}, s.uc.Create(ctx, &user)
    }
    

    打开 internal/service/service.go,代码如下:

    package service
    
    import "github.com/google/wire"
    
    // ProviderSet is service providers.
    var ProviderSet = wire.NewSet(NewUserService)
    
    

    代码中引入了biz.User, 建立 ./internal/biz/user.go

    package biz
    
    import (
    	"context"
    	"github.com/go-kratos/kratos/v2/log"
    )
    
    type User struct {
    	Id int64
    	Name string
    }
    
    type UserRepo interface{
    	CreateUser(ctx context.Context, user *User) error
    }
    
    type UserUseCase struct{
    	repo UserRepo
    	log *log.Helper
    }
    
    func NewUserUseCase(repo UserRepo, logger log.Logger) *UserUseCase {
    	return &UserUseCase{repo:repo, log: log.NewHelper(logger)}
    }
    // 创建
    func (uc *UserUseCase) Create(ctx context.Context, user *User) error {
    	return uc.repo.CreateUser(ctx, user)
    }
    

    修改 ./internal/biz/biz.go

    package biz
    
    import "github.com/google/wire"
    
    // ProviderSet is biz providers.
    var ProviderSet = wire.NewSet(NewUserUseCase)
    

    打开 ./internal/data/data.go

    package data
    
    import (
    	"users/internal/conf"
    
    	"github.com/go-kratos/kratos/v2/log"
    	"github.com/google/wire"
    
    	"gorm.io/driver/mysql"
    	"gorm.io/gorm"
    )
    
    // ProviderSet is data providers.
    var ProviderSet = wire.NewSet(NewData, NewUserRepo)
    
    // Data .
    type Data struct {
    	db *gorm.DB
    }
    
    // NewData .
    func NewData(conf *conf.Data, logger log.Logger) (*Data, func(), error) {
    	log :=  log.NewHelper(logger)
    	// mysql数据库连接
    	db, err := gorm.Open(mysql.Open(conf.Database.Source), &gorm.Config{});
    	if err != nil {
    		return nil, nil, err
    	}
    
    	d := &Data{
    		db: db,
    	}
    
    	return d, func() {
    		log.Info("message", "closing the data resources")
    	}, nil
    }
    

    建立 ./internal/data/user.go

    package data
    
    import (
    	"context"
    	"errors"
    	"github.com/go-kratos/kratos/v2/log"
    	"gorm.io/gorm"
    	"users/internal/biz"
    	"users/internal/data/model"
    )
    
    type userRepo struct {
    	data *Data
    	log  *log.Helper
    }
    
    
    func (u userRepo) CreateUser(ctx context.Context, user *biz.User) error {
    	// 判断名称是否存在,存在则返回错误
    	record := u.GetUserByName(user.Name)
    	if record.Id != 0 {
    		return errors.New("用户名已存在")
    	}
    	return u.data.db.Model(&model.User{}).Create(&model.User{
    		Id:   0,
    		Name: user.Name,
    	}).Error
    }
    
    func NewUserRepo(data *Data, logger log.Logger) biz.UserRepo {
    	return &userRepo{
    		data: data,
    		log:  log.NewHelper(logger),
    	}
    }
    
    
    

    建立 ./internal/data/model/user.go

    package model
    
    type User struct{
    	Id int64 `json:"id"`
    	Name string `json:"name"`
    }
    
    
    func (User) TableName() string {
    	return "user"
    }
    

    修改./internal/server/http.go

    package server
    
    import (
    	"github.com/go-kratos/kratos/v2/log"
    	"github.com/go-kratos/kratos/v2/middleware/logging"
    	"github.com/go-kratos/kratos/v2/middleware/metrics"
    	"github.com/go-kratos/kratos/v2/middleware/recovery"
    	"github.com/go-kratos/kratos/v2/middleware/tracing"
    	"github.com/go-kratos/kratos/v2/middleware/validate"
    	"github.com/go-kratos/kratos/v2/transport/http"
    
    	v1 "users/api/user/v1"
    	"users/internal/conf"
    	"users/internal/service"
    )
    
    // NewHTTPServer new a HTTP server.
    func NewHTTPServer(c *conf.Server, user *service.UserService, logger log.Logger) *http.Server {
    	var opts = []http.ServerOption{
    		http.Middleware(
    			recovery.Recovery(),
    			tracing.Server(),
    			logging.Server(logger),
    			metrics.Server(),
    			validate.Validator(),
    		),
    	}
    	if c.Http.Network != "" {
    		opts = append(opts, http.Network(c.Http.Network))
    	}
    	if c.Http.Addr != "" {
    		opts = append(opts, http.Address(c.Http.Addr))
    	}
    	if c.Http.Timeout != nil {
    		opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
    	}
    	srv := http.NewServer(opts...)
    	v1.RegisterUserHTTPServer(srv, user)
    	return srv
    }
    

    修改./internal/server/grpc.go

    package server
    
    import (
    	"github.com/go-kratos/kratos/v2/log"
    	"github.com/go-kratos/kratos/v2/middleware/logging"
    	"github.com/go-kratos/kratos/v2/middleware/metrics"
    	"github.com/go-kratos/kratos/v2/middleware/recovery"
    	"github.com/go-kratos/kratos/v2/middleware/tracing"
    	"github.com/go-kratos/kratos/v2/middleware/validate"
    	"github.com/go-kratos/kratos/v2/transport/grpc"
    
    	v1 "users/api/user/v1"
    	"users/internal/conf"
    	"users/internal/service"
    )
    
    // NewGRPCServer new a gRPC server.
    func NewGRPCServer(c *conf.Server, user *service.UserService, logger log.Logger) *grpc.Server {
    	var opts = []grpc.ServerOption{
    		grpc.Middleware(
    			recovery.Recovery(),
    			tracing.Server(),
    			logging.Server(logger),
    			metrics.Server(),
    			validate.Validator(),
    		),
    	}
    	if c.Grpc.Network != "" {
    		opts = append(opts, grpc.Network(c.Grpc.Network))
    	}
    	if c.Grpc.Addr != "" {
    		opts = append(opts, grpc.Address(c.Grpc.Addr))
    	}
    	if c.Grpc.Timeout != nil {
    		opts = append(opts, grpc.Timeout(c.Grpc.Timeout.AsDuration()))
    	}
    	srv := grpc.NewServer(opts...)
    	v1.RegisterUserServer(srv, user)
    	return srv
    }
    

    修改配置文件

    打开 ./configs/config.yaml,修改成自己的数据库

    server:
      http:
        addr: 0.0.0.0:8000
        timeout: 1s
      grpc:
        addr: 0.0.0.0:9000
        timeout: 1s
    data:
      database:
        driver: mysql
        source: root: root@tcp(127.0.0.1:3306)/kratos_user?charset=utf8&parseTime=True&loc=Local
      redis:
        addr: 127.0.0.1:6379
        read_timeout: 0.2s
        write_timeout: 0.2s
    

    项目编译

    生成所有proto源码、wire等等

    go generate ./...
    

    运行项目

    kratos run
    

    发起请求 (postman)

    POST localhost:8000/v1/user
    
    {
        "name":"周周周周周"
    }
    

    以上是单个http接口请求,完整的增删改查自行下载

    链接: https://pan.baidu.com/s/1mfUGAFr4YA3GtQUJ9Gd6TQ  密码: 2cma
    
  • 相关阅读:
    使用hugo在gitee上写blog
    golang初识2
    golang初识1
    install go on ubuntu
    sql优化的几种方式
    UpdatePanel 无刷新弹出窗口
    .net web 点击链接在页面指定位置显示DIV的问题
    重建主键
    sql 日期时间格式转换
    UpdatePanel无法直接弹出窗口的解决
  • 原文地址:https://www.cnblogs.com/zhouqi666/p/15160796.html
Copyright © 2020-2023  润新知