duanjian4150 2013-10-05 06:19
浏览 43
已采纳

Go中命名返回变量的预期用途是什么?

I find the provision of named returned variables in Go to be a useful feature, because it can avoid the separate declaration of a variable or variables. However, in some instances I want to return a different variable to the variable declared in the function as the return-variable. That appears to work ok, however I do find it a little strange to declare a return variable and then return something else.

While writing a test program to help learn Go (not the one below), I found it a little annoying specifying the return variable in the return statement of functions returning multiple variables. Particularly so, because the variables had been named in the function declaration. I now find while posting this, that it appears that where there are named return variables, they don't need to be used in the return statement, just "return" will suffice and will implicitly use the named variables. That I find this a great feature.

So, although I have possibly partly answered my own question, could someone advise if my usage below is acceptable? I'm sure this is documented, but I haven't come across it, and it doesn't appear to be in the reference-book that I purchased which I think overlooks this feature.

Basically, the rule appears to be (as far as I can determine), that where named return variables are used, that the function statement declares the variables, and also the function can optionally implicitly uses them as the return values, however this can be overridden by using explicit return values.

Example Program :

package main

func main() {
    var sVar1, sVar2 string
    println("Test Function return-values")
    sVar1, sVar2 = fGetVal(1)
    println("This was returned for '1' : " + sVar1 + ", " + sVar2)
    sVar1, sVar2 = fGetVal(2)
    println("This was returned for '2' : " + sVar1 + ", " + sVar2)
}

func fGetVal(iSeln int) (sReturn1 string, sReturn2 string) {
    sReturn1 = "This is 'sReturn1'"
    sReturn2 = "This is 'sReturn2'"

    switch iSeln {
        case 1  :  return
        default : return "This is not 'sReturn1'", "This is not 'sReturn2'"
    }
}
  • 写回答

3条回答 默认 最新

  • douyi3767 2013-10-05 07:25
    关注

    Your usage is absolutely fine and you'll find plenty of similar examples in the Go source code.

    I'll attempt to explain how the return statement actually works in Go to give a deeper appreciation of why. It is useful to have a think about how Go implements parameter passing and return from functions. Once you understand that you'll understand why named return variables are so natural.

    All arguments to functions and all return values from functions are passed on the stack in Go. This varies from C which usually passes some parameters in registers. When a function is called in Go the caller makes space on the stack for both the arguments and the return values then calls the function.

    Specifically, when this function is called, which has 3 input parameters a, b, c and two return values

    func f(a int, b int, c int) (int, int)
    

    The stack will look like this (low memory address at the top)

    * a
    * b
    * c
    * space for return parameter 1
    * space for return parameter 2
    

    Now it is obvious that naming your return parameter just names those locations on the stack.

    func f(a int, b int, c int) (x int, y int)
    
    * a
    * b
    * c
    * x
    * y
    

    It should now also be obvious what an empty return statement does - it just returns to the caller with whatever the values of x and y are.

    Now for some disassembly! Compiling this with go build -gcflags -S test.go

    package a
    
    func f(a int, b int, c int) (int, int) {
        return a, 0
    }
    
    func g(a int, b int, c int) (x int, y int) {
        x = a
        return
    }
    

    Gives

    --- prog list "f" ---
    0000 (test.go:3) TEXT    f+0(SB),$0-40
    0001 (test.go:3) LOCALS  ,$0
    0002 (test.go:3) TYPE    a+0(FP){int},$8
    0003 (test.go:3) TYPE    b+8(FP){int},$8
    0004 (test.go:3) TYPE    c+16(FP){int},$8
    0005 (test.go:3) TYPE    ~anon3+24(FP){int},$8
    0006 (test.go:3) TYPE    ~anon4+32(FP){int},$8
    0007 (test.go:4) MOVQ    a+0(FP),BX
    0008 (test.go:4) MOVQ    BX,~anon3+24(FP)
    0009 (test.go:4) MOVQ    $0,~anon4+32(FP)
    0010 (test.go:4) RET     ,
    
    --- prog list "g" ---
    0011 (test.go:7) TEXT    g+0(SB),$0-40
    0012 (test.go:7) LOCALS  ,$0
    0013 (test.go:7) TYPE    a+0(FP){int},$8
    0014 (test.go:7) TYPE    b+8(FP){int},$8
    0015 (test.go:7) TYPE    c+16(FP){int},$8
    0016 (test.go:7) TYPE    x+24(FP){int},$8
    0017 (test.go:7) TYPE    y+32(FP){int},$8
    0018 (test.go:7) MOVQ    $0,y+32(FP)
    0019 (test.go:8) MOVQ    a+0(FP),BX
    0020 (test.go:8) MOVQ    BX,x+24(FP)
    0021 (test.go:9) RET     ,
    

    Both functions assemble to pretty much the same code. You can see quite clearly the declarations of a,b,c,x,y on the stack in g, though in f, the return values are anonymous anon3 and anon4.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?