问答

golang return defer的疑惑

作者:admin 2021-04-21 我要评论

package mainimport ( "fmt")func main() { fmt.Println(f0()) // 1 fmt.Println(f1()) // 0}func f0() (result int) { defer func() { result++ }() return 0}f...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)
package main

import (
    "fmt"
)

func main() {
    fmt.Println(f0()) // 1
    fmt.Println(f1()) // 0
}

func f0() (result int) {
    defer func() {
        result++
    }()
    return 0
}

func f1() (result int) {
    result = 0 //return语句不是一条原子调用,return xxx其实是赋值+RET指令
    return
}
  1. f0中明明返回的是0,是一个整形,虽然有个defer但是他还是一个数字0啊,为啥结果被改为了1
  2. f1中return那里明明啥都没有,给人直观感受就是null,他怎么就被改为了0
###

go里面没有null。编程靠只管感受?学习新语言就好好学习这门语言的语法,思想,不要混用。

问题1:defer 执行先于 return。所以会执行result++,因为你返回值定义了result变量,所以其值等于默认值0,result++等于1,只要定义了返回变量名,他会使用变量名返回,而不是你的 return 0

问题2:int默认值为0,slice,map这类复杂类型默认值才为nil

###

一个函数如果有命名的返回值,可以省略 return 语句的操作数,这称为裸返回。

你的代码等同于:

func f0() (result int) {
    defer func() {
        result++
    }()
    
    result = 0
    return result
}

func f1() (result int) {
    result = 0
    return result
}
###
1. defer是延后执行,但是不会延后至return后,是在return之前触发defer
2. go的一切定义皆有默认值,int类型默认值0,string类型默认值'',bool类型默认值false,以此类推
3. 函数定义了返回值,就一定会要求有返回内容。但是函数定义返回值变量,只是简略的返回写法,return 等同于 return result。
4. f0 写了return 0,结果是却返回了1,这个就不太清楚了。
###

第一个问题: 你注释里也写了的 return不是原子操作。是先执行return后的表达式,然后先进后出的执行defer,最后才返回 因此你return 0其实是三步 1.result=0 2.result++ 3.RET
第二个问题: 虽然return后面什么都没有,但是因为你定义的是命名返回值,因此在函数签名写下的时候,你的return值就是result变量了,result变量默认值是0,且你赋值也是0,所以结果就是0。如果写成result=1那么结果就是1。如果你声明的是未命名返回值,那么你这种return后面没东西的写法是编译不通过的,如:

// 编译失败
func f1() int {
    var result int
    result = 0
    return
}

你的对比不全面。可以考虑把下面的几种情况一起对比下:

// 11
func f0() (result int) {
   defer func() {
      result++
   }()
   return 10
}

// 10
func f1() int {
    var result int
    defer func() {
      result++
    }()
    return 10
}

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • golang return defer的疑惑

    golang return defer的疑惑

  • golang反射NumMethod()返回值的问题

    golang反射NumMethod()返回值的问题

  • 请问怎样给feaflet做一个罗盘功能。

    请问怎样给feaflet做一个罗盘功能。

  • vue下载图片跨域怎么解决?

    vue下载图片跨域怎么解决?

腾讯云代理商
海外云服务器