- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我很难理解为什么我的代码在一种状态下存在错误,而在另一种状态下却没有。我已经有一段时间没有介绍指针了,所以我可能已经生疏了!
基本上我有一个我用来在内存中存储对象的存储库结构,它有一个 Store
函数。
type chartsRepository struct {
mtx sync.RWMutex
charts map[ChartName]*Chart
}
func (r *chartsRepository) Store(c *Chart) error {
r.mtx.Lock()
defer r.mtx.Unlock()
r.charts[c.Name] = c
return nil
}
所以它所做的只是设置一个 RW 互斥锁并将指针添加到由标识符引用的映射。
然后我有一个函数,它基本上会遍历这些对象的一部分,将它们全部存储在存储库中。
type service struct {
charts Repository
}
func (svc *service) StoreCharts(arr []Chart) error {
hasError := false
for _, chart := range arr {
err := svc.repo.Store(&chart)
// ... error handling
}
if hasError {
// ... Deals with the error object
return me
}
return nil
}
上面的方法不起作用,起初看起来一切正常,但是在稍后尝试访问数据时, map 中的条目都指向同一个 Chart
对象,尽管有不同的键。
如果我执行以下操作并将指针引用移动到另一个函数,一切都会按预期工作:
func (svc *service) StoreCharts(arr []Chart) error {
// ...
for _, chart := range arr {
err := svc.storeChart(chart)
}
// ...
}
func (svc *service) storeChart(c Chart) error {
return svc.charts.Store(&c)
}
我假设问题是因为循环覆盖了 for
循环中对 chart
的引用,所以指针引用也发生了变化。当指针在独立函数中生成时,该引用永远不会被覆盖。对吗?
我觉得我很愚蠢,但是指针不应该由 &chart
生成并且独立于 chart
引用吗?我还尝试在 for
循环中为指针 p := &chart
创建一个新变量,但这也不起作用。
我应该避免在循环中生成指针吗?
最佳答案
这是因为只有一个循环变量chart
,并且在每次迭代中只为其分配一个新值。因此,如果您尝试获取循环变量的地址,那么在每次迭代中它都是相同的,因此您将存储相同的指针,并且指向的对象(循环变量)在每次迭代中被覆盖(并且在循环之后它将保留上次迭代中分配的值)。
这在 Spec: For statements: For statements with range
clause: 中有所提及
The iteration variables may be declared by the "range" clause using a form of short variable declaration (
:=
). In this case their types are set to the types of the respective iteration values and their scope is the block of the "for" statement; they are re-used in each iteration. If the iteration variables are declared outside the "for" statement, after execution their values will be those of the last iteration.
您的第二个版本有效,因为您将循环变量传递给函数,因此将对其进行复制,然后您存储副本的地址(与循环变量分离)。
你可以在没有函数的情况下达到同样的效果:只需创建一个本地副本并使用它的地址:
for _, chart := range arr {
chart2 := chart
err := svc.repo.Store(&chart2) // Address of the local var
// ... error handling
}
另外请注意,您还可以存储 slice 元素的地址:
for i := range arr {
err := svc.repo.Store(&arr[i]) // Address of the slice element
// ... error handling
}
这样做的缺点是,由于您存储指向 slice 元素的指针,所以只要您保留任何指针, slice 的整个支持数组就必须保存在内存中(数组不能被垃圾收集) .此外,您存储的指针将与 slice 共享相同的 Chart
值,因此如果有人修改传递的 slice 的图表值,则会影响您存储其指针的图表。
查看相关问题:
Golang: Register multiple routes using range for loop slices/map
Why do these two for loop variations give me different behavior?
关于for-loop - 在 for 循环中使用指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48826460/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我在64位linux下使用c++,编译器(g++)也是64位的。当我打印某个变量的地址时,例如一个整数,它应该打印一个 64 位整数,但实际上它打印了一个 48 位整数。 int i; cout <<
我是一名优秀的程序员,十分优秀!