听说你还在自己做重复劳动?看我一键生成错误码映射

news2024/11/17 21:55:16

大家在工作中定义错误码的时候都是如何处理的? xdm 可以评论区交流交流

我看到过有的是这样定义错误码的:

m := make(map[int]string)
m[0] = "OK"
m[1] = "链接失败"
m[2] = "文件类型错误"
...

还看到过这样定义错误码的:

type myErr struct {
 code   int
 err    error
 extMsg interface{}
}

myOk := myErr{0,errors.New("PROCESS OK"),"xxx"}
myOk := myErr{1,errors.New("文件类型错误"),"xxx"}
myOk := myErr{2,errors.New("连接数据库失败"),"xxx"}
...

也有见到过这样做的:

const (
 ERR_OK          = 0
 ERR_CONN_REFUSE = 1
 ERR_FILE_NOT    = 2
)


var m = map[int]string{
    ERR_OK:          "OK",
    ERR_CONN_REFUSE: "链接被拒绝",
    ERR_FILE_NOT:    "文件不存在",
}

现在有一个更好的方法来实现我们工作中错误码的映射

引入 go generate

咱们引入 go generate ,可以只用定义错误码和写注释,就可以达到,当我们调用错误码的时候,能够正确的输出我们想要的错误信息

举个例子:

我们先建立如下目录,将错误码文件 errcode.go,放在一个单独的包里面

.
├── go.mod
├── main.go
└── mycodes
    └── errcode.go

我们还需要运用 stringer 工具,来辅助我们完成这个目标

go get golang.org/x/tools/cmd/stringer

我们来看看上述文件的内容:

./mycodes/errcode.go

/*
____  ___   _____ ___________
\   \/  /  /     \\__    ___/
 \     /  /  \ /  \ |    |
 /     \ /    Y    \|    |
/___/\  \\____|__  /|____|
      \_/        \/
createTime:2021/10/10
createUser:Administrator
*/
package mycodes

type ErrCode int64 //错误码
const (
        ERR_CODE_OK             ErrCode = 0 // PROCESS OK
        ERR_CODE_INVALID_PARAMS ErrCode = 1 // 参数无效
        ERR_CODE_TIMEOUT        ErrCode = 2 // 超时
        ERR_CODE_FILE_NOT_EXIST ErrCode = 3 // 文件不存在
        ERR_CODE_CONN_REFUSE    ErrCode = 4 // 连接被拒绝
        ERR_CODE_NET_ABNORMAL   ErrCode = 5 // 网络异常
)

main.go

/*
____  ___   _____ ___________
\   \/  /  /     \\__    ___/
 \     /  /  \ /  \ |    |
 /     \ /    Y    \|    |
/___/\  \\____|__  /|____|
      \_/        \/
createTime:2021/10/10
createUser:Administrator
*/
package main

import (
        "fmt"
        "myerr/mycodes"
)

func main() {
        fmt.Println(mycodes.ERR_CODE_CONN_REFUSE)
}

我们在 main.go 统计目录下初始化一下 go 的 模块, go mod init myerr

go.mod

module myerr

go 1.15

开始演示

我们直接在 main.go 的同级目录下执行 go run main.go,输出如下:

4

是 ERR_CODE_CONN_REFUSE 对应的枚举值 4 ,可是我们期望的课不是这个,我们是期望能直接输出错误码对应的错误信息

使用 stringer

手动在 mycodes 目录下使用刚才安装的 stringer 工具

stringer -linecomment -type ErrCode 

此处的 ErrCode 是错误码的类型 , 执行上述语句后,mycodes 生成了一个文件 errcode_string.go ,现在目录结构是这样的

.
├── go.mod
├── main.go
└── mycodes
    ├── errcode.go
    └── errcode_string.go

看看 errcode_string.go 内容

// Code generated by "stringer -linecomment -type ErrCode"; DO NOT EDIT.

package mycodes

import "strconv"

const _ErrCode_name = "PROCESS OK参数无效超时文件不存在连接被拒绝网络异常"

var _ErrCode_index = [...]uint8{0, 10, 22, 28, 43, 58, 70}

func (i ErrCode) String() string {
        if i < 0 || i >= ErrCode(len(_ErrCode_index)-1) {
                return "ErrCode(" + strconv.FormatInt(int64(i), 10) + ")"
        }
        return _ErrCode_name[_ErrCode_index[i]:_ErrCode_index[i+1]]
}

我们可以看出 stringer 工具,将我们的错误码信息映射的字符串全部合并起来放在 _ErrCode_name 常量中,且有 _ErrCode_index 来作为每一个错误码映射字符串的索引值 ,最终便能实现错误码和字符串的映射,这个就很简单吧

效果展示

此时,我们仍然在 main.go 的同级目录下执行 go run main.go,输出如下:

连接被拒绝

显示的正式我们期望的错误信息

stringer 工具

我们来看看 stringer 工具的帮助,在来详细学习一波

# stringer -h
Usage of stringer:
        stringer [flags] -type T [directory]
        stringer [flags] -type T files... # Must be a single package
For more information, see:
        http://godoc.org/golang.org/x/tools/cmd/stringer
Flags:
  -linecomment
        use line comment text as printed text when present
  -output string
        output file name; default srcdir/<type>_string.go
  -trimprefix prefix
        trim the prefix from the generated constant names
  -type string
        comma-separated list of type names; must be set

可以看到大的用法有 2 种:

 stringer [flags] -type T [directory]
 stringer [flags] -type T files... # Must be a single package

第一种可以在类型 T 后面加上目录

第二种可以指定类型 T 后面指定明确的文件,但是这种方式必须是在一个单独的包里面

参数如下:

  • -linecomment

使用行注释文本作为打印文本

  • -output string

输出文件名称;默认源目录下的 / <类型> _string.go,所以我们可以看到例子中我们的输出文件在 mycodes 下的 errcode_string.go

  • -trimprefix prefix

从生成的常量名称中修剪前缀

  • -type string

以逗号分隔的类型名称列表,这个参数是必须要设置的

go generate

刚才我们是在命令行中,使用 stringer 工具来生成的,那么我们要把这些东西放入项目代码中就需要使用 go generate 工具了

先大致了解一下 go generate 是个啥玩意

go generate 是 go 自带的一个工具,我们可以通过在命令行中查看到:

# go

咱们查看一下帮助文档 go help generate

# go help generate
...

Go generate scans the file for directives, which are lines of
the form,

        //go:generate command argument...

...

Go generate sets several variables when it runs the generator:

        $GOARCH
                The execution architecture (arm, amd64, etc.)
        $GOOS
                The execution operating system (linux, windows, etc.)
        $GOFILE
                The base name of the file.
        $GOLINE
                The line number of the directive in the source file.
        $GOPACKAGE
                The name of the package of the file containing the directive.
        $DOLLAR
                A dollar sign.

上面这些是 go generate 使用时候的环境变量

  • $GOARCH

体系架构(arm、amd64 等)

  • $GOOS

当前的 OS 环境(linux、windows 等)

  • $GOFILE

当前处理中的文件名

  • $GOLINE

当前命令在文件中的行号

  • $GOPACKAGE

当前处理文件的包名

go generate命令格式

go generate [-run regexp] [-n] [-v] [-x] [command] [build flags] [file.go... | packages]
参数说明如下:
-run 
正则表达式匹配命令行,仅执行匹配的命令;

-v 
输出被处理的包名和源文件名;

-n 
显示不执行命令;

-x 
显示并执行命令;

command 
可以是在环境变量 PATH 中的任何命令。

generate 用法

上面帮助文档有体现,我们可以使用 //go:generate command argument... 来讲 generate 工具用起来

实际案例

我们来简单的尝试一下

我们在刚才的 main.go 中加入 generate 的语句,使用 generate 执行,ls -alh

/*
____  ___   _____ ___________
\   \/  /  /     \\__    ___/
 \     /  /  \ /  \ |    |
 /     \ /    Y    \|    |
/___/\  \\____|__  /|____|
      \_/        \/
createTime:2021/10/10
createUser:Administrator
*/
package main

//go:generate ls -alh

import (
        "fmt"
        "myerr/mycodes"
)

func main() {
        fmt.Println(mycodes.ERR_CODE_CONN_REFUSE)
}

在 main.go 同级目录下执行 go generate 看效果

# go generate
total 20K
drwxr-xr-x  3 root root 4.0K Oct 10 17:30 .
drwxr-xr-x 11 root root 4.0K Oct 10 16:25 ..
-rw-r--r--  1 root root   22 Oct 10 16:02 go.mod
-rw-r--r--  1 root root  346 Oct 10 17:30 main.go
drwxr-xr-x  2 root root 4.0K Oct 10 17:13 mycodes

果然是调用 ls -alh 成功了

go generate + stringer 的使用

那么我们就把刚才我们实践的 stringer 工具也加进去玩玩

此时目录是这样的

.
├── go.mod
├── main.go
└── mycodes
    └── errcode.go

main.go 是这样的

/*
____  ___   _____ ___________
\   \/  /  /     \\__    ___/
 \     /  /  \ /  \ |    |
 /     \ /    Y    \|    |
/___/\  \\____|__  /|____|
      \_/        \/
createTime:2021/10/10
createUser:Administrator
*/
package main

//go:generate stringer -linecomment -type ErrCode ./mycodes

import (
        "fmt"
        "myerr/mycodes"
)

func main() {
        fmt.Println(mycodes.ERR_CODE_CONN_REFUSE)
}

没错我们加入了 //go:generate stringer -linecomment -type ErrCode ./mycodes

直接执行 go generate -x 来看效果吧

# go generate -x
stringer -linecomment -type ErrCode ./mycodes

errcode_string.go 又生成了

.
├── go.mod
├── main.go
└── mycodes
    ├── errcode.go
    └── errcode_string.go

执行 go run main.go 当然必须是我们想要的东西啦

# go run main.go
连接被拒绝

go generate 的使用规范

  • 运行 go generate命令时,才会执行特殊注释后面的命令
  • 特殊注释必须以 //go:generate开头,双斜线后面没有空格
  • 该特殊注释必须在 .go 源码文件中
  • 每个源码文件可以包含多个 generate 特殊注释
  • go generate命令执行出错时,将终止程序的运行

最后说说 go generate 还能干些啥

go generate 能干的事情还真不少,只要是能够在 path 下面能找到的可执行程序,都可以放在 //go:generate 后面玩,一般使用 go generate 会有如下场景:

  • protobuf:从 protocol buffer 定义文件(.proto)生成 .pb.go 文件 , 这种情况 grpc 通信的时候常用
  • yacc:从 .y 文件生成 .go 文件
  • HTML:将 HTML 文件嵌入到 go 源码
  • bindata:将形如 JPEG 这样的文件转成 go 代码中的字节数组
  • Unicode:从 UnicodeData.txt 生成 Unicode 表

工具要用用起来才能体现它的价值

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~

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

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

相关文章

腾讯云2核2G、2核4G、4核8G、8核16G、16核32G服务器价格出炉

腾讯云轻量应用服务器为轻量级的云服务器&#xff0c;使用门槛低&#xff0c;按套餐形式购买&#xff0c;轻量应用服务器套餐自带的公网带宽较大&#xff0c;4M、6M、7M、10M、14M及20M套餐可选&#xff0c;如果是云服务器CVM这个带宽价格就要贵很多了。 轻量应用服务器CPU内存…

Linux系统中如何实现串口的格式化功能方法

大家好&#xff0c;今天的话&#xff0c;主要和大家聊一聊&#xff0c;如何实现串口格式化功能实验。 目录 第一&#xff1a;串口格式化基本简介 第二&#xff1a;实验程序的操作 第三&#xff1a;具体的代码实现 第一&#xff1a;串口格式化基本简介 前面虽然实现了串口的功…

[附源码]计算机毕业设计基于vuejs的爱宠用品销售appSpringboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【vue】中英文切换(多语言国际化)

一、安装i18n插件 npm install vue-il8n8.23.0 --save二、创建语言包文件夹与配置 &#xff08;1&#xff09;index.js中 import Vue from vue // 引入vue import VueI18n from vue-i18n // 引入i18n模块 import elementEnLocale from element-ui/lib/locale/lang/en // elem…

新手使用wvp-pro和ZLMediaKit的菜鸟说明(手把手教)

对于wvp-pro的使用&#xff0c;很多大佬都是白嫖菜鸟党&#xff0c;很多都第一次使用wvp&#xff0c;甚至第一次接触国标&#xff0c;连国标最基本流程都不清楚。所以写此文档以供各位菜鸟大佬点评指正 看此文档前提&#xff1a;&#xff08;下文ZLMediaKit简称zlm&#xff09…

springBoot中日志的使用

springBoot中日志的使用 日志基础 首先你需要知道日志门面&#xff0c;日志实现&#xff0c;日志桥接器。 基于日志实现&#xff0c;常用的有logback,log4j2&#xff0c;这两个日志实现是的创始人是同一个&#xff0c;概念差不多&#xff0c;这里以log4j2为例&#xff0c;有如…

迭代器和生成器

文章目录迭代器和生成器图解迭代器和生成器的关系迭代器容器生成器yield函数生成器表达式总结迭代器和生成器 图解迭代器和生成器的关系 图1-1​ 不管是生成器还是我们的容器&#xff0c;最终都是迭代器&#xff0c;使用next方法进行有规律的获取元素&#xff0c;不需要将元素…

免费的在线3D CAD【BimAnt】

BimAnt托管了可以免费使用的在线三维CAD&#xff0c;采用BRep内核&#xff0c;支持几何约束求解&#xff0c;支持二维草图&#xff0c;支持挤压、放样、扫掠和旋转等操作。访问地址&#xff1a;BimAnt三维CAD。 一、添加基础图元 BimAnt三维CAD支持圆柱、圆锥、球体、圆环体…

STM32的最小系统组成的详解

经常使用STM32开发的工程师对于它的开发环境的最小系统是必须要有所了解的&#xff0c;特别是硬件工程师在设计硬件的时候对这个最小系统就要更加的深入了解了&#xff0c;如果最小系统的搭建都有问题&#xff0c;那以后的使用很难避免不出现问题。 话不多说&#xff0c;进入正…

【自省】使用Executors.xxx违反阿里Java代码规范,那还不写定时任务了?

一、背景 在《分布式锁主动续期的入门级实现-自省 | 简约而不简单》中通过【自省】的方式讨论了关于分布式锁自动续期功能的入门级实现方式&#xff0c;简单同步一下上下文&#xff1a; 客户端抢到分布式锁之后开始执行任务&#xff0c;执行完毕后再释放分布式锁。持锁后因客…

微服务守护神-Sentinel-热点-授权-系统规则

引言 书接上篇 微服务守护神-Sentinel-降级规则 &#xff0c;上面介绍了Sentinel降级规则&#xff0c;本篇继续来Sentinel的热点、授权、系统规则。 热点规则 何为热点&#xff1f;热点即经常访问的数据。很多时候我们希望统计某些热点数据中访问频次最高的 Top K 数据&…

# String-security(配置异常处理器,封装JWT工具类)

1 JWT是做什么的? 为了在前后端分离项目中使用 JWT &#xff0c;我们需要达到 2 个目标&#xff1a; 在用户登录认证成功后&#xff0c;需要返回一个含有 JWT token 的 json 串。 在用户发起的请求中&#xff0c;如果携带了正确合法的 JWT token &#xff0c;后台需要放行&a…

ELK日志分析系统

目录 一.ELK概述 1.1 ELK简介 1.2 ELK日志组件 1.2.1 ELK组件介绍 1.3 日志处理步骤 二. Elasticsearch 集群部署 2.1 关闭防火墙 ​2.2 ELK Elasticsearch 集群部署&#xff08;在Node1&#xff0c;Node2节点上操作&#xff09; ​ 2.2.1 更改主机名​ 2.2.2 配置域名…

RCE漏洞简介

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是RCE漏洞简介。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未授权设备进行…

高级篇之如何升级5GCPE固件

高级篇之如何升级5GCPE固件1. 准备工作2. 安装5GCPE串口驱动3. 升级固件3.1 选择固件3.2 选择串口号3.3 下载固件3.4 下载固件意外情况4. 重新启动结束&#xff01;LINKPI-5GCPE是LINKPI推出的可以做户外移动直播的 5G无线网关&#xff0c;可以支持三种模式&#xff1a; 网卡模…

计算机网络-分组交换与电路交换

有志者&#xff0c;事竟成 文章持续更新&#xff0c;可以关注【小奇JAVA面试】第一时间阅读&#xff0c;回复【资料】获取福利&#xff0c;回复【项目】获取项目源码&#xff0c;回复【简历模板】获取简历模板&#xff0c;回复【学习路线图】获取学习路线图。 文章目录一、分组…

普乐蛙VR航天科技馆太空体验馆VR太空舱体验馆vr飞碟遨游太空

什么是航天航空主题馆 普乐蛙VR航天航空体验馆系列 普乐蛙VR航天航空主题馆可以根据客户的需求&#xff0c;用航天航空的科技氛围方案进行布置&#xff0c;大多用最新的黑科技&#xff0c;让整个馆充满科技科幻的感觉&#xff0c;使人沉浸&#xff0c;容易进入主题。馆内设置不…

MySQL函数:列转行CONCAT、CONCAT_WS、GROUP_CONCAT的使用(精要)

前言 很久没有接触Mysql了。 今天心血来潮&#xff0c;突然想了解一下Mysql列转行&#xff0c;看了一些文章&#xff0c;重点不清晰&#xff0c;遂有下文&#xff01; Mysql官网、 社区版下载&#xff08; Windows版_mysql.8.0.31下载 &#xff09; 概述 Mysql内部提供了列转…

UNIAPP实战项目笔记50 登录和注册页面的布局

UNIAPP实战项目笔记50 登录和注册页面的布局 实际案例图片 登录页面布局 注册页面布局 显示登录和注册页面布局 页面布局的切换 具体内容图片自己替换哈&#xff0c;随便找了个图片的做示例 具体位置见目录结构 完善布局页面和样式 代码 login.vue部分 <template><v…

拉线援(AD PADS Cadence快捷键汇总)

年纪越大&#xff0c;记性就不太好了&#xff0c; 要干的活越多&#xff0c; 还要盯盘&#xff0c; 效率得提升一下。 总结下平时拉线容易用到的快捷键、评审资料等。 以后不断更新完善。 公众号发消息&#xff08;Download|拉线援&#xff09;可获得源文档。 一、Altium Desi…