如何从函数调用中获取返回值的指针?

时间:2015-06-10 00:07:04

标签: pointers go

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

  

./ c.go:5:不能取时间地址。现在()

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

package main

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

3 个答案:

答案 0 :(得分:22)

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

实际上,可能是因为函数的返回值可能没有可用的地址;它可能在一个寄存器中(在这种情况下它绝对不可寻址)或在堆栈中(在这种情况下它有一个地址,但如果它被放入,它将无效)一个逃避当前范围的指针。为了保证可寻址性,Go必须完全相同地将它分配给一个变量。但Go是一种语言,如果它要为它分配存储空间它会变成一个变量,因为你说过,而不是因为编译器神奇地决定了它。所以它并没有使函数的结果可寻址。

或者我可能过度思考它并且他们根本不想为返回一个值的函数与返回多个函数的函数有特殊情况:)

答案 1 :(得分:13)

您无法直接获取函数调用的地址(或者更确切地说是函数的返回值),如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()),切片被索引(0 th 元素)并且采用0 th 元素的地址。

所以只需使用局部变量:

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?

答案 2 :(得分:0)

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

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