golang for循環種遍歷defer

defer需求分析

golang中幾乎所有涉及對數據庫的操作都要在回滾操作時用到defer,而當涉及到批量創建/刪除操作的回滾時,就要在for循環內使用defer,雖不推薦使用,但這可以在遍歷其中一條數據失敗時即可回滾止損

func saveDB() error {
	ips := []string{"192.168.1.1","192.168.1.2"}
	for _, ip := range ips {
			if err := db.create(ip); err != nil {
				errInfo := fmt.Sprintf("save ip to db error %+v", err)
				logCtx.Errorf(errInfo)
				return errors.New(errInfo)
			}
			defer func(ip string) {
				if err != nil {
					_, errTmp := db.delete(ip)
					if errTmp != nil {
						errInfo := fmt.Sprintf("delete ip error %v", errTmp)
						logCtx.Errorf(errInfo)
					}
				}
			}(ip)
		}
	}

注意點:每一條for循環遍歷時,defer中第一個判斷條件是err!=nil,這個err是執行存入數據庫的err,而我們執行回滾裏將創建失敗的數據刪除,此時的errTmp必須與err名字錯開,否則若執行回滾內的操作失敗,全局的err還是會進入defer,進入死循環狀態

defer坑

1、defer是先進後出
2、壓入defer中的數據不會隨後續代碼中更改而更改(比如定義i=0,存入defer後續執行i++,但最後defer中的i值仍然是 0)
3、defer可以修改返回值,如果defer中的是i++,最後返回值的i如果是1,執行完defer後,返回值變成2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章