Learn and use unsafe package

Go language pack presentation and use of unsafe

unsafe Introduction

type ArbitraryType int
type Pointer *ArbitraryType
func Sizeof(x ArbitraryType) uintptr
func Offsetof(x ArbitraryType) uintptr
func Alignof(x ArbitraryType) uintptr

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

unsafe library allows golang can operate as the computer's memory like a C language, but this is not recommended for use golang can not try to do, just as expressed by its name, it bypasses the security principles golang of memory, it is unsafe easily make your program appear baffling, is not conducive to expansion and maintenance procedures.

First a brief introduction Golang pointer

  1. * Type : Normal Pointer for delivering object address, pointer arithmetic can not be performed.
  2. unsafe.Pointer : generic pointer type, for converting different types of pointers, pointer arithmetic can not be performed.
  3. uintptr : a pointer arithmetic, GC when the pointer is not the uintptr, uintptr not holding the object. uintptr types of targets will be recycled .

unsafe.Pointer conversion and may be an ordinary pointer.

unsafe.Pointer conversion and can be uintptr.

That unsafe.Pointer is a bridge that allows any type of pointer realize the transformation, but also any type of pointer can be converted to a pointer operation uintptr count.

uintptr of this type, in golang, the byte length is consistent with the int. Pointer arithmetic usually can not participate, for example, you want to add an offset to the address of a pointer, Pointer can not do this operation, then who will? Uintptr type is, as long as the type of the Pointer converted into uintptr type, done after addition and subtraction, converted into Pointer, the * operation, the value, the modified value free.

About two 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 int

type Pointer *ArbitraryType

ArbitraryType is an alias for int, in Go to ArbitraryType given special significance. Go represents an expression of any type.

Pointer is a pointer alias int type, Pointer types can, be understood as any type of parent pointers in Go.

The following is the official document usage scenarios for the introduction Pointer

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.

golang length int type pointer type length, the number of bytes occupied in memory is the same.

ArbitraryType type may be a pointer variable. So, do not Sike behind the int type

About three functions

// Sizeof takes an expression x of any type and returns the size in bytes
// of a hypothetical variable v as if v was declared via var v = x.
// The size does not include any memory possibly referenced by x.
// For instance, if x is a slice,  Sizeof returns the size of the slice
// descriptor, not the size of the memory referenced by the slice.
**func Sizeof(x ArbitraryType) uintptr**

// Offsetof returns the offset within the struct of the field represented by x,
// which must be of the form structValue.field. In other words, it returns the
// number of bytes between the start of the struct and the start of the field.
**func Offsetof(x ArbitraryType) uintptr**

// Alignof takes an expression x of any type and returns the required alignment
// of a hypothetical variable v as if v was declared via var v = x.
// It is the largest value m such that the address of v is 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) will return the required alignment
// of a field of that type within a struct. This case is the same as the
// value returned by reflect.TypeOf(s.f).FieldAlign().
**func Alignof(x ArbitraryType) uintptr**

The analysis revealed that the parameters of these three functions are ArbitraryType type, it is to accept any type of variable.

  1. Return variable number of bytes are aligned Alignof
  2. Offsetof return variable specified offset properties, though this function is received variables of any type, but there is a prerequisite, if the variable is a struct type, and not directly to the struct type variable as parameters, the only this property type struct variable as a parameter.
  3. Returns the number of bytes occupied Sizeof variables in memory, remember, if a slice, the slice does not return the actual occupation length in memory .

Examples

Sizeof

is the value returned by the function unsafe.Sizeof uintptr type (expression, i.e., the size value):

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

results:

uintptr
8

unsafe.Sizeof accepts any type of value (expression), and returns the number of bytes occupied, float64 in the example above is the size of 8bytes.

If the incoming number of objects a pointer type of return it?

type W struct {
    a byte
    b int32
    c int64
}

var w *W
fmt.Println(unsafe.Sizeof(w)) //4 or 8

In general, it may be 4 or 8, because w is a pointer type uintptr, and uintptr is platform, at the system size is 4bytes 32, 64 is 8bytes in the system.

To obtain the value of the type of size, the need for a pointer variable values:

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

Align

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

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

Are 1,4,8, because alignment type int32 4bytes value, must be a multiple of 4, it is to be filled with a byte 3 bytes. After the filling, and the size of both of 8bytes, int64 alignment value is 8bytes, does not require filling, so the size of the structure to obtain a unsafe.Sizeof is 4 + 4 + 8 = 16.

Reflection packet alignment method

Package has reflection certain methods available for calculating alignment values:

unsafe.Alignof (w) is equivalent to reflect.TypeOf (w) .Align.

unsafe.Alignof(w.i)等价于reflect.Typeof(w.i).FieldAlign()。

Structure alignment value

If we calculate the value of the structure is aligned instead of a field or a primitive type, then the value is how much?

type W struct {
    a byte
    b int32
    c int64
}

var w *W
var w2 W

fmt.Println(unsafe.Alignof(w))
fmt.Println(unsafe.Alignof(w2))
fmt.Println(reflect.TypeOf(w).Elem().Align())  

results:

8
8
8

64-bit machine, the alignment value of the pointer object is 8, because the pointer type uintptr. And the value of the type of structure is aligned 8bytes value, which will carry out because of the alignment field, the field value is the maximum alignment 8bytes, and therefore the value of the structure type of alignment is 8 values.

Restructuring, verify:

type W struct {
    a byte
    b int32
    c int32
}
var w W
fmt.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 = 99
fmt.Println(t)
t3 := (*int64)(unsafe.Pointer(uintptr(ptr) + unsafe.Offsetof(t.t3)))
fmt.Println(*t3)
*t3 = 123
fmt.Println(t)

results:

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

By means unsafe.Pointer, we implemented as C language pointer offset operation. It can be seen that this unsafe operation allows members of the public we can not access anywhere in the structure directly, as long as can get this structure variable address.





Guess you like

Origin www.cnblogs.com/hualou/p/12070155.html