我有这个简单的代码:
import "fmt"
type Foo struct {
val int
}
func main() {
var a = make([]*Foo, 1)
a[0] = &Foo{0}
var b = [3]Foo{Foo{1}, Foo{2}, Foo{3}}
for _, e := range b {
a = append(a, &e)
}
for _, e := range a {
fmt.Printf("%v ", *e)
}
}
我期望它可以打印{0} {1} {2} {3}
,但是可以打印{0} {3} {3} {3}
。这里发生了什么?
这是因为在for
循环中,您使用 副本 而不是slice / array元素本身进行操作。
将for ... range
使得它遍历元素的副本,并追加此一时,循环变量的地址-
这是在所有的迭代相同。因此,您将相同的指针添加3次。而且此临时变量将Foo{3}
在最后一次迭代(数组的最后一个元素)中设置为,因此这就是为什么您看到该变量打印了3次的原因。
修复:不添加循环变量的地址,而是添加数组元素的地址:
for i := range b {
a = append(a, &b[i])
}
输出(在Go Playground上尝试):
{0} {1} {2} {3}
在Go中,有 指针 类型和 非指针
类型,但是没有“引用”(在C
++和Java中使用的含义)。考虑到Go中没有“引用”类型的事实,这不是意外的行为。循环变量只是一个“普通”局部变量,它只能保存一个值(可以是指针或非指针),而不能保存引用。
从这个答案摘录:
指针是值,就像说
int
数字一样。区别在于该值的解释:指针被解释为内存地址,而int
s被解释为整数。当要改变类型的变量的值
int
,则通过一个指向int
它的类型的*int
,并且修改尖锐的物体:*i = newvalue
(分配值是一个int
)。指针也是如此:当您想要更改指针类型的变量的值时
*int
,可以将指针传递给类型的指针,*int
然后**int
修改指向的对象:(*i = &newvalue
分配的值为*int
)。
总而言之,循环变量只是具有您要循环的数组/切片的元素类型的普通变量,并且要使其具有实际迭代的值,必须将值赋给该变量,该值将复制该值。在下一次迭代中将覆盖它。
我试图实现BFS算法,以找到图中的所有路径(从src和dp)。我使用一个切片来模拟一个队列,但是当我在for循环中追加多个元素时,切片会损坏(追加没有按预期工作)。我不知道为什么。我是新来戈兰的
问题内容: 考虑以下代码: 现在,更改方法的可见性,我得到: (for ,for ) (看起来像)。 我期望所有东西都像声明时一样。但是,尽管和本质上是同一件事,但根据in 和的可见性,它们会产生不同的结果。为什么会这样? 问题答案: 继承/覆盖私有方法 在PHP中,子类中的方法(包括私有方法)为: 复制;保留原始功能的范围。 已替换(如果需要,则为“覆盖”)。 您可以使用以下代码查看此内容: 现
问题内容: 我今天在go代码中遇到了奇怪的行为:当我追加到in循环中,然后尝试根据循环的结果创建new时,最后一个重写了previous 。 在这个特殊的例子这意味着 ,和切片的最后一个元素都没有,和分别,但是......始终! 第二个示例- 行为符合预期。 链接至play.golang:https : //play.golang.org/p/INADVS3Ats 经过一番阅读,挖掘和实验后,我发
问题内容: 我在go中编写了一个简单的UDP服务器。 当我这样做时,它会打印我发送给它的所有包裹。但是,当客户端停止运行时,它将停止传递到文件。 客户端是发送10k请求的简单程序。因此,在文件中,我大约有50%的已发送软件包。当我再次运行客户端时,文件会再次增长,直到客户端脚本完成。 服务器代码: 这是客户端代码: 问题答案: 如您所怀疑,由于UDP的性质,似乎 UDP数据包丢失 。由于UDP是无
我有以下代码来解析一个JSON文件: 要处理以下JSON文件: 如果我执行此代码,我将收到以下错误: 所以我开始一步一步地调试应用程序,看看part processing()中的哪个代码部分抛出了这个异常。令人惊讶的是,那里的所有代码都正常执行:没有抛出异常,也没有返回结果I except。 更让我惊讶的是,当我稍微改变第一种方法的代码时,它可以在不产生异常的情况下工作。 我不知道println方
Go语言中切片的cap和len有什么区别? 根据定义: 切片既有长度也有容量。 切片的长度是它包含的元素数。 切片的容量是底层数组中的元素数,从切片中的第一个元素开始计数。 len是否仅表示非空值?