英文:
How can I store reference to the result of an operation in Go?
问题
好的,以下是翻译好的内容:
好的,很难用文字来描述,但是假设我有一个存储int
指针的映射表,并且想要将操作的结果作为另一个键存储在我的哈希表中:
m := make(map[string]*int)
m["d"] = &(*m["x"] + *m["y"])
这样做是不起作用的,并且会给出错误:cannot take the address of *m["x"] & *m["y"]
你有什么想法?
英文:
Okay it's hard to describe it in words but let's say I have a map that stores int
pointers, and want to store the result of an operation as another key in my hash:
m := make(map[string]*int)
m["d"] = &(*m["x"] + *m["y"])
This doesn't work and gives me the error: cannot take the address of *m["x"] & *m["y"]
Thoughts?
答案1
得分: 18
指针是一个内存地址。例如,变量在内存中有一个地址。
像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
**注意:**如果上述代码在一个函数中,我们刚刚放入映射中的局部变量(d
)的地址将继续存在,即使我们从函数中返回(即如果map
是在函数外返回或创建的,例如全局变量)。在Go中,获取并返回局部变量的地址是完全安全的。编译器将分析代码,如果地址(指针)逃逸出函数,它将自动分配在堆上(而不是栈上)。有关详细信息,请参阅FAQ:如何知道变量是在堆上还是栈上分配的?
**注意2:**还有其他创建指向值的指针的方法(详见此答案:如何在Go中创建字面量*int64?),但它们只是“技巧”,并不更好或更高效。使用局部变量是最清晰和推荐的方法。
例如,不创建局部变量也可以实现,但显然不直观:
m["d"] = &[]int{*m["x"] + *m["y"]}[0]
输出结果相同。在Go Playground上尝试一下。
英文:
A pointer is a memory address. For example a variable has an address in memory.
The result of an operation like 3 + 4
does not have an address because there is no specific memory allocated for it. The result may just live in processor registers.
You have to allocate memory whose address you can put into the map. The easiest and most straightforward is to create a local variable for it.
See this example:
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"])
Output (try it on the Go Playground):
0x10438300 3
Note: If the code above is in a function, the address of the local variable (d
) that we just put into the map will continue to live even if we return from the function (that is if the map
is returned or created outside - e.g. a global variable). In Go it is perfectly safe to take and return the address of a local variable. The compiler will analyze the code and if the address (pointer) escapes the function, it will automatically be allocated on the heap (and not on the stack). For details see FAQ: How do I know whether a variable is allocated on the heap or the stack?
Note #2: There are other ways to create a pointer to a value (as detailed in this answer: How do I do a literal *int64 in Go?), but they are just "tricks" and are not nicer or more efficient. Using a local variable is the cleanest and recommended way.
For example this also works without creating a local variable, but it's obviously not intuitive at all:
m["d"] = &[]int{*m["x"] + *m["y"]}[0]
Output is the same. Try it on the Go Playground.
答案2
得分: 1
将加法的结果放在临时位置(堆栈)上,因此取其地址是不安全的。你可以通过显式地在堆上分配一个int
来解决这个问题:
result := make(int)
*result = *m["x"] + *m["y"]
m["d"] = result
英文:
The result of the addition is placed somewhere transient (on the stack) and it would therefore not be safe to take its address. You should be able to work around this by explicitly allocating an int
on the heap to hold your result:
result := make(int)
*result = *m["x"] + *m["y"]
m["d"] = result
答案3
得分: 0
在Go语言中,你不能获取字面值(也称为r-value)的引用。请尝试以下代码:
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"])
}
你可以查看这个教程。
英文:
In Go, you can not take the reference of a literal value (formally known as an r-value). Try the following:
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"])
}
Have a look at this tutorial.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论