Golang in the unsafe package tutorial

Source: Internet
Author: User

Unsafe Content Introduction

type ArbitraryType inttype Pointer *ArbitraryTypefunc Sizeof(x ArbitraryType) uintptrfunc Offsetof(x ArbitraryType) uintptrfunc Alignof(x ArbitraryType) uintptr

The unsafe package has only two types, three functions, but is very powerful.

Unsafe library Let Golang like C language Operation computer memory, but this is not Golang recommended, can not use as much as its name is expressed, it bypasses the Golang memory security principle, is unsafe, easy to make your program appear inexplicable problems, Not conducive to the extension and maintenance of the program.

A brief introduction to the next Golang pointer

    1. * type : normal pointer, used to pass object address, cannot be pointer operation.

    2. unsafe. Pointer: Generic pointer type for converting different types of pointers and not for pointer operations.

    3. uintptr: For pointer arithmetic, GC does not take uintptr as pointer, UIntPtr cannot hold object. the target of the UIntPtr type is recycled .

Unsafe. Pointer can be converted to and from normal pointers.

Unsafe. Pointer can be converted to and from UIntPtr.

That means unsafe. Pointer is a bridge that allows arbitrary types of pointers to be converted to each other, or any type of pointer can be converted to UINTPTR for pointer operations .

UIntPtr this type, in Golang, the byte length is also the same as Int. Usually pointer can not participate in the operation, such as you want to add an offset to a pointer address, pointer is not able to do this operation, then who can? Is the uintptr type, as long as the pointer type converted to UINTPTR type, after the addition and subtraction, converted to pointer, through the * operation, value, modify the value, arbitrary.

Two description of types

// ArbitraryType is here for the purposes of documentation only and is not actually// part of the unsafe package. It represents the type of an arbitrary Go expression.type ArbitraryType inttype Pointer *ArbitraryType

Arbitrarytype is an alias of int, which gives special meaning to Arbitrarytype in go. Represents an arbitrary go expression type.

Pointer is an alias of the int pointer type, and in go you can interpret the Pointer type as the parent type of any pointer.

The following is an introduction to the usage scenarios for pointer in official documents

Pointer represents a pointer to an arbitrary type. There are four special operationsavailable for type Pointer that are not available for other types:- A pointer value of any type can be converted to a Pointer.- A Pointer can be converted to a pointer value of any type.- A uintptr can be converted to a Pointer.- A Pointer can be converted to a uintptr.Pointer therefore allows a program to defeat the type system and read and write arbitrary memory. It should be used with extreme care.

The pointer type length of the Golang is the same as the length of the int type and the number of bytes in memory.

A variable of type Arbitrarytype can also be a pointer. So, don't die of the int behind the type.

Introduction to three functions

Sizeof takes an expression x of any type and returns the size in bytes//of a hypothetical variable V as if V were DECLA Red via var v = x.//The size does not include any memory possibly referenced by x.//for instance, if X is a slice, size of returns the size of the slice//descriptor, not the size of the memory referenced by the Slice.**func Sizeof (x arbitrar YType) uintptr**//Offsetof returns the offset within the struct of the field represented by x,//which must is of the for M Structvalue.field. In other words, it returns the//number of bytes between the start of the struct and the start of the Field.**func Offseto F (x Arbitrarytype) uintptr**//Alignof takes an expression x of any type and returns the required alignment//of a hypothe  Tical variable V as if V was declared via var v = x.//It's the largest value m such that the address of V are always zero MoD m.//It is the same as the value returned by reflect. TypeOf (x). Align ().//As a special case, if a variable s is of StrucT type and F is a field//within that struct, then Alignof (S.F) would return the required alignment//of a field of that Ty PE within a struct. This was the same as the//value returned by reflect. TypeOf (S.F). Fieldalign (). **func Alignof (x arbitrarytype) uintptr**

The analysis found that the parameters of these three functions are arbitrarytype types, which is to accept any type of variable.

    1. Alignof returns the number of variable alignment bytes
    2. The Offsetof returns the offset of the specified property, although the function receives any type of variable, but there is a premise that the variable is a struct type and cannot be directly used as a parameter to the struct type's variable. You can only use the property of this struct type variable as an argument.
    3. Sizeof returns the number of bytes that the variable occupies in memory, and remember that if it is slice, it does not return the actual length of the slice in memory .

Example

Sizeof

Unsafe. The sizeof function returns a value of type uintptr (an expression, the size of a value):

var p float64 = 99fmt.Println(reflect.TypeOf(unsafe.Sizeof(p)))fmt.Println(unsafe.Sizeof(p))

Results

uintptr8

Unsafe. sizeof accepts any type of value (an expression), returns the number of bytes it occupies, and in the example above, the size of float64 is 8bytes.

What happens if an object passing in a pointer type returns?

type W struct {    a byte    b int32    c int64}var w *Wfmt.Println(unsafe.Sizeof(w)) //4 or 8

In general, it could be 4 or 8 because W is a pointer-type UINTPTR, while UIntPtr is platform-dependent, the size is 4bytes under the 32-bit system and 8bytes under the 64-bit system.

To get the size of a value type, you need to take a value for the pointer variable:

fmt.Println(unsafe.Sizeof(*w)) //16

Snap To

In the above example, the size of *w is 16, according to common Sense, byte occupies 1 bytes, Int32 occupies 4 bytes, Int64 occupies 8 bytes, the size should be 13. This is because of the alignment, unsafe. Alignof can calculate the alignment value:

unsafe.Alignof(w.a)   // type byteunsafe.Alignof(w.b)   // type int32 unsafe.Alignof(w.c)   // type int64

1, 4, 8, respectively, because the alignment value of the Int32 type is 4bytes and must be a multiple of 4, so the byte type is populated with 3 bytes. Instead of padding, the size of the two and the alignment value for 8bytes,int64 are 8bytes and do not need to be filled, so use unsafe. sizeof gets the size of the structure to 4+4+8=16.

The alignment method of reflection package

Reflection packages also have some methods that you can use to calculate alignment values:

Unsafe. Alignof (W) is equivalent to reflect. TypeOf (W). Align.

Unsafe. Alignof (W.I) is equivalent to reflect. Typeof (W.I). Fieldalign ().

Alignment value of the struct

If we are calculating the alignment value of a struct instead of a field or base type, what is the value?

type W struct {    a byte    b int32    c int64}var w *Wvar w2 Wfmt.Println(unsafe.Alignof(w))fmt.Println(unsafe.Alignof(w2))fmt.Println(reflect.TypeOf(w).Elem().Align())   

Results

888

Under a 64-bit machine, the alignment value of the pointer object is 8, because the pointer type is UINTPTR. The value type of the struct is a 8bytes alignment value because the field is aligned first, the maximum alignment value of the field is 8bytes, so the alignment value of the struct value type is also 8.

Change the structure and verify that:

type W struct {    a byte    b int32    c int32}var w Wfmt.Println(unsafe.Alignof(w)) //4

Comprehensive example

type T struct {    t1 byte    t2 int32    t3 int64    t4 string    t5 bool}fmt.Println("----------unsafe.Pointer---------")t := &T{1, 2, 3, "this is a example", true}ptr := unsafe.Pointer(t)t1 := (*byte)(ptr)fmt.Println(*t1)t2 := (*int32)(unsafe.Pointer(uintptr(ptr) + unsafe.Offsetof(t.t2)))*t2 = 99fmt.Println(t)t3 := (*int64)(unsafe.Pointer(uintptr(ptr) + unsafe.Offsetof(t.t3)))fmt.Println(*t3)*t3 = 123fmt.Println(t)

Results

----------unsafe.Pointer---------1&{1 99 3 this is a example true}3&{1 99 123 this is a example true}

With the help of unsafe. Pointer, we implemented pointer-offset operations like the C language. As you can see, this insecure operation allows us to directly access the non-exposed members of the struct anywhere, as long as we can get the address of the struct variable.

Resources:

    1. https://blog.csdn.net/libing_thinking/article/details/49907815
    2. https://studygolang.com/articles/6903
    3. https://blog.csdn.net/hzwy23/article/details/60893765
    4. Https://www.cnblogs.com/golove/p/5909968.html
    5. https://studygolang.com/articles/1414

Author: ycyoes
Links: https://www.jianshu.com/p/c85fc3e31249
Source: Pinterest
The copyright of the book is owned by the author, and any form of reprint should be contacted by the author for authorization and attribution.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.