學習 Gin 問題總結 2020.12.29


學習 Gin 問題總結 2020.12.29

數據綁定與解析

BindXXXShouldBindXXXShouldBindWith區別

  1. BindXXX

    會自動返回信息,輸入無效時,在header寫入400

  2. ShouldBindXXX

    返回消息,輸入無效時,不會在header寫入400狀態碼,這時候可以自定義返回信息,在使用上相對來說更加靈活。

  3. ShouldBindWith

    gin 1.4 之前,重復使用ShouldBind綁定會報錯EOF

    gin 1.4 之后官方提供了一個 ShouldBindBodyWith 的方法,可以支持重復綁定,原理就是將body的數據緩存了下來,但是二次取數據的時候還是得用 ShouldBindBodyWith 才行,直接用 ShouldBind 還是會報錯的。

    根據方法內參數b的類型去綁定jsonquery,去綁定obj,不返回狀態碼。

func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error {
	return b.Bind(c.Request, obj)
}

HTML渲染

func main() {
	// 1.創建路由
	r := gin.Default()
	//靜態文件,聲明模板文件所在的目錄,系統自動解析
	r.LoadHTMLGlob("static/html/*")
    
    ...
}

LoadHTMLGlob(),該方法參數內的目錄下,不能有二級目錄,存在二級目錄將會panic

而且該方法只能在一個實例中對一個目錄使用一次(使用過的目錄下的子目錄同樣是為已使用)。

使用兩次

//靜態文件,聲明模板文件所在的目錄,系統自動解析
	r.LoadHTMLGlob("static/html/*")
	r.LoadHTMLGlob("static/html/html2/*")

將會:

panic: read static\html\html2: The handle is invalid.

如果需要解析兩個目錄下的HTML文件,可在同一目錄下創建兩個文件夾:

	//靜態文件,聲明模板文件所在的目錄,系統自動解析
	r.LoadHTMLGlob("static/html/*")
	r.LoadHTMLGlob("static/html2/*")

[GIN-debug] Loaded HTML Templates (4):
- form.html
- login.html
- upload.html
-

[GIN-debug] Loaded HTML Templates (2):
- uploadMore.html
-

此時將會正常解析兩個目錄下的HTML模板。


還可以使用:

//靜態文件,聲明模板文件所在的目錄,系統自動解析
	r.LoadHTMLGlob("static/**/*")

-[GIN-debug] Loaded HTML Templates (5):

  - form.html
          - login.html
          - upload.html
                  - uploadMore.html

static目錄下的子目錄內的所有模板文件都將被解析。

注意:static目錄下的模板文件將不會被解析。

重定向

c.Redirect(http.StatusPermanentRedirect,"http://localhost:8080/updateBook")

狀態碼可選:

http.StatusPermanentRedirect //永久性重定向

http.StatusTemporaryRedirect //臨時性重定向

第二個參數為重定向的地址。

異步處理

// Async 異步處理,保存上傳文件,開啟相應數量的 goroutine
func Async(c *gin.Context)  {
	form, err := c.MultipartForm()
	if err != nil {
		c.String(http.StatusBadRequest,fmt.Sprintf("get err %s",err.Error()))
	}
	//根據key:‘files’,獲取表單中的文件切片
	files := form.File["files"]
	fileSum := len(files)
	fileName := make([]string,fileSum)

	//控制上傳文件同步問題處理
	waitG := sync.WaitGroup{}
	waitG.Add(fileSum)

	for index, file := range files {
		fileName[index] = file.Filename
		//異步處理時,上下文應該復制一個只讀副本,不直接使用原始上下文
		cc := c.Copy()
		go func(c *gin.Context,fileName string,fileUpload *multipart.FileHeader) {
			defer waitG.Done()
			fmt.Println("正在保存",fileName)
			cc.SaveUploadedFile(fileUpload,fileName)
		}(cc,fileName[index],file)
	}
	waitG.Wait()
	c.String(http.StatusOK,"%s",strings.Join(fileName,",\n"))
}

初始寫法(錯誤):

	go func() {
			defer waitG.Done()
			fmt.Println("正在保存",fileName[index])
			cc.SaveUploadedFile(file,fileName[index])
		}()
	}

錯誤原因總結:

未進行傳參,導致只有最后一個文件被上傳,通過debug發現,雖然已經做同步處理(使用WaitGroup),但是goroutine內因為延遲求值的原因,導致每次都只是保存最后一個文件。傳入參數fileNamefileUpload后,會立即復制參數,不會出現延遲求值的情況,使得保存文件按順序進行保存。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM