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

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