所以我回来时有更多的初学者问题,我似乎无法解决这个问题。 我正在尝试以下代码。
func main() {
start := time.Now()
var powers []*big.Int
for i := 1; i < 1000; i++ {
I := big.NewInt(int64(i))
I.Mul(I, I)
powers = append(powers, I)
}
fmt.Println(powers)
fmt.Println(time.Since(start))
start = time.Now()
var seqDiffs []*big.Int
diff := new(big.Int)
for i, v := range powers {
if i == len(powers)-2 {
break
}
diff = v.Sub(powers[i+1], v)
seqDiffs = append(seqDiffs, diff)
}
fmt.Println(seqDiffs)
fmt.Println(time.Since(start))
}
我的目的是以下列方式将Sub()的结果分配给diff
diff.Sub(powers[i+1], v)
但是这导致seqDiffs的值为1995(正确的最后一个值)反复重复。我知道这可能是因为seqDiffs只是一个指向相同内存地址的指针列表,但我不明白为什么以下工作正常
v.Sub(powers[i+1], v)
seqDiffs = append(seqDiffs, v)
这导致seqDiffs是从3到1995的所有奇数的列表,这是正确的,但这本质上仍然是指向相同内存地址的指针列表? 另外为什么以下正确的时候它也应该导致seqDiffs成为同一个内存地址的指针列表呢?
diff = v.Sub(powers[i+1], v)
seqDiffs = append(seqDiffs, diff)
我也尝试过以下方式
diff := new(*big.Int)
for i, v := range powers {
if i == len(powers)-2 {
break
}
diff.Sub(powers[i+1], v)
seqDiffs = append(seqDiffs, diff)
}
但是从ide中收到了这些错误:
*./sequentialPowers.go:26: calling method Sub with receiver diff (type **big.Int) requires explicit dereference
./sequentialPowers.go:27: cannot use diff (type **big.Int) as type *big.Int in append*
我如何进行“明确”的解除引用?
答案 0 :(得分:2)
在使用Go中的指针调试问题时,了解正在发生的事情的一种方法是使用fmt.Printf
使用%p
来打印感兴趣的变量的内存地址。
关于为什么在将diff.Sub(powers[i+1], v)
的结果附加到*big.Int
的切片时,为什么会在每个索引具有相同值的切片中产生结果时,您的第一个问题就是更新内存地址diff
被分配给该片并将该指针的副本附加到片上。因此,切片中的所有值都是指向相同值的指针。
打印diff
的内存地址将显示这种情况。填充切片后 - 执行以下操作:
for _, val := range seqDiffs {
fmt.Printf("%p\n", val) // when i ran this - it printed 0xc4200b7d40 every iteration
}
在第二个示例中,值v
是指向不同地址的big.Int
的指针。您正在将v.Sub(..)
的结果分配给diff
,这会更新diff指向的基础地址。因此,当您将diff
附加到切片时,您会在唯一地址处附加指针的副本。使用fmt.Printf
你可以这样看 -
var seqDiffs []*big.Int
diff := new(big.Int)
for i, v := range powers {
if i == len(powers)-2 {
break
}
diff = v.Sub(powers[i+1], v)
fmt.Printf("%p\n", diff) // 1st iteration 0xc4200109e0, 2nd 0xc420010a00, 3rd 0xc420010a20, etc
seqDiffs = append(seqDiffs, diff)
}
关于你的第二个问题 - 在Go中使用new
关键字分配指定类型的内存但不初始化它(check the docs)。在你的情况下对new
的调用会分配一种指向big.Int
(**big.Int
)的指针的类型,因此编译器错误说你不能在调用{{{ 1}}。
要明确取消引用append
以便在其上调用diff
,您必须将代码修改为以下内容:
Sub
在Go中,选择器表达式为您指向结构的指针,但在这种情况下,您在指向指针的指针上调用方法,因此您必须显式取消引用它。
可以找到关于Go中结构(选择器表达式)的调用方法的非常有用的信息here
并将其添加到切片
(*diff).Sub(powers[i+1], v)