Considering you can (can't think of a great way to put it, but) manipulate pointers in Go, is it possible to perform pointer arithmetic like you would in C, say for iterating over an array? I know loops are just fine for that kind of things these days but I'm just curious if it's possible.
Asked
Active
Viewed 2.0k times
2 Answers
60
No. From the Go FAQ:
Why is there no pointer arithmetic?
Safety. Without pointer arithmetic it's possible to create a language that can never derive an illegal address that succeeds incorrectly. Compiler and hardware technology have advanced to the point where a loop using array indices can be as efficient as a loop using pointer arithmetic. Also, the lack of pointer arithmetic can simplify the implementation of the garbage collector.
That being said, you can get around this by using the unsafe
package, but just don't:
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)
}
}

Community
- 1
- 1
-
if you do this, use `//go:nosplit`, else you risk corrupting the gc's state. – thwd Sep 21 '15 at 19:44
-
9I don't see why //go:nosplit is going to make a difference here one way or another. The //go:nosplit comment tells the compiler to not check for stack overflow when entering the function. That has the side effect that the garbage collector will not run when entering the function. But these pointers are being manipulated inside the function, and go:nosplit isn't going to affect that. The issue for documenting when it is safe to convert between unsafe.Pointer and uintptr is https://golang.org/issue/8994. – Ian Lance Taylor Oct 20 '15 at 23:07
4
As of Go 1.17, we now have unsafe.Add
, which makes it a little easier:
package main
import (
"unsafe"
)
func main() {
vals := []int{10, 20, 30, 40}
ptrStart := unsafe.Pointer(&vals[0])
itemSize := unsafe.Sizeof(vals[0])
for i := 0; i < len(vals); i++ {
item := *(*int)(unsafe.Add(ptrStart, uintptr(i)*itemSize))
println(item)
}
}

rodrigocfd
- 6,450
- 6
- 34
- 68