Учитывая, что вы можете (не могу придумать отличный способ выразить это, но) манипулировать указателями в Go, возможно ли выполнять арифметические операции с указателями, как в C, скажем, для перебора массива? Я знаю, что петли в наши дни отлично подходят для таких вещей, но мне просто любопытно, возможно ли это.
Арифметика указателей в Go
Ответы (1)
Нет. Из часто задаваемых вопросов о Go:
Почему нет арифметики указателей?
Безопасность. Без арифметики указателей можно создать язык, который никогда не сможет получить недопустимый адрес, если он окажется неверным. Компилятор и аппаратные технологии продвинулись до такой степени, что цикл, использующий индексы массива, может быть столь же эффективным, как и цикл, использующий арифметику указателей. Также отсутствие арифметики указателей может упростить реализацию сборщика мусора.
При этом вы можете обойти это, используя пакет unsafe
, но просто не делайте этого сильный>:
package main
import "fmt"
import "unsafe"
func main() {
vals := []int{10, 20, 30, 40}
start := unsafe.Pointer(&vals[0])
size := unsafe.Sizeof(int(0))
for i := 0; i < len(vals); i++ {
item := *(*int)(unsafe.Pointer(uintptr(start) + size*uintptr(i)))
fmt.Println(item)
}
}
https://play.golang.org/p/QCHEQqy6Lg
person
Tim Cooper
schedule
21.09.2015
если вы сделаете это, используйте
//go:nosplit
, иначе вы рискуете испортить состояние gc.
- person thwd; 21.09.2015
Я не понимаю, почему //go:nosplit так или иначе будет иметь здесь значение. Комментарий //go:nosplit указывает компилятору не проверять переполнение стека при входе в функцию. Это имеет побочный эффект, заключающийся в том, что сборщик мусора не запускается при входе в функцию. Но эти указатели манипулируются внутри функции, и go:nosplit не повлияет на это. Проблема с документированием безопасного преобразования между unsafe.Pointer и uintptr: golang.org/issue/8994 а>.
- person Ian Lance Taylor; 21.10.2015