zoukankan      html  css  js  c++  java
  • 记一次:发生错误,但是defer错误没有生效的情况

    在处理程序异常时,使用defer能够很大程度检查代码量,提高码字效率。

    但是,却发现一件很奇怪的事情,defer中的err竟然失效了!!!

    这时一万个为什么瞬间闪现脑海,因为之前一直这样码的呀?

    代码:

        var err error
        var Error string = "success"
        defer func() {
            if err != nil {this.Data["Error"] = Error
                this.TplName = "layout/error.html"
            }
        }()
    
        name := strings.TrimSpace(this.GetString("activity_name"))
        if len(name) == 0 {
            Error = "活动的名字不能为空"
            err = fmt.Errorf("activity name can not null")
            return
        }

    上面是我的平时代码,没有问题,错误提醒ok

    错误代码:

        var err error
        var Error string = "success"
        defer func() {if err != nil {
                fmt.Println("add_activity,defer1-1:",Error)
                this.Data["Error"] = Error
                this.TplName = "layout/error.html"
            }
        }()
    
        ....省略n行代码
    
        productId := this.GetStrings("product_id")
        if len(productId) == 0 {
            err = fmt.Errorf("商品id 非法, err:%v", err)
            Error = err.Error()
            return
        }
    
        //处理活动商品信息
        var productList = make([]model.SeckillActivityProduct, len(productId))
        for k, v := range productId {
            idInt, err := strconv.Atoi(v)
            if err != nil {
                err = fmt.Errorf("idInt atoi failed ,product id=[%s] err:%v
    ", v, err)
                Error = err.Error()
                return
            }
            productList[k].ProductId = idInt
            seckillPriceFloat64, err := strconv.ParseFloat(seckillPriceArr[k], 64)
            if err != nil {
                err = fmt.Errorf("seckillPriceFloat64 ParseFloat failed ,product id=[%s] err:%v
    ", v, err)
                Error = err.Error()
                return
            }
            totalInt, err := strconv.Atoi(totalArr[k])
            if err != nil {
                err = fmt.Errorf("totalInt atoi failed ,product id=[%s] err:%v
    ", v, err)
                Error = err.Error()
                return
            }
            SeckillProductIdInt, errMsg := strconv.Atoi(seckillProductIdArr[k])
            fmt.Println("add_activity3-5")
            if errMsg != nil {
                err = fmt.Errorf("SeckillProductIdInt atoi failed ,product id=[%s] err:%v
    ", v, errMsg)
                Error = err.Error()return
            }
            productList[k].SeckillPrice = seckillPriceFloat64
            productList[k].Total = totalInt
            productList[k].Id = SeckillProductIdInt
        }

    上面代码执行请求后,错误竟然没有提醒!why?

    第一反应不可能,一直这样的呀。

    后来想到golang和php的作用域用法不同,就各种修改,问题依然...

    自学golang一段时间了,golang属于静态语言广泛使用内存地址,就想到会不会是内存地址被修改了,而上面defer还是使用原来的内存地址呢?

    于是大量断点,果然...,在一个循环中发现err := 函数()的时候err的内存地址被修改了。于是改之,问题解决。

    在这里总结下:

      定义完重要变量后,千万不要再在非必要地方重复使用这个变量名,防止滥用产生不必要麻烦。

      同时,我看到网上有人说是引用类型问题,即应这样定义var err *Error。但是,测试后发现在同一个函数下,defer后,return前返回err仍然地址相同。所以应该不是值类型和引用类型问题,当然嵌套多函数就另说了。所以,在一个函数下,renturn时应该是自动赋值给上面定义好的变量。

    哈哈,这些都是测试所得,有不对之处还请留言指出,大家共同进步

  • 相关阅读:
    .c 文件取为.o文件
    wildcard 处理全部文件
    专家解读Linux操作系统内核中的GCC特性
    Yeoman:适合现代Web应用的现代工作流
    【转】nodejs
    node.js
    2019暑假集训 种树
    2019.6.5 NOIP2014 day2 t2 寻找道路
    2019.6.1 最优贸易
    2019.5.11 海淀区赛之杯子
  • 原文地址:https://www.cnblogs.com/two-bees/p/12986137.html
Copyright © 2011-2022 走看看