Мне нужно создать фрагмент указателей для проекта Go, над которым я работаю, который ссылается на элементы в фрагменте. Ожидаемым поведением было бы то, что я мог бы изменить один из разыменованных элементов в срезе указателей, и это изменило бы исходный элемент в обычном списке, на который он указывает. Ожидается, что изменение исходных элементов также будет отображаться как новое значение при разыменовании указателей в срезе. Однако ни одно из этих действий, похоже, не работает.
Вот демо-код, который я написал, чтобы воспроизвести это.
package main
import "fmt"
func main() {
var x []int = []int{5,4,3,2,1}
var y *[]int = &x
var g []*int
for _, x := range x {
g = append(g, &x)
}
fmt.Println("x, y, g, *g = ")
fmt.Println(x)
fmt.Println(y)
fmt.Println(g)
printPtr(g)
fmt.Println()
fmt.Println()
fmt.Println("Setting *g[0] to 10")
*g[0] = 10
fmt.Println("*g = ")
printPtr(g)
fmt.Println()
fmt.Println()
fmt.Println("Setting x[1] to 17")
x[1] = 17
fmt.Println("x, y, *g = ")
fmt.Println(x)
fmt.Println(y)
printPtr(g)
fmt.Println()
}
func printPtr(i []*int) {
for _, v := range i {
fmt.Print(*v)
fmt.Print(" ")
}
}
Этот код печатает:
x, y, g, *g =
[5 4 3 2 1]
&[5 4 3 2 1]
[0x140000a6018 0x140000a6020 0x140000a6028 0x140000a6030 0x140000a6038]
5 4 3 2 1
Setting *g[0] to 10
*g =
10 4 3 2 1
Setting x[1] to 17
x, y, *g =
[5 17 3 2 1]
&[5 17 3 2 1]
10 4 3 2 1
Кажется, что эти два куска каким-то образом не связаны. Что именно здесь идет не так?
(p.s. Мне нужен фрагмент указателей вместо указателя на фрагмент по странным конкретным причинам в моем проекте, в том числе из-за того, что фрагмент указателей и обычный фрагмент могут быть разной длины. Если нет способа добиться этого, я конечно, я мог бы использовать другой метод, однако поначалу он показался самым простым)
Выражение диапазона _, x := range x
объявляет новую переменную x
, ограниченную областью действия цикла. Элемент среза присваивается x
на каждой итерации цикла.
Петля
for _, x := range x {
g = append(g, &x)
}
добавляет адрес переменной цикла x
к срезу g
.
Используйте этот код, чтобы добавить адрес элемента среза к g
:
for i := range x {
g = append(g, &x[i])
}
Примечание. Переменная x
, объявленная в цикле вопроса, затеняет переменную среза x
. Слежка не является причиной проблемы, а является плохой практикой.