Hi Hello, I am Brother K. A back-end programmer who has worked in a large factory for 6 years and is still continuing to move bricks.
We all know that C/C++ provides a powerful universal pointer void*, and any type of pointer can be converted to universal pointers. In addition, the pointer can also perform arithmetic operations such as addition and subtraction. So, is there a similar function in Golang? The answer is yes, this is the unsafe package we are going to discuss today.
This article will explore in-depth the functions and principles of the unsafe package. At the same time, we learn something, on the one hand, for practical application, and on the other hand, for the purpose of utilitarian interviews. Therefore, this article will also introduce to you the typical applications of unsafe package and high-frequency interview questions.
Function
In order to achieve the purpose of flexible memory operation, the unsafe package mainly provides 4 functions:
- Defines the Pointer type,Any type of pointer can be converted to Pointer, similar to void* in C language
var a int = 1 p := (&a) // Other types of pointer to Pointerb := (*int)(p) // Pointer type to other type pointers(*b) // Output1
- The uintptr type is defined,Pointer and uintptr can be converted to each other.This realizes arithmetic operations such as addition and subtraction of pointers.
type Person struct { age int name string } person := Person{age:18,name:"Brother K"} p := (&person) // Other types of pointer to Pointeru := uintptr(p) // Convert Pointer type to uintptru=u+8 // uintptr addition and subtraction operationpName := (u) // Convert uintptr to Pointername := *(*string)(pName) (name) // Outputkelder brother
uintptr is used for pointer operation, it just stores onePointer address
ofint
Type, GC does not treat uintptr as a pointer, so the target of type uintptr may be recycled
- Gets any type of memory alignment, offset, and memory size.
func Alignof(x ArbitraryType) uintptr // Memory alignmentfunc Offsetof(x ArbitraryType) uintptr // Memory offsetfunc Sizeof(x ArbitraryType) uintptr // Memory size
- Alignof returns the memory address alignment value m of type x. The address of this type in memory must be a multiple of m (based on memory read and write performance considerations).
- Offsetof returns the number of bytes at the position of the structure member x in memory from the beginning of the structure (the offset of the first field of the structure is 0), that is, the offset.
- Sizeof Returns the number of bytes occupied by type x. If the type x structure has a pointer, Sizeof does not contain the size of the content pointed to by the x pointer member.
ArbitraryType is a placeholder, and the golang compiler will be replaced with a specific type when compiled.
- High performance type conversion.
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType func SliceData(slice []ArbitraryType) *ArbitraryType func String(ptr *byte, len IntegerType) string func StringData(str string) *byte
- Slice Pass in a pointer and length of any type, and return the slice variable of that type
- SliceData Passes in a slice variable of any type and returns a pointer to the underlying array of the slice.
- String derives a string of specified length from a byte pointer.
- StringData is used to get the pointer to the first byte in the underlying byte sequence of a string.
High-performance type conversion principle
Why are Slice, SliceData, String, and StringData high-performance type conversion functions? Let’s analyze their implementation principles below.
This article takes String and StringData functions as examples, and the implementation principles of Slice and SliceData functions are similar. Before introducing the principle of function implementation, first understand the underlying data structure of string type StringHeader. The string type will be compiled into this structure by the Golang compiler, where Data is the byte array address and Len is the string length.
type StringHeader struct { Data uintptr // byte array address Len int // string length}
The String function will be compiled by Go into the following function implementation logic. We can find that converting the ptr pointer to the string type directly assigns ptr to the member Data of the StringHeader without re-copying the byte array pointed to by ptr. This enables high-performance type conversion through zero copy.
import ( "fmt" "reflect" "unsafe" ) func String(ptr *byte, len int) string { p := (uintptr)((ptr)) hdr := &{ Data: p, Len: len, } // Convert StringHeader to string str := *(*string)((hdr)) return str } func main() { bytes := []byte{'h', 'e', 'l', 'l', 'o'} ptr := &bytes[0] len := 5 str := String(ptr, len) (str) // Output hello}
The StringData function will be compiled by Go to the following function implementation logic. Similarly, we can find that converting the string type to byte directly takes the uintptr type member Data of the StringHeader and converts it to byte. There is no need to copy the entire string and regenerate the byte array. This enables high-performance type conversion through zero copy.
import ( "fmt" "reflect" "unsafe" ) func StringData(str string) *byte { hdr := (*)((&str)) data := return (*byte)((data)) } func main() { str := "hello" data := StringData(str) (string(*data)) // Output h}
Back to the question, why are Slice, SliceData, String, and StringData high-performance type conversion functions? Through the implementation logic of String and StringData functions, we can know that String and StringData use unsafe packages,Zero copy, realizes high-performance type conversion.
Typical Applications
In practice, there are two common scenarios where unsafe packages are used:
- Communication with operating systems and non-go-written (cgo) code.
func SetData(bytes []byte) { cstr := (*)((&bytes[0])) // Convert to a C char type (cstr, ()(len(bytes))) // Call C functions}
- High performance type conversion.
func Bytes2String(b []byte) string { return *(*string)((&b)) } func String2Bytes(s string) []byte { sh := (*)((&s)) bh := { Data: , Len: , Cap: , } return *(*[]byte)((&bh)) }
High frequency interview questions
- Can you tell me the difference between uintptr?
- Will memory copy occur when a string is converted into a byte array?
Here is the article about how golang uses pointers to flexibly operate memory? This is the article about the analysis of the principle of unsafe package. For more related contents of the original content of the unsafe package, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!