作者:林冠宏 / 指尖下的幽灵
如果你是一个后端Server程序
开发人员。你应该知道,在你写完API
之后,是需要给客户端
的同学提供调用
文档的。
例如下面一个api handler
,创建一个用户
。
func HandleCreateUser(w http.ResponseWriter,r *http.Request) map[string]interface{} { if r.Body == nil { return util.GetCommonErr(23,"create user req body is fucking null?") } .... .... return util.GetCommonSuccess("success") }
util.GetCommonErr(23,"create user req body is fucking null?")
假设我们要写成markDown风格的
文档,上面的可能是这样一种对应
含义 | 提示 |
---|---|
手动
写完了。
如果有几百上千个
呢?一个完整的服务端程序,肯定会有很多这种错误信息输出
的代码。在几百上千个
的时候,还要手动写?这是多么低效率
,且浪费时间
的令人窒息
的操作。
文章要介绍的就是一个帮你自动检索并生成api输出错误信息文档的开源程序">而我这篇文章要介绍的就是一个帮你自动检索并生成API输出错误信息文档
的开源程序
ErrorDocAutoPrinter
- 自定义代码文件夹路径
-
Json
配置文件形式导入设置,避免反复编译程序
- 按照给定的
代码方法名称
自动检索对应的代码行
- 按照给定的
切割参数规则
,自动切割组合
- 按照给定的
列名描述
,自动组合成新的文字
- 接口化的设计逻辑,高度自定义
- 自动按照
code
从小到大排序输出,可控!
- 自动提示
重复出现过
的错误信息。
- 自动按照设定生成输出文件
- 可设置
符合目标
的文件后缀
- 可设置
需要过滤
的文件名,符合就不处理
- 自定义输出风格,
markDown
?txt
?html
?
- 自行定义输出的逻辑,可以映射到很多情况的文字玩法
- 总之:‘为所欲为’
输出">我,提供了两种风格的输出
-
简单文本
风格
-
markDown
风格
- 配置好
json
文件 DefaultConfig.json
{
"TargetFileSuffix":[".go"],"TargetErrorFuncName":["util.GetCommonErr","util.GetErrWithTips"],"FilterFileName":["core"],"ParamsColumnNames":[" 错 误 码 "," 含 义 ","提 示"],"ParamsSplitChar":","
}
func TestDocPrinter(t *testing.T) {
p := NewDefaultErrorDocPrinter(NewDefaultMarkDownErrorDocPrinter())
if p == nil {
return
}
fmt.Println(p.printErrorDoc("../../errorDocPrinter"))
}
- 复制粘贴
结果
Json
配置文件形式导入设置,避免反复编译程序代码方法名称
自动检索对应的代码行切割参数规则
,自动切割组合列名描述
,自动组合成新的文字code
从小到大排序输出,可控!重复出现过
的错误信息。符合目标
的文件后缀
需要过滤
的文件名,符合就不处理markDown
?txt
?html
?简单文本
风格markDown
风格- 配置好
json
文件DefaultConfig.json
{ "TargetFileSuffix":[".go"],"TargetErrorFuncName":["util.GetCommonErr","util.GetErrWithTips"],"FilterFileName":["core"],"ParamsColumnNames":[" 错 误 码 "," 含 义 ","提 示"],"ParamsSplitChar":"," }
func TestDocPrinter(t *testing.T) { p := NewDefaultErrorDocPrinter(NewDefaultMarkDownErrorDocPrinter()) if p == nil { return } fmt.Println(p.printErrorDoc("../../errorDocPrinter")) }
- 复制粘贴
结果
含义 | 提示 |
---|---|
生成">简单分析下 markDown
风格的生成
接口
type IErrorDocPrinter interface { FindLines(printer *ErrorDocPrinter,reader *bufio.Reader,fileName,currentSuffix string,handleLine func(line string)) []string BuildACell(printer ErrorDocPrinter,columns,size int,prefixName,param string) string ResultLine(line string) EndOfAFile(printer ErrorDocPrinter,aFileRetLines []string) EndOfAllFile(printer ErrorDocPrinter,allRetLines []string) }
文件所有行">找到一个文件所有行
func (p MarkDownErrorDocPrinter) FindLines( printer *ErrorDocPrinter,handleLine func(line string)) []string { // 正则匹配 todo var lines []string printer.currentLineNum = 0 for { byt,_,err := reader.ReadLine() if err != nil { // 读完一个文件 break } line := string(byt) // 排除注释 printer.currentLineNum++ if startWith(line,"//") { continue } if startWith(line,"/*") { continue } if startWith(line,"*") { continue } for _,value := range printer.TargetErrorFuncName { if strings.Contains(line,value) { // hit,准备生成 handleLine(line) lines = append(lines,line) } } } return lines }
func (p MarkDownErrorDocPrinter) BuildACell(
printer ErrorDocPrinter,param string) string {
/**
| Name | Academy | score |
| - | - | - |
| Harry Potter | Gryffindor| 90 |
| Hermione Granger | Gryffindor | 100 |
| Draco Malfoy | Slytherin | 90 |
*/
if columns == 0 {
code,err := strconv.ParseInt(param,10,64)
if err == nil {
codeArr = append(codeArr,code)
}
return "|" + param
}
count := tipsMap[param]
if columns == 1 {
// 保存提示列
if count != 0 {
count++
diffMap[fmt.Sprintf("param: -- %s -- times:%d",param,count-1)] =
fmt.Sprintf(" 与 %s 的第 %d 行提示重复",printer.currentFileName,printer.currentLineNum)
}else{
count = 1
}
tipsMap[param] = count
}
if columns == size - 1 {
return "|" + param + "|"
}
// 找出提示一样,但是 code 不一样的
return "|" + param
}
func quickSort(arr *[]int64,left,right int) {
if arr == nil {
return
}
if right == len(*arr) {
right--
}
if left < 0 || left >= len(*arr) {
return
}
hight := right
low := left
base := (*arr)[left]
if low < hight {
for ;low < hight; {
for ;low < hight && base <= (*arr)[hight]; {
hight--
break
}
(*arr)[low] = (*arr)[hight]
for ;low < hight && base >= (*arr)[low]; {
low++
break
}
(*arr)[hight] = (*arr)[low]
}
(*arr)[low] = base
quickSort(arr,low-1)
quickSort(arr,low+1,right)
}
}
quickSort(&codeArr,len(codeArr))
codeArrSize := len(codeArr)
for i:=0; i次数
//retLines = append(retLines[:index],retLines[index+1:]...)
index--
break
}
index++
}
}
// 生成文件
fileName := "errorInfo.md"
file,err := os.Create(fileName)
defer file.Close()
if err!=nil {
fmt.Println(err)
}
for _,line := range final {
fmt.Println(line)
file.WriteString(line+"\n")
}
<h2 id="如果编程不是为了让复杂的问题简单化那和机械学习有什么区别">如果编程不是为了让复杂的问题简单化,那和机械学习有什么区别?
func quickSort(arr *[]int64,left,right int) { if arr == nil { return } if right == len(*arr) { right-- } if left < 0 || left >= len(*arr) { return } hight := right low := left base := (*arr)[left] if low < hight { for ;low < hight; { for ;low < hight && base <= (*arr)[hight]; { hight-- break } (*arr)[low] = (*arr)[hight] for ;low < hight && base >= (*arr)[low]; { low++ break } (*arr)[hight] = (*arr)[low] } (*arr)[low] = base quickSort(arr,low-1) quickSort(arr,low+1,right) } }
quickSort(&codeArr,len(codeArr))
codeArrSize := len(codeArr)
for i:=0; i次数
//retLines = append(retLines[:index],retLines[index+1:]...)
index--
break
}
index++
}
}
// 生成文件
fileName := "errorInfo.md"
file,err := os.Create(fileName)
defer file.Close()
if err!=nil {
fmt.Println(err)
}
for _,line := range final {
fmt.Println(line)
file.WriteString(line+"\n")
}
<h2 id="如果编程不是为了让复杂的问题简单化那和机械学习有什么区别">如果编程不是为了让复杂的问题简单化,那和机械学习有什么区别?
// 生成文件
fileName := "errorInfo.md"
file,err := os.Create(fileName)
defer file.Close()
if err!=nil {
fmt.Println(err)
}
for _,line := range final {
fmt.Println(line)
file.WriteString(line+"\n")
}