Author: Lin Guanhong/The Ghost at my Fingertips

The Denver nuggets: https://juejin.cn/user/1785262612681997

Blog: http://www.cnblogs.com/linguanh/

Making: https://github.com/af913337456/

Tencent cloud column: https://cloud.tencent.com/developer/user/1148436/activities


Source – making:Github.com/af913337456…

If you are a back-end Server application developer. You should know that after you write the API, you need to provide the call documentation to the students on the client side.

For example, the following API handler creates a user.

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")}Copy the code

There is a line of error message output code above

util.GetCommonErr(23."create user req body is fucking null?")
Copy the code

Suppose we want to write a markDown style document, the one above might look something like this

Error code meaning prompt
23 create user req body is fucking null? no

Ok, this is just a case of an error message that we could easily write manually.

What if there were hundreds or thousands of them? A complete server program, there must be a lot of this error message output code. Do you have to do it by hand when you have hundreds or thousands of them? What an inefficient, time-wasting stifling operation.

And that’s what I want to introduce in this articleOne that automatically retrieves and generates API output error messages for youtheOpen source program

ErrorDocAutoPrinter

It has the following characteristics

  • Custom code folder path
  • JsonImport Settings as a configuration file to avoid compiling the program repeatedly
  • As givenCode method nameAutomatically retrieves the corresponding line of code
  • As givenCutting parameter rule, automatic cutting combination
  • As givenThe column name descriptionAutomatically combine into new text
  • Interface design logic, high degree of customization
  • Automatically according to thecodeSort output from small to large, controllable!
  • Automatic promptRepeated occurrenceError message.
  • Automatically generate output files according to the Settings
  • Can be set upConform to the targetThe fileThe suffix
  • Can be set upNeed to filterIf yes, no processing is required
  • Custom output style,markDown?txt?html?
  • Self – defined output logic can be mapped to many situations of text play
  • In short: ‘Do whatever you want’

I provide two styles of output

  • Simple textstyle
  • markDownstyle

Using the step

  1. configuredjsonfileDefaultConfig.json
{
  "TargetFileSuffix": [".go"]."TargetErrorFuncName": ["util.GetCommonErr"."util.GetErrWithTips"]."FilterFileName": ["core"]."ParamsColumnNames": ["Error error code"."With righteousness"."Carry in"]."ParamsSplitChar":","
}
Copy the code
  1. Enter yourCode folder pathAnd run the program
func TestDocPrinter(t *testing.T) {
	p := NewDefaultErrorDocPrinter(NewDefaultMarkDownErrorDocPrinter())
	if p == nil {
		return
	}
	fmt.Println(p.printErrorDoc(".. /.. /errorDocPrinter"))}Copy the code
  1. Copy and pasteThe results of
Error code meaning prompt
9 – invalid create user – open –
4 – invalid create user – open –
– 1 create user failed Failed to create a user
88 Failed to create a comment – open –
3110 error params – open –
3111 update failed – open –
3112 Yellow content is related to pornography – open –
3113 Forbid visit – open –
3114 empty id – open –
3115 The server failed to start a transaction. Procedure – open –
3116 Server transaction commit failed – open –
3117 update effect row <= 0 – open –
3118 RowsAffected failure – open –
3119 The update was only partially successful – open –
3120 empty userId – open –
3121 too lager – open –
3122 user not exits – open –
3123 Illegal update – open –
3124 Parameter Length limit – open –
3126 Server transaction commit failed – open –
3127 invalid money – open –
3128 money not enough – open –
3129 Failed to create consumption record. Procedure – open –
Basically finished, the source code to see the above open source link, to play.

Just a quick analysismarkDownStyle generation

interface

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)
}
Copy the code

Find all lines of a file

func (p MarkDownErrorDocPrinter) FindLines(
	printer *ErrorDocPrinter,reader *bufio.Reader,fileName,currentSuffix string,handleLine func(line string)) []string {
	// The re matches todo
	var lines []string
	printer.currentLineNum = 0
	for {
		byt, _, err := reader.ReadLine()
		iferr ! =nil {
			// Finish reading a file
			break
		}
		line := string(byt)
		// exclude comments
		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, ready to generate
				handleLine(line)
				lines = append(lines,line)
			}
		}
	}
	return lines
}
Copy the code

Process a cell

func (p MarkDownErrorDocPrinter) BuildACell(
printer ErrorDocPrinter,columns,size int,prefixName,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 {
		// Save the prompt column
		ifcount ! =0 {
			count++
			diffMap[fmt.Sprintf("param: -- %s -- times:%d",param,count- 1)] =
				fmt.Sprintf("Duplicate prompt for line %d of %s",printer.currentFileName,printer.currentLineNum)
		}else{
			count = 1
		}
		tipsMap[param] = count
	}
	if columns == size - 1 {
		return "|" + param + "|"
	}
	// find the same prompt, but different code
	return "|" + param
}
Copy the code

Sort from smallest to largest –code

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,left,low- 1)
		quickSort(arr,low+1,right)
	}
}
Copy the code

The assembly


quickSort(&codeArr,0.len(codeArr))
codeArrSize := len(codeArr)
for i:=0; i<codeArrSize ; i++ { codeAtr := strconv.Itoa((int)(codeArr[i]))
	index := 0
	for _,line := range allRetLines {
		if strings.Contains(line,"|"+codeAtr+"|") {
			final = append(final,line)
			// Subtract one to reduce the number of loops
			//retLines = append(retLines[:index],retLines[index+1:]...)
			index--
			break
		}
		index++
	}
}

// Generate the file
fileName := "errorInfo.md"
file,err := os.Create(fileName)
defer file.Close()
iferr! =nil {
	fmt.Println(err)
}
for _,line := range final {
	fmt.Println(line)
	file.WriteString(line+"\n")}Copy the code

If programming isn’t about simplifying complex problems, how is it different from rote learning?