go zero手把手教你入门案例

一、入门案例

  • 1、在黑窗口上安装

    go install github.com/zeromicro/go-zero/tools/goctl@latest
    
  • 2、使用goland创建一个项目

  • 3、在项目中安装依赖

    go get -u github.com/zeromicro/go-zero@latest
    
  • 4、模拟创建一个user的项目

    goctl api new user
    
  • 5、安装依赖包

    go mod tidy
    
  • 6、补充代码段

    func (l *UserLogic) User(req *types.Request) (resp *types.Response, err error) {
    	// todo: add your logic here and delete this line
    
    	return &types.Response{
    		Message: "你好,水痕",
    	}, nil
    }
    
  • 7、在浏览器上输入http://localhost:8888/from/me,关于为什么是me可以查看types.go文件

    package types
    
    type Request struct {
    	Name string `path:"name,options=you|me"`
    }
    
  • 8、关于user项目目录解说

    .
    ├── etc
    │   └── user-api.yaml # 配置文件
    ├── internal 
    │   ├── config
    │   │   └── config.go
    │   ├── handler
    │   │   ├── routes.go # 路由文件
    │   │   └── userhandler.go # 可以理解为控制层
    │   ├── logic
    │   │   └── userlogic.go # 可以理解为服务层
    │   ├── svc
    │   │   └── servicecontext.go
    │   └── types
    │       └── types.go # 可以理解为DTO、VO
    ├── user.api
    └── user.go # 启动文件
    
    7 directories, 9 files
    

二、自己编写api文件来生成别的文件

  • 1、创建一个空的module项目

  • 2、在根目录下创建一个user.api的文件

    type LoginRequest {
    	Username string `json:"username"`
    	Password string `json:"password"`
    }
    
    type LoginResponse {
    	Code    int64  `json:"code"`
    	Data    string `json:"data"`
    	Message string `json:"message"`
    }
    
    type UserInfo {
    	Id       int64  `json:"id"`
    	Username string `json:"username"`
    }
    
    type UserInfoResponse {
    	Code    int64    `json:"code"`
    	Data    UserInfo `json:"data"`
    	Message string   `json:"message"`
    }
    // 定义要被方法的方法
    service users {
    	@handler login
    	post /api/users/login (LoginRequest) returns (LoginResponse)
    
    	@handler userInfo
    	get /api/users/userInfo returns (UserInfoResponse)
    }
    
  • 3、执行脚本

    goctl api go -api user.api -dir .
    
  • 4、等生成文件后,安装依赖包

  • 5、书写一个获取用户信息的代码

    
    func (l *UserInfoLogic) UserInfo() (resp *types.UserInfoResponse, err error) {
    	// todo: add your logic here and delete this line
    	return &types.UserInfoResponse{
    		Code:    0,
    		Message: "请求成功",
    		Data: types.UserInfo{
    			Id:       1,
    			Username: "水痕",
    		},
    	}, nil
    }
    
  • 6、运行启动

三、封装自定义返回模板

  • 1、创建一个utils的文件夹

    package utils
    
    import (
    	"github.com/zeromicro/go-zero/rest/httpx"
    	"net/http"
    )
    
    type Body struct {
    	Code    int         `json:"code"`
    	Message string      `json:"message"`
    	Result  interface{} `json:"result,omitempty"`
    }
    
    func Response(w http.ResponseWriter, code int, message string, data interface{}) {
    	httpx.OkJson(w, Body{
    		Code:    code,
    		Message: message,
    		Result:  data,
    	})
    }
    
    // Success 成功的请求
    func Success(w http.ResponseWriter, data interface{}) {
    	Response(w, 0, "请求成功", data)
    }
    
    // Fail 失败的请求
    func Fail(w http.ResponseWriter, message string) {
    	Response(w, 1, message, nil)
    }
    
  • 2、定义api的时候就可以去除这些固定的写法

    type LoginRequest {
    	Username string `json:"username"`
    	Password string `json:"password"`
    }
    
    type UserInfoResponse {
    	Id       int64  `json:"id"`
    	Username string `json:"username"`
    }
    // 定义要被方法的方法
    service users {
    	@handler login
    	post /api/users/login (LoginRequest) returns (string )
    
    	@handler userInfo
    	get /api/users/userInfo returns (UserInfoResponse)
    }
    
  • 3、重新执行转换脚本

    goctl api go -api user.api -dir .
    
  • 4、改写代码,后运行

四、统一前缀

  • 1、上面每次在service里面都要写/api/users/这个路径,如果都是一样的,可以提取出去统一到前面

    // 定义要被方法的方法
    @server(
    	prefix: /api/users
    )
    service users {
    	@handler login
    	post /login (LoginRequest) returns (string)
    
    	@handler userInfo
    	get /userInfo returns (UserInfoResponse)
    }
    
  • 2、重新转换下

五、jwt的使用

  • 1、改写user.api文件

    type LoginRequest {
    	Username string `json:"username"`
    	Password string `json:"password"`
    }
    
    type UserInfoResponse {
    	Id       int64  `json:"id"`
    	Username string `json:"username"`
    }
    // 定义要被方法的方法
    @server(
    	prefix: /api/users
    )
    service users {
    	@handler login
    	post /login (LoginRequest) returns (string)
    }
    
    @server(
    	prefix: /api/users
    	jwt: Auth
    )
    service users {
    	@handler userInfo
    	get /userInfo returns (UserInfoResponse)
    }
    
  • 2、重新执行转换文件的脚本

    goctl api go -api user.api -dir .
    goctl api go -api *.api -dir .
    
  • 3、在etc/users.yaml文件中添加jwt的配置

    Name: users
    Host: 0.0.0.0
    Port: 8888
    Auth:
      AccessSecret: test1test1  # 随机一个数就可以
      AccessExpire: 3600 # 过期时间
    
  • 4、在internal/config/config.go中配置,任何在yaml中添加的配置都要在config.go中添加配置

    package config
    
    import "github.com/zeromicro/go-zero/rest"
    
    type Config struct {
    	rest.RestConf
    	Auth struct {
    		AccessSecret string
    		AccessExpire int64
    	}
    }
    
  • 5、在utils文件夹下创建一个jwt.go的文件

    package utils
    
    import (
    	"errors"
    	"github.com/golang-jwt/jwt/v4"
    	"time"
    )
    
    // JwtPayLoad jwt中payload数据
    type JwtPayLoad struct {
    	UserID   uint   `json:"userId"`   // 用户id
    	Username string `json:"username"` // 用户名
    }
    
    type CustomClaims struct {
    	JwtPayLoad
    	jwt.RegisteredClaims
    }
    
    // GenToken 创建 Token
    func GenToken(user JwtPayLoad, accessSecret string, expires int64) (string, error) {
    	claim := CustomClaims{
    		JwtPayLoad: user,
    		RegisteredClaims: jwt.RegisteredClaims{
    			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * time.Duration(expires))),
    		},
    	}
    
    	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)
    	return token.SignedString([]byte(accessSecret))
    }
    
    // ParseToken 解析 token
    func ParseToken(tokenStr string, accessSecret string, expires int64) (*CustomClaims, error) {
    
    	token, err := jwt.ParseWithClaims(tokenStr, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
    		return []byte(accessSecret), nil
    	})
    	if err != nil {
    		return nil, err
    	}
    	if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
    		return claims, nil
    	}
    	return nil, errors.New("invalid token")
    }
    
  • 6、在登录的时候返回token给前端

    func (l *LoginLogic) Login(req *types.LoginRequest) (resp string, err error) {
    	// TODO 模拟查询数据库操作
    	if req.Username == "admin" && req.Password == "123456" {
    		auth := l.svcCtx.Config.Auth
    		token, err := utils.GenToken(utils.JwtPayLoad{
    			UserID:   1,
    			Username: req.Username,
    		}, auth.AccessSecret, auth.AccessExpire)
    		if err != nil {
    			fmt.Println("生成token失败")
    			return "", errors.New("账号或密码错误")
    		}
    		return token, nil
    	} else {
    		return "", errors.New("账号或密码错误")
    	}
    }
    
  • 7、在需要从token中获取用户信息

    func (l *UserInfoLogic) UserInfo() (resp *types.UserInfoResponse, err error) {
    	// todo: add your logic here and delete this line
    	// 从请求头中获取token,解析出来
    	userId := l.ctx.Value("userId").(json.Number)
    	fmt.Println(userId)
    	fmt.Printf("数据类型:%v,%T\n", userId, userId)
    	username := l.ctx.Value("username").(string)
    	fmt.Println(username)
    	uid, _ := userId.Int64()
    	return &types.UserInfoResponse{
    		Id:       uid,
    		Username: username,
    	}, nil
    }
    
  • 8、登录接口生成token

  • 9、测试获取用户信息

    {
    	"Authorization":"Bearer eyJhbGciOiJIUzI1Ni"
    }
    

    在这里插入图片描述

六、获取客户端参数

  • 1、获取path参数,url上请求的地址为:``,这里xx就是要获取的地址

    type MessageReq {
        Id int64  `path:"id"`
    }
    @server(
        prefix: /api/messages
    )
    service users {
       
        @handler message
        get /message/:id(MessageReq) returns (string)
    }
    
  • 2、获取query参数,url上请求的地址为localhost:8888/api/message?name=xx&age=zz

    type MessageInfoReq {
        Name string `form:"name"`
        Age int64 `form:"age"`
    }
    
    
    @server(
        prefix: /api/messages
    )
    service users {
        @handler messageInfo
        get /messageInfo(MessageInfoReq) returns (string)
    }
    
  • 3、获取post提交的json数据

    type LoginRequest {
    	Username string `json:"username"`
    	Password string `json:"password"`
    }
    
    @server(
    	prefix: /api/users
    )
    service users {
    	@handler login
    	post /login (LoginRequest) returns (string)
    }
    
  • 4、接收方法根据转码后会自动生成,且都是一样的

    var req types.MessageReq
    if err := httpx.Parse(r, &req); err != nil {
        httpx.ErrorCtx(r.Context(), w, err)
        return
    }
    // 直接从req中获取数据就可以
    

七、一个项目下多个api文件

  • 1、在实际开发中,我更喜欢一张表就对应一个api文件,这样更好维护,唯一注意点就是每个文件里面的service users这个users是要一样的就可以,实际根据你项目来写的

  • 2、在根目录下创建一个api的文件夹,里面包括message.apiuser.api

  • 3、message.api文件内容

    syntax = "v2"
    
    type MessageInfoReq {
        Name string `form:"name,default=word"`
        Age int64 `form:"age,default=20"`
    }
    
    type MessageReq {
        Id int64  `path:"id"`
    }
    @server(
        prefix: /api/messages
    )
    service users {
        @handler messageInfo
        get /messageInfo(MessageInfoReq) returns (string)
    
        @handler message
        get /message/:id(MessageReq) returns (string)
    }
    
  • 4、user.api文件内容

    syntax = "v2"
    
    type LoginRequest {
    	Username string `json:"username"`
    	Password string `json:"password"`
    }
    
    type UserInfoResponse {
    	Id       int64  `json:"id"`
    	Username string `json:"username"`
    }
    // 定义要被方法的方法
    @server(
    	prefix: /api/users
    )
    service users {
    	@handler login
    	post /login (LoginRequest) returns (string)
    }
    
    @server(
    	prefix: /api/users
    	jwt: Auth
    )
    service users {
    	@handler userInfo
    	get /userInfo returns (UserInfoResponse)
    }
    
  • 5、根目录下创建一个api.api的文件

    syntax = "v2"
    
    import "api/user.api"
    import "api/message.api"
    
  • 6、运行转码命令

    goctl api go -api api.api -dir .
    # 或者直接使用下面的
    goctl api go -api *.api -dir .
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/160508.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java 算法篇-链表的经典算法:有序链表去重、合并多个有序链表

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 链表的说明 2.0 有序链表去重的实现方式 2.1 有序链表去重(保留重复的节点) - 使用递归来实现 2.2 有序链表去重(保留重复的节点) - 使用双指针来实现 2.3 有序…

U盘如何自定义图标?

1、准备一张图片,转换为.ico格式,转换格式的工具推荐一个ToYcon 转换好后放到拷贝到u盘里面。 2、在u盘里面新建一个文本文档,在文档里面写入以下内容,注意,这里的test为图片的名称。 根据自己图片名称做一下修改。 […

三十二、W5100S/W5500+RP2040树莓派Pico<UPnP示例>

文章目录 1 前言2 简介2 .1 什么是UPnP?2.2 UPnP的优点2.3 UPnP数据交互原理2.4 UPnP应用场景 3 WIZnet以太网芯片4 UPnP示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 随着智能家居、物联网等…

6.7二叉树的最小深度(LC111)

审题要清楚: 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意是叶子节点(左右孩子都为空的节点才是叶子节点!)。 算法: 既可以求最小高度,也可以直接求深度。 最小高度: 后序…

4M防错追溯与MES管理系统的融合应用

在现代化制造业中,质量追溯已成为企业核心竞争力的重要组成部分。为了实现精确的质量追溯,制造企业广泛采用了MES管理系统解决方案来进行生产过程中的数据管理。本文将探讨如何通过MES管理系统实现4M防错追溯,并提升企业的生产与管理效率。 一…

软件质量保护与测试(第2版)学习总结第十三章 集成测试

很多人都认为微软是一家软件开发公司,事实上我们是一家软件测试公司。 ---比尔盖茨 集成测试是在单元测试的基础上将多个模块组合在一起进行测试的过程。 13.1.1 区别 单元测试主要关注模块内部,系统测试则是在用户的角度来评价系统&#xff…

第四篇 《随机点名答题系统》——基础设置详解(类抽奖系统、在线答题系统、线上答题系统、在线点名系统、线上点名系统、在线考试系统、线上考试系统)

目录 1.功能需求 2.数据库设计 3.流程设计 4.关键代码 4.1.设置题库 4.1.1数据请求示意图 4.1.2选择题库(index.php)数据请求代码 4.1.3取消题库(index.php)数据请求代码 4.1.4业务处理Service(xztk.p…

【高并发内存池】第一篇 项目简介及定长内存池

🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的…

Flume学习笔记(4)—— Flume数据流监控

前置知识: Flume学习笔记(1)—— Flume入门-CSDN博客 Flume学习笔记(2)—— Flume进阶-CSDN博客 Flume 数据流监控 Ganglia 的安装与部署 Ganglia 由 gmond、gmetad 和 gweb 三部分组成。 gmond(Ganglia …

MybatisPlus学习

一.快速入门 1.相关数据库创建 CREATE TABLE USER(id BIGINT(20) NOT NULL COMMENT 主键ID,NAME VARCHAR(30) NULL DEFAULT NULL COMMENT 姓名,age INT(11) NULL DEFAULT NULL COMMENT 年龄,email VARCHAR(50) NULL DEFAULT NULL COMMENT 邮箱,PRIMARY KEY (id));​​INSERT I…

BUG:编写springboot单元测试,自动注入实体类报空指针异常

原因:修饰测试方法的Test注解导入错误 造成错误的原因是 import org.junit.Test;正确的应该是 import org.junit.jupiter.api.Test前者是Junit4,后者是Junit5 junit4的使用似乎要在测试类除了添加SpringbootTest还要添加RunWith(SpringRunner.class) 同时要注意spring-boot-s…

制作翻页电子相册,这个工具你必须了解!

电子相册作为一种很有纪念意义的载体,无论是生日、旅行、结婚、毕业纪念等等,可以应用在很多场合当中,如何制作呢? 而对于不会制作电子相册的人来说,使用套用模板是最直接快速的方式了。所以,推荐大家使用…

Find My充电宝|苹果Find My技术与充电宝结合,智能防丢,全球定位

充电宝是一种个人可随身携带,自身能储备电能,主要为手持式移动设备等消费电子产品(例如无线电话、笔记本电脑)充电的便携充电器,特别应用在没有外部电源供应的场合。其主要组成部分包括:用作电能存储的电池…

C++软件开发面试场景题

自己在秋招过程中遇到的一些场景题 海量数据N取Top K个元素,复杂度是多少 在处理海量数据中获取前K个元素(Top K)的问题中,通常会使用一些高效的算法来减少时间和空间复杂度。以下是两种常见的解决方案和它们的复杂度&#xff1…

LeetCode热题100——图论

图论 1. 岛屿的数量2. 腐烂的橘子 1. 岛屿的数量 给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆…

PHP排序sort()、asort() 和 ksort() 的区别及用法

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师…

Centos(Linux)服务器安装Dotnet8 及 常见问题解决

1. 下载dotnet8 sdk 下载 .NET 8.0 SDK (v8.0.100) - Linux x64 Binaries 拿到 dotnet-sdk-8.0.100-linux-x64.tar.gz 文件 2. 把文件上传到 /usr/local/software 目录 mkdir -p /usr/local/software/dotnet8 把文件拷贝过去 mv dotnet-sdk-8.0.100-linux-x64.tar.gz /usr/loc…

多维时序 | MATLAB实现PSO-BiGRU-Attention粒子群优化双向门控循环单元融合注意力机制的多变量时间序列预测

多维时序 | MATLAB实现PSO-BiGRU-Attention粒子群优化双向门控循环单元融合注意力机制的多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-BiGRU-Attention粒子群优化双向门控循环单元融合注意力机制的多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 …

混沌系统在图像加密中的应用(基于哈密顿能量函数的混沌系统构造1.4)

混沌系统在图像加密中的应用(基于哈密顿能量函数的混沌系统构造1.4) 前言一、逆时间对称性分析二、具有逆时间对称性的单晶格状混沌与拟周期流1.逆时间对称性及哈密顿能量函数2.数值仿真 python代码 前言 续接混沌系统在图像加密中的应用(基…

数据科学家应该知道的 10 个高级深度学习架构!

一、介绍 跟上深度学习的最新进展变得非常困难。几乎每天都会出现深度学习的新创新或新应用。然而,这些进步大部分都隐藏在 ArXiv / Springer 等媒体上发表的大量研究论文中。 本文包含深度学习的一些最新进展以及 keras 库中的实现代码。我还提供了…