Home > Article > Backend Development > What are the operations on pointers in go language?
Go language does not have pointer arithmetic. The syntax of the go language does not support pointer arithmetic, and all pointers are used within a controllable range; but in fact, the go language can use the Pointer() method of the unsafe package to convert pointers into uintptr type numbers to indirectly Implement pointer arithmetic.
The operating environment of this tutorial: Windows 7 system, GO version 1.18, Dell G3 computer.
Memory is a series of storage units with serial numbers. Variables are nicknames assigned by the compiler to memory addresses. So what are pointers?
A pointer is a value that points to another memory address variable
The pointer points to the memory address of the variable, and the pointer is like the memory address of the variable value
Let’s look at a code snippet
func main() { a := 200 b := &a *b++ fmt.Println(a) }
In the first line of the main function, we define a new variable a and assign it a value of 200. Next we define a variable b and assign the address of variable a to b. We don't know the exact storage address of a, but we can still store the address of a in the variable b.
Because of the strongly typed nature of Go, the third line of code may be the most disturbing, b contains a The address of a variable, but we want to increment the value stored in a variable.
In this way we must dereference b and instead refer to a by b following the pointer.
Then we add 1 to the value and store it back at the memory address stored in b.
The last line prints the value of a. You can see that the value of a has increased to 201
Function parameters in the Go language are all value copies. When we want to modify a variable, we cancreate an address pointing to the variable Pointer variable .
Different from pointers in C/C, pointers in Go language cannot be offset and operated, and are safe pointers.
To understand pointers in Go language, you need to know three concepts: Pointer address, pointer type and pointer value.
Pointer operations in Go language are very simple. You only need to remember two symbols: & (take address ) and * (value based on address).
Each variable has an address at runtime, which represents the location of the variable in memory. In the Go language, the & character is used in front of the variable to "get the address" of the variable.
The syntax for taking the variable pointer is as follows:
ptr := &v // v的类型为T
Among them:
v: represents the variable of the taken address, type is T
ptr: A variable used to receive the address. The type of ptr is *T, which is called the pointer type of T. * stands for pointer.
func main() { a := 10 b := &a fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078 fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int fmt.Println(&b) // 0xc00000e018 }
1. When the pointer operator is an lvalue, We can update the state of the target object; when it is an rvalue, it is to obtain the state of the target.
func main() { x := 10 var p *int = &x //获取地址,保存到指针变量 *p += 20 //用指针间接引用,并更新对象 println(p, *p) //输出指针所存储的地址,以及目标对象 }
Output:
0xc000040780 30
2. Pointer types support equality operators, but cannot do addition, subtraction and type conversion. Two pointers are equal if they point to the same address or are both nil.
func main() { x := 10 p := &x p++ //编译报错 invalid operation: p++ (non-numeric type *int) var p2 *int = p+1 //invalid operation: p + 1 (mismatched types *int and int) p2 = &x println(p == p2) //指向同一地址 }
You can use unsafe.Pointer to convert the pointer to uintptr and then perform addition and subtraction operations, but it may cause illegal access.
In many golang programs, although pointers are used, the pointers are not added or subtracted. This is different from C programs. Very different. Golang’s official introductory learning tool (go tour) even says that Go does not support pointer arithmetic. Although this is not actually the case, it seems that I have never seen pointer arithmetic in ordinary go programs (well, I know you want to write unusual programs).
- 但实际上,go 可以通过
unsafe.Pointer
来把指针转换为uintptr
类型的数字,来间接实现指针运算。- 这里请注意,
uintptr
是一种整数类型,而不是指针类型。
比如:
uintptr(unsafe.Pointer(&p)) + 1
就得到了 &p
的下一个字节的位置。然而,根据 《Go Programming Language》 的提示,我们最好直接把这个计算得到的内存地址转换为指针类型:
unsafe.Pointer(uintptr(unsafe.Pointer(&p) + 1))
因为 go 中是有垃圾回收机制的,如果某种 GC 挪动了目标值的内存地址,以整型来存储的指针数值,就成了无效的值。
同时也要注意,go 中对指针的 + 1,真的就只是指向了下一个字节,而 C 中 + 1
或者 ++
考虑了数据类型的长度,会自动指向当前值结尾后的下一个字节(或者说,有可能就是下一个值的开始)。如果 go 中要想实现同样的效果,可以使用 unsafe.Sizeof
方法:
unsafe.Pointer(uintptr(unsafe.Pointer(&p) + unsafe.Sizeof(p)))
最后,另外一种常用的指针操作是转换指针类型。这也可以利用 unsafe 包来实现:
var a int64 = 1 (*int8)(unsafe.Pointer(&a))
如果你没有遇到过需要转换指针类型的需求,可以看看这个项目(端口扫描工具),其中构建 IP 协议首部的代码,就用到了指针类型转换。
The above is the detailed content of What are the operations on pointers in go language?. For more information, please follow other related articles on the PHP Chinese website!