【问题标题】:How can I store reference to the result of an operation in Go?如何在 Go 中存储对操作结果的引用?
【发布时间】:2016-03-15 19:32:53
【问题描述】:

好的,很难用语言来描述它,但是假设我有一个存储 int 指针的映射,并且想要将操作的结果作为另一个键存储在我的哈希中:

m := make(map[string]*int)

m["d"] = &(*m["x"] + *m["y"])

这不起作用并给我错误:cannot take the address of *m["x"] & *m["y"]

想法?

【问题讨论】:

  • 为什么要存储这样的东西? m["d"] = m["x"] + m["y"] 确实存储了操作的结果

标签: pointers dictionary go


【解决方案1】:

指针是内存地址。例如一个变量在内存中有一个地址。

3 + 4 这样的操作的结果没有地址,因为没有为其分配特定的内存。结果可能只存在于处理器寄存器中。

您必须分配可以将其地址放入映射的内存。最简单直接的就是为它创建一个局部变量。

看这个例子:

x, y := 1, 2
m := map[string]*int{"x": &x, "y": &y}

d := *m["x"] + *m["y"]
m["d"] = &d

fmt.Println(m["d"], *m["d"])

输出(在Go Playground 上试试):

0x10438300 3

注意:如果上面的代码是在一个函数中,那么我们刚刚放入map中的局部变量(d)的地址即使我们从函数中返回也会继续存在(也就是说,如果 map 在外部返回或创建 - 例如全局变量)。在 Go 中,获取并返回局部变量的地址是非常安全的。编译器将分析代码,如果地址(指针)转义函数,它将自动分配到堆上(而不是堆栈上)。详情见FAQ: How do I know whether a variable is allocated on the heap or the stack?

注意 #2: 还有其他方法可以创建指向值的指针(如本答案所述:How do I do a literal *int64 in Go?),但它们只是“技巧”,并没有更好或更多高效的。使用局部变量是最简洁和推荐的方法。

例如,这在不创建局部变量的情况下也可以工作,但它显然根本不直观:

m["d"] = &[]int{*m["x"] + *m["y"]}[0]

输出是一样的。在Go Playground 上试试吧。

【讨论】:

    【解决方案2】:

    加法的结果被放置在某个临时的地方(在堆栈上),因此获取它的地址是不安全的。您应该能够通过在堆上显式分配 int 来保存您的结果来解决此问题:

    result := make(int)
    *result = *m["x"] + *m["y"]
    m["d"] = result
    

    【讨论】:

      【解决方案3】:

      在 Go 中,不能引用文字值(正式称为 r 值)。 Try以下:

      package main
      
      import "fmt"
      
      func main() {
      
          x := 3;
          y := 2;
          m := make(map[string]*int)
      
          m["x"] = &x
          m["y"] = &y
      
          f := *m["x"] + *m["y"]
          m["d"]  =  &f
      
          fmt.Printf("Result: %d\n",*m["d"])
      }
      

      看看this 教程。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-25
        • 2019-06-27
        • 2017-03-22
        • 1970-01-01
        • 1970-01-01
        • 2012-11-18
        • 2019-08-24
        相关资源
        最近更新 更多