go-zero快速入门

go-zero

项目地址
晓智科技晓智科技
晓智文档晓智文档
源码地址源码地址
文档源码文档源码

环境安装

  1. 安装 goctl
go install github.com/zeromicro/go-zero/tools/goctl@latest
  1. 安装 protoc
goctl env check --install --verbose --force

go get -u github.com/zeromicro/go-zero@latest
  1. 加载环境变量
export GOPATH="/Users/zhangdezhi/Documents/go"
export GOBIN="${PATH}:/bin"

生成 api 服务

goctl api new api
cd /api
go run api.go

mac 安装etcd

  1. 下载etcd
brew install etcd
  1. 启动etcd
brew services start etcd 
  1. 查看应用列表
brew services list
  1. 查看应用列表
brew services list
  1. 停止etcd
brew services stop etcd 

goctl生成微服务

  1. 编写proto文件
syntax = "proto3";

package user;

option go_package = "./user";

message IdRequest  {
  string  id = 1;
}

message UserResponse {
  // 用户id
  string  id = 1;
  // 用户名
  string name = 2;
  // 性别
  bool  gender = 3;
}

service User {
  rpc getUserInfo(IdRequest) returns(UserResponse);
}
  1. 通过proto文件生成微服务
# 切换到user.proto同级目录下
goctl rpc protoc user.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
  1. 运行rpc服务
go mod tidy
go run user.go

api服务调用rpc服务

  1. 添加rpc配置
// video/internal/config/config.go
package config

import (
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/zrpc"
)

type Config struct {
	rest.RestConf
    // rpc服务地址
	userRpc zrpc.RpcClientConf
}

  1. 完善服务依赖
package svc

import (
	"github.com/zeromicro/go-zero/zrpc"
	"go-zero/user/userclient"
	"go-zero/video/internal/config"
)

type ServiceContext struct {
	Config  config.Config
    // 服务依赖
	UserRpc userclient.User
}

func NewServiceContext(c config.Config) *ServiceContext {
	return &ServiceContext{
		Config:  c,
        // 服务依赖
		UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
	}
}
  1. 提供对外api
package logic
import (
	"context"
	"fmt"
	"go-zero/user/pb/user"

	"go-zero/video/internal/svc"
	"go-zero/video/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type VideoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewVideoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VideoLogic {
	return &VideoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *VideoLogic) Video(req *types.Request) (resp *types.Response, err error) {
	// todo: add your logic here and delete this line
	info, err := l.svcCtx.UserRpc.GetUserInfo(l.ctx, &user.IdRequest{
		Id: "1",
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(info)

	return &types.Response{Message:info.Name}, nil
}

接口服务api语法

  1. 简单路由服务
syntax = "v1"
type Request {
	Id string `json:"id"`
}
type Response {
	Id     string `json:"id"`
	Name   string `json:"name"`
	Gender bool   `json:"gender"`
}
service video-api {
	@handler VideoHandler
	get /api/v1/user/:id (Request) returns (Response)
}
  1. 生成对应路由
# video.api路由api
goctl api go -api video.api -dir .
  1. 编写报务接口
package logic

import (
	"context"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"go-zero/user/pb/user"
	"go-zero/video/internal/svc"
	"go-zero/video/internal/types"
)

type VideoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewVideoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VideoLogic {
	return &VideoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *VideoLogic) Video(req *types.Request) (resp *types.Response, err error) {
	// 提供对外服务
	info, err := l.svcCtx.UserRpc.GetUserInfo(l.ctx, &user.IdRequest{
		Id: "1",
	})
	if err != nil {
		panic(err)
	}
	return &types.Response{
		Id:     info.Id,
		Name:   info.Name,
		Gender: info.Gender,
	}, nil
}

  1. api前
@server (
	prefix: /api/users
)

操作mysql

  • go-zero对应文档地址mysql
  1. 编写proto文件
syntax = "proto3";
package user;
option go_package = "./user";

message IdRequest  {
  string  id = 1;
}

message UserResponse {
  // 用户id
  string  id = 1;
  // 用户名
  string name = 2;
  // 性别
  bool gender = 3;
}
message UserRequest{
  // 生名
  string name = 1;
  // 密码
  string password = 2;
  // 手机号
  string mobile = 3;
}
message UserOkResponse{
  string message = 1;
}

//goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.

service User {
  // createUser创建用户
  rpc createUser(UserRequest) returns(UserOkResponse);
  // getUserInfo获取用户信息
  rpc getUserInfo(IdRequest) returns(UserResponse);
}
  1. 生成对应的代码
# 切到和user.proto同级目录下
goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.
  1. 编写mydql ddl文件
# user/models
CREATE TABLE users
(
    id        bigint AUTO_INCREMENT,
    name      varchar(255) NOT NULL DEFAULT '' COMMENT '用户名',
    password  varchar(255) NOT NULL DEFAULT '' COMMENT '密码',
    mobile    varchar(255) NOT NULL DEFAULT '' COMMENT '手机号',
    gender    char(10)     NOT NULL DEFAULT 'male' COMMENT 'gender,male|female|unknown',
    create_at timestamp NULL,
    update_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE mobile_index (mobile),
    UNIQUE name_index (name),
    PRIMARY KEY (id)
) ENGINE = InnoDB COLLATE utf8mb4_general_ci COMMENT 'users table';
  1. 生成mysql操作代码
cd ~/workspace/model/mysql
goctl model mysql ddl --src user.sql --dir . -c
  1. 编写配置文件
Name: user.rpc
ListenOn: 0.0.0.0:8080
Etcd:
  Hosts:
  - 127.0.0.1:2379
  Key: user.rpc

Mysql:
  DataSource: "root:12345678@tcp(127.0.0.1:3306)/zero?charset=utf8mb4&parseTime=True&loc=Local"

Cache:
- Host: "127.0.0.1:6379"
  Type: "node"
  Pass:
  1. 添加配置文件
//interal/config
package config
import (
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/zrpc"
)
type Config struct {
	zrpc.RpcServerConf
	Mysql struct {
		DataSource string
	}
	// redis配置
	Cache cache.CacheConf
}
  1. 添加context
//interal/srv
package svc
import (
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"go-zero/user/internal/config"
	"go-zero/user/models"
)
type ServiceContext struct {
	Config    config.Config
	UserModel models.UsersModel
}
func NewServiceContext(c config.Config) *ServiceContext {
	sqlConn := sqlx.NewMysql(c.Mysql.DataSource)
	return &ServiceContext{
		Config:    c,
		UserModel: models.NewUsersModel(sqlConn, c.Cache),
	}
}
  1. 编写业务逻辑
//internal/logic

package logic

import (
	"context"
	"go-zero/user/models"

	"go-zero/user/internal/svc"
	"go-zero/user/user"

	"github.com/zeromicro/go-zero/core/logx"
)

type CreateUserLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewCreateUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateUserLogic {
	return &CreateUserLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// CreateUser 创建用户
func (l *CreateUserLogic) CreateUser(in *user.UserRequest) (*user.UserOkResponse, error) {
	_, err := l.svcCtx.UserModel.Insert(l.ctx, &models.Users{
		Name:     in.Name,
		Password: in.Password,
		Mobile:   in.Mobile,
	})
	if err != nil {
		panic(err)
	}
	return &user.UserOkResponse{Message: "创建用户成功"}, nil
}

中间件middleware的使用

  1. 编写api接口
syntax = "v1"
type URequest {
	id string `json:"id"`
}

type ULoginResponse {
	Token   string `json:"token"`
	Message string `json:"message"`
}

type UInfoResponse {
	Id     string `json:"id"`
	Name   string `json:"name"`
	Mobile string `json:"mobile"`
	Gender string `json:"gender"`
}

service user {
	@handler LoginHandler
	post /user/login (URequest) returns (ULoginResponse)
}

// 添加中间件
@server (
	middleware: LoginVerification
)
service user {
	// 添加中间件检验
	@handler GetUserInfoHandler
	get /user/info (URequest) returns (UInfoResponse)
}
  1. 添加中间件context
//internal/srv
package svc

import (
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/zrpc"
	"go-zero/api/internal/config"
	"go-zero/api/internal/middleware"
	"go-zero/user/userclient"
)

type ServiceContext struct {
	Config config.Config
	userclient.User
	LoginVerification rest.Middleware
}

func NewServiceContext(c config.Config) *ServiceContext {
	return &ServiceContext{
		Config:            c,
		User:              userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
		LoginVerification: middleware.NewLoginVerificationMiddleware().Handle,
	}
}
  1. 编写中间件给验证
package middleware

import (
	"fmt"
	"net/http"
)

type LoginVerificationMiddleware struct {
}

func NewLoginVerificationMiddleware() *LoginVerificationMiddleware {
	return &LoginVerificationMiddleware{}
}

func (m *LoginVerificationMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Println(r.Header.Get("token"))
		if r.Header.Get("token") == "go-zero" {
			next(w, r)
			return
		}
		_, err := w.Write([]byte("您没有权限"))
		if err != nil {
			panic(err)
		}
		return
	}
}

api服务调用rpc

  1. yaml配置rpc服务发现
Name: user
Host: 0.0.0.0
Port: 8888
## 让ectc发现rpc
UserRpc:
  Etcd:
    Hosts:
      - 127.0.0.1:2379
    Key: user.rpc
  1. 添加rpc调用配置
// internal/config
package config
import (
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/zrpc"
)

type Config struct {
	rest.RestConf
	// 调用rpc配置
	UserRpc zrpc.RpcClientConf
}
  1. 添加context
// internal/srv
package svc

import (
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/zrpc"
	"go-zero/api/internal/config"
	"go-zero/api/internal/middleware"
	"go-zero/user/userclient"
)

type ServiceContext struct {
	Config config.Config
	// 调用rpc
	userclient.User
	LoginVerification rest.Middleware
}

func NewServiceContext(c config.Config) *ServiceContext {
	return &ServiceContext{
		Config:            c,
		// 调用rpc 
		User:              userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
		LoginVerification: middleware.NewLoginVerificationMiddleware().Handle,
	}
}
  1. 编写调用逻辑
//internal/logic
package logic
import (
	"context"
	"go-zero/user/userclient"

	"go-zero/api/internal/svc"
	"go-zero/api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetUserInfoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserInfoLogic {
	return &GetUserInfoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}
func (l *GetUserInfoLogic) GetUserInfo(req *types.URequest) (resp *types.UInfoResponse, err error) {
	info, err := l.svcCtx.User.GetUserInfo(l.ctx, &userclient.IdRequest{
		Id: req.Id,
	})
	if err != nil {
		panic(err)
	}

	return &types.UInfoResponse{
		Id:     info.Id,
		Name:   info.Name,
		Mobile: info.Mobile,
		Gender: info.Gender,
	}, nil
}

公众号
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值