【问题标题】:How to get the pointer of return value from function call?如何从函数调用中获取返回值的指针?
【发布时间】:2015-08-25 00:48:49
【问题描述】:

我只需要一个指向 time.Time 的指针,所以下面的代码似乎无效:

./c.go:5: 不能取time.Now()的地址

我只是想知道为什么?除了先对变量赋值并获取变量的指针之外,还有什么方法可以做到这一点?

package main

import "time"
func main() {
    _ = &time.Now()
}

【问题讨论】:

    标签: pointers go


    【解决方案1】:

    可能不令人满意的答案是“你不能这样做,因为规范是这样说的。”规范说,要在某些东西上使用&,它必须是addressable 或复合文字,并且要可寻址,它必须是“变量、指针间接或切片索引操作;或可寻址的字段选择器结构操作数;或可寻址数组的数组索引操作。”函数调用和方法调用肯定不在列表中。

    实际上,这可能是因为函数的返回值可能没有一个可用的地址;它可能在一个寄存器中(在这种情况下它肯定是不可寻址的)或在堆栈上(在这种情况下它有一个地址,但如果它放在一个超出当前范围的指针中,则该地址将无效。为了保证可寻址性, Go 必须做几乎完全等同于将其分配给变量的操作. 但是 Go 是一种语言, 如果它要为变量分配存储空间, 那将是因为你说的, 而不是因为编译器神奇地决定这样做。所以它不会使函数的结果可寻址。

    或者我可能想多了,他们根本不希望返回 一个 值的函数与返回多个值的函数有特殊情况:)

    【讨论】:

      【解决方案2】:

      你不能像 hobbs 所说的那样直接获取函数调用的地址(或者更准确地说是函数的返回值)。

      还有另一种方法,但是很丑:

      p := &[]time.Time{time.Now()}[0]
      fmt.Printf("%T %p\n%v", p, p, *p)
      

      输出(Go Playground):

      *time.Time 0x10438180
      2009-11-10 23:00:00 +0000 UTC
      

      这里发生的是一个struct 是用一个文字创建的,包含一个元素(time.Now() 的返回值),切片被索引(第 0th 元素)和地址0th 元素被采用。

      所以宁愿只使用一个局部变量:

      t := time.Now()
      p := &t
      

      或辅助函数:

      func ptr(t time.Time) *time.Time {
          return &t
      }
      
      p := ptr(time.Now())
      

      也可以是单行匿名函数:

      p := func() *time.Time { t := time.Now(); return &t }()
      

      或者作为替代:

      p := func(t time.Time) *time.Time { return &t }(time.Now())
      

      更多替代方案,请参见:

      How do I do a literal *int64 in Go?

      另见相关问题:How can I store reference to the result of an operation in Go?

      【讨论】:

        【解决方案3】:

        如果您在编写函数时遇到此问题,请将函数更改为返回指针。即使您不能获取返回值的地址,您也可以取消引用返回值,因此无论您想要指针还是对象都是合适的。

        func Add(x, y int) *int {
            tmp := x + y
            return &tmp
        }
        
        func main() {
            fmt.Println("I want the pointer: ", Add(3, 4))
            fmt.Println("I want the object: ", *Add(3, 4))
        }
        

        https://play.golang.org/p/RogRZDNGdmY

        【讨论】:

        • 答案似乎与 OP 的问题无关,因为示例中提到了 time.Time() - 您无法修改。
        猜你喜欢
        • 1970-01-01
        • 2017-03-25
        • 2021-01-20
        • 1970-01-01
        • 2015-12-03
        • 1970-01-01
        • 2017-11-05
        • 2021-11-17
        • 1970-01-01
        相关资源
        最近更新 更多