unsafe packages in go and their usage details

  • 2020-07-21 08:28:41
  • OfStack

Unsafe code is an Go code that bypasses go type safety and memory security checks. For the most part, unsafe code is related to Pointers. But keep in mind that using unsafe code can hurt your program, so don't use unsafe code if you're not completely sure you'll need it.

Take unsafe. go as an example, see the use of unsafe code in 1


package main
import (
 "fmt"
 "unsafe"
)
func main() {
 var value int64 = 5
 var p1 = &value
 var p2 = (*int32)(unsafe.Pointer(p1))

Here we use unsafe.Pointer() Method that lets you create a pointer to p2 of int32 to an value variable of int64 that is accessed using the pointer to p1.

Any go pointer can be converted to unsafe.Pointer Pointer.

unsafe.Pointer A pointer of type can override the system type of go. This is no doubt fast, but can be dangerous if not used carefully or correctly, giving developers more options to control their data.

The latter part of unsafe is as follows


fmt.Println("*p1: ", *p1)
 fmt.Println("*p2: ", *p2)
 *p1 = 5434123412312431212
 fmt.Println(value)
 fmt.Println("*p2: ", *p2)
 *p1 = 54341234
 fmt.Println(value)
 fmt.Println("*p2: ", *p2)
}

You can demystify a pointer by using an asterisk (*)

Running ES43en.go yields the following output

[

*p1: 5
*p2: 5
5434123412312431212
*p2: -930866580
54341234
*p2: 54341234

]

So what does this output say? It tells us that a pointer using 32-bit cannot store an integer type of 64-ES63en

About unsafe package

Now that you've actually worked with the unsafe package, let's look at why this library is so special.

First of all, if you look at the source code of the unsafe package, you might be surprised. in macOS Hight Sierra On the system, you can use Homebrew to install Go. unsafe source path at  /usr/local/Cellar/go/1.9.1/libexec/src/unsafe/unsafe.go Below, without comments, it reads as follows


$ cd /usr/local/Cellar/go/1.9.1/libexec/src/unsafe/
$ grep -v '^//' unsafe.go|grep -v '^$'
package unsafe
type ArbitraryType int
type Pointer *ArbitraryType
func Sizeof(x ArbitraryType) uintptr
func Offsetof(x ArbitraryType) uintptr
func Alignof(x ArbitraryType) uintptr

OK, where is the go code for other unsafe packages? The answer is simple: the Go compiler implements the unsafe library when you get to your program.

Many system libraries such as runtime, syscall, and os make frequent use of the usafe library

Another example of an usafe package

Let's go through 1 moreUnsafe.go To learn about unsafe library compatibility.  moreUnsafe.go All it does is use a pointer to access all the elements in the array.


package main
import (
 "fmt"
 "unsafe"
)
func main() {
 array := [...]int{0, 1, -2, 3, 4}
 pointer := &array[0]
 fmt.Print(*pointer, " ")
 memoryAddress := uintptr(unsafe.Pointer(pointer)) + unsafe.Sizeof(array[0])
 for i := 0; i < len(array)-1; i++ {
 pointer = (*int)(unsafe.Pointer(memoryAddress))
 fmt.Print(*pointer, " ")
 memoryAddress = uintptr(unsafe.Pointer(pointer)) + unsafe.Sizeof(array[0])
 }

First, the pointer variable points to the address of array[0], which is the first element of an integer array. The pointer variable that next points to the integer value is passed in unsafe.Pointer() Method, and pass in uintptr. The final result is saved memoryAddress In the water.

unsafe.Sizeof(array[0]) To access the next array element, the value is the amount of memory each element takes up. Each for loop adds this value to memoryAddress to get the address of the next array element. The * symbol for *pointer dereferences the pointer and returns the stored integer value.

The following code is as follows:


fmt.Println()
 pointer = (*int)(unsafe.Pointer(memoryAddress))
 fmt.Print("One more: ", *pointer, " ")
 memoryAddress = uintptr(unsafe.Pointer(pointer)) + unsafe.Sizeof(array[0])
 fmt.Println()
}

Here, we try to access a nonexistent array element using Pointers and memory addresses. Because of the use of the unsafe package, the Go compiler does not catch such logic errors, resulting in 1 unexpected thing.

Executing ES126en.go produces the following output:


$ go run moreUnsafe.go
0 1 -2 3 4 
One more: 824634191624

Now, you use Pointers to access all the elements in the Go array. However, the real problem here is that when you try to access an invalid array element, the program does not make an error but returns a random number.

conclusion

unsafe is very powerful and can convert any pointer to unsafe.Pointer Pointers, while giving developers more means to manipulate the data. In contrast, if used improperly, it can cause unexpected errors, which is why the package is called unsafe, so try not to use unsafe when you are not sure if you should use it.


Related articles: