In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)05/31 Report--
This article will explain in detail how to use unsafe and uintptr pointers in golang. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.
Pointer types in 1.golang
Three types
Actually, there are three kinds of pointers:
One is our common pointer, which is represented by *.
One is that unsafe.Pointer,Pointer is a type under the unsafe package.
The last one is uintptr,uintptr, which can be calculated, that is, it can be + +-
There is a transformational relationship between them:
* unsafe.Pointer uintptr
It is important to note that uintptr does not have pointer semantics, meaning that the objects pointed to by uintptr will be mercilessly recycled by gc. Unsafe.Pointer, on the other hand, has pointer semantics to protect the objects it points to from garbage collection when they are "useful".
You can probably guess from this relationship that the pointer we use * p is converted to Pointer and then converted to uintptr for operation and then returned to the original path, which is theoretically equivalent to the operation of a pointer. Let's put it into practice.
two。 Concrete operation
Unsafe operation slice
Func main () {s: = make ([] int) 10) s [1] = 2p: = & s [0] fmt.Println (* p) up: = uintptr (unsafe.Pointer (p)) / / it is possible to be recycled here, so it is best to write (* int) unsafe.Pointer (uintptr (unsafe.Pointer (p)) + unsafe.Sizeof (int (0)) up+ = unsafe.Sizeof (int (0)) / / this is not up++p2: = (* int) (unsafe.Pointer (up)) fmt.Println (* p2)}
Output:
0
two
We can see from the code that we first point the pointer to the first position of the slice, then convert to get uintptr, operate uintptr + 8 bits (note that it cannot be + + because what is stored here is int, the position of the next element is separated by an example of int bytes), and finally convert back to get the pointer, take the value, and then get the second position of the slice.
Unsafe operation struct (private properties can be accessed)
We know that if the property defined in a structure is private, then the property cannot be accessed by the outside world. Let's take a look at the following:
Package maintype User struct {age intname string} package mainfunc main () {user: = & User {} fmt.Println (user) s: = (* int) (unsafe.Pointer (user)) * s = 15up: = uintptr (unsafe.Pointer (user)) + unsafe.Sizeof (int (0)) namep: = (* string) (unsafe.Pointer (up) * namep = "ljy" fmt.Println (user)}
User is a structure in another basic package, where age begins with lowercase. In theory, we have no way to modify the value of age externally, but after the above operation, the output is as follows:
& {0}
& {10 xxx}
That is to say, the private property of the structure was successfully operated.
Incidentally: creating a structure will be allocated a contiguous piece of memory, and the address of the structure represents the address of the first member.
String and byte array conversion inplace
We know that it is very convenient to convert a string to [] byte.
S: = "123" a: = [] byte (s)
But this needs to open up additional space, so how to achieve in-place conversion that does not require copying data?
In fact, from the underlying storage point of view, the storage rule of string is the same as that of [] byte, that is, the pointer starts from a certain location to a space, one grid in the middle. So you can do it with unsafe.
Func main () {s: = "123" a: = [] byte (s) print ("s =", & s, "\ n") print ("a =", & a, "\ n") a2: = (* [] byte) (unsafe.Pointer (& s)) print ("a2 =", a2, "\ n") fmt.Println (* a2)} output result: s = 0xc420055f40a = 0xc420055f60a2 = 0xc420055f40 [49 50 51]
We can see that the addresses of s and an are different, but the addresses of s and a2 are the same, and a2 is already a [] byte.
Existing problems
In fact, there is a problem with this conversion, which is that the Cap of the new [] byte is not initialized correctly.
Let's print it and take a look at the cap.
The result of fmt.Println ("cap a =", cap (a)) fmt.Println ("cap a2 =", cap (* a2)) is: cap a = 32cap a2 = 17418400
The cause of the problem
Look at it under src/reflect/value.go
Type StringHeader struct {Data uintptr Len int} type SliceHeader struct {Data uintptr Len int Cap int}
It is easy to understand that string does not have cap while [] byte does, so it is easy to understand that string does not have capacity expansion, so the new [] byte does not assign cap, so it uses the default value.
Problem solving
StringHeader: = (* reflect.StringHeader) (unsafe.Pointer (& s) bh: = reflect.SliceHeader {Data: stringHeader.Data, Len: stringHeader.Len, Cap: stringHeader.Len,} return * (* [] byte) (unsafe.Pointer (& bh))
This can be done by resetting the SliceHeader
This is the end of the article on "how to use unsafe and uintptr pointers in golang". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.