go zero手把手教你入门案例

news2024/11/16 21:52:14

一、入门案例

  • 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 .
    

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字音频工作站FL Studio21.1中文版本如何下载?

在现在这个数字音乐时代,各种音乐中都或多或少有些电子音乐的影子,或是合成器音色、或是通过数字效果器制作出的变幻莫测的变化效果。而小马丁、Brooks、Eliminate等众多电子音乐巨头便是使用FL Studio来制作音乐的。今天小编就以FL Studio五年的资深用户…

⑩④【MySQL】什么是视图?怎么用?视图的检查选项? 视图的作用?[VIEW]

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ 视图VIEW ⑩④详解MySQL视图1. 视图的基本使用…

U盘如何自定义图标?

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

CAD Exchanger SDK 3.23.0 的亮点

代号“CAD Exchanger MTK”的新兴产品首次亮相,支持新版本的流行格式,重新设计的 BIM 模型结构以及 3.23.0 中的 SDK 文档修订 阅读最新版本编写的 Autodesk Inventor 和 NX 文件,享受更严格的 BIM 模型结构,轻松浏览 SDK 文档&am…

三次握手和四次握手到底有啥区别?

1. 三次握手 TCP 协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保 证连接的可靠。 • 第一次握手,客户端向服务器端发起 TCP 连接的请求• 第二次握手,服务器端发送针对客户端 TCP 连接请求的确认•…

FISCO BCOS 3.0【01】搭建第一个区块链网络

官方技术文档:https://fisco-bcos-doc.readthedocs.io/zh-cn/latest/index.html 我们在官方技术文档的基础上,进行,对文档中一些不清楚的地方进行修正 搭建Air版本FISCO BCOS联盟链 本节以搭建单群组FISCO BCOS链为例操作,使用开…

NPDP 02组合管理

NPDP 产品经理认证知识体系指南解读,02组合管理 第二章 组合管理 公司战略或经营战略以及创新战略,为竞争性创新投资之间的权衡决策提供了整体方向和框架。在发展和持续性维护一个组织的产品组合时,总要面对一系列彼此竞争资源和投资的项目。…

Spring Cloud学习(九)【Elasticsearch 分布式搜索引擎01】

文章目录 初识 elasticsearch了解 ES倒排索引ES 的一些概念安装es、kibana安装elasticsearch部署kibana 分词器安装IK分词器ik分词器-拓展词库 索引库操作mapping 映射属性索引库的 CRUD 文档操作添加文档查看、删除文档修改文档Dynamic Mapping RestClient 操作索引库什么是Re…

Docker之DockerFile解析

DockerFile解析 是什么 Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。 概述 官网 https://docs.docker.com/engine/reference/builder/ 构建三步骤 编写Dockerfile文件 docker build命令构建镜像 docker run依镜像运…

轻地图+数据闭环加速落地,觉非科技获多家头部车企定点

‍作者 |张祥威 编辑 |德新 智能驾驶日益普及,「轻地图」和「数据闭环」成为各家能力比拼的关键,车企对此的需求也逐渐迫切。 11月16日,觉非科技宣布已与多家头部主机厂达成量产定点合作,围绕轻地图与数据闭环服务,支…

人工智能Keras的第一个图像分类器(CNN卷积神经网络的图片识别)

CNN卷积神经网络是人工智能的开端,CNN卷积神经网络让计算机能够认识图片,文字,甚至音频与视频。CNN卷积神经网络的基础知识,可以参考:CNN卷积神经网络 LetNet体系结构是卷积神经网络的“第一个图像分类器”。最初设计用于对手写数字进行分类,上期文章我们分享了如何使用k…

.Net6 部署到IIS示例

基于FastEndpoints.Net6 框架部署到IIS 环境下载与安装IIS启用与配置访问网站 环境下载与安装 首先下载环境安装程序,如下图所示,根据系统位数选择x86或者x64进行下载安装,网址:Download .NET 6.0。 IIS启用与配置 启用IIS服务 打开控制面板&#xff…

深度学习基础知识——从人工神经网络开始

一、介绍 您知道第一个神经网络是在 20 世纪 50 年代初发现的吗? 深度学习 (DL) 和神经网络 (NN) 目前正在推动本世纪一些最巧妙的发明。他们从数据和环境中学习的令人难以置信的能力使他们成为机器学习科学家的首选。 深度学习和神经网络是自动驾驶汽车、图像识别软…

AI先行者第三辑:石油专家正在加速“吸入”AI养分

AI对于石油行业而言,绝不是一个非此即彼、非黑即白、有用或者无用的简单命题,而是一个如何不断深入去提升效率,逐步证明自己价值的过程。 本篇作者安鹏,中国海洋石油集团有限公司信息技术中心 技术中台工程师;AICA首席…

22款奔驰S450L升级钢琴内饰板 完美的融合进去

钢琴拉丝桃木面板装车让人眼前一亮,内饰的豪华度和高级感立马提升一个等级,带条纹的亮面烤漆,温润高端。 为什么升级更换桃木饰板?因为升级桃木饰板可以更换掉一些镀铬银色的装饰件,这样就可以让整车的豪华感大大的提升…

qt library创建和使用

1、创建library 2、修改library中的代码 3、把library进行编译,编译后会生成相关文件 4、把编译后的文件拷贝到主程序目录下面。 5、并把library中的testlib头文件拷贝到主程序,并在pro文件加入(这里在后面使用library中函数有关&#xff0…

基于LeNet实现手写体数字识别实验

目录 1 数据 1.1 数据预处理 2 模型构建 2.1 自定义算子实现 2.2 Pytorch框架实现 2.3 测试两个网络的运算速度 2.4 两个网络加载同样的权重,两个网络的输出结果是否一致? 2.5 计算模型的参数量和计算量。 3 模型训练 4 模型评价 5 模型预测 总结…

专攻数学的Prompt:使GPT-3解数学题准确率升至92.5%

专攻数学的Prompt:使GPT-3解数学题准确率升至92.5% 写在最前面示例(试过了,难点的和普通输出差不多;只能说,比简单的题目输出内容更丰富一些)MathPrompter解题示例 机理MathPrompter是怎么工作的&#xff0…

秋招算法高频算法笔试题

自己在秋招过程中遇到的算法笔试题,包含中大厂,都附解析! 汽水瓶 如果汽水瓶数目为1或者0,那么一瓶都喝不到 如果汽水瓶数目为2或者3,那么只能喝到一瓶 如果为2,喝到一瓶后手里一个瓶子都没有了&#xff…

Flume学习笔记(3)—— Flume 自定义组件

前置知识: Flume学习笔记(1)—— Flume入门-CSDN博客 Flume学习笔记(2)—— Flume进阶-CSDN博客 Flume 自定义组件 自定义 Interceptor 需求分析:使用 Flume 采集服务器本地日志,需要按照日志…