What is an unsecured package?

Description of official documents

Package unsafe contains operations that step around the type safety of Go programs. Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.

Insecure packages contain operations that bypass the go language type safety. Introducing insecure packages may be non-portable and may not be protected by the GO Version1 consistency guidelines

Type safety

In GO, each variable has its own type that can be converted to another type before being assigned to other variables:

Var I int8 = -1 // -1 Binary: 11111111 var j = int16(I) // -1 binary: 11111111 11111111 println(I, j) // -1 -1Copy the code

The unsafe package lets you directly retrieve the value of this variable’s memory, which holds binary values on the address. That way we can bypass the type constraint.

Continue with the above code:

Var k uint8 = *(*uint8)(uint.pointer (& I)) println(k) // 255 because the 11111111 binary is used to represent the current value in the memory addressCopy the code

GO 1 Consistency guidelines

Packages that import unsafe may depend on internal properties of the Go implementation. We reserve the right to make changes to the implementation that may break such programs.

It is important to note that there may be minor changes between the two versions that can cause problems, but some of the standard libraries will be used in the GO standard library

Use unsafe in reflection packages

Reflection packets are internal data based on an empty interface. To be able to read the data, go knowledge transforms our variables into the empty interface, and then reads them by mapping a structure that matches the internal display of the empty interface, using memory for its pointer address

// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
func ValueOf(i interface{}) Value {
	if i == nil {
		return Value{}
	}

	// TODO: Maybe allow contents of a Value to live on the stack.
	// For now we make the contents always escape to the heap. It
	// makes life easier in a few places (see chanrecv/mapassign
	// comment below).
	escapes(i)

	return unpackEface(i)
}



// unpackEface converts the empty interface i to a Value.
func unpackEface(i interface{}) Value {
	e := (*emptyInterface)(unsafe.Pointer(&i))
	// NOTE: don't read e.word until we know whether it is really a pointer or not.
	t := e.typ
	if t == nil {
		return Value{}
	}
	f := flag(t.Kind())
	if ifaceIndir(t) {
		f |= flagIndir
	}
	return Value{t, e.word, f}
}
Copy the code

The e here contains all of our information, including the type, whether the value is leakable or not. Reflection also uses the unsafe package to change the value of reflection variables by directly modifying the address of memory.

insyncPackage use

In the sync package, pools are shared by all goroutines/ Porcessors through the unbroadening part. All goroutines can be accessed directly through the unbroadening package:

func indexLocal(l unsafe.Pointer, i int) *poolLocal {
   lp := unsafe.Pointer(uintptr(l) + uintptr(i)*unsafe.Sizeof(poolLocal{}))
   return (*poolLocal)(lp)
}
Copy the code

Where L is the memory segment and I is the number of processors, the indexLocal method reads the memory segment — which contains x(number of processors) of the poolLocal structure — as an offset from the relevant index that it reads. Storing a single ruling to the entire memory fast is a very lightweight way to implement shared pools.

Used in the Runtime package

Go uses the Unsafe package in the Runtime environment because it can perform operations on memory, such as stack allocation or freeing stack memory. A stack is represented by two boundaries in its structure:

type stack struct {
   lo uintptr
   hi uintptr
}
Copy the code

The unsafe package helps to implement operations

// stackfree frees an n byte stack allocation at stk. // // stackfree must run on the system stack because it uses per-P  // resources and must not split the stack. // //go:systemstack func stackfree(stk stack) { gp := getg() v := unsafe.Pointer(stk.lo) n := stk.hi - stk.lo if n&(n-1) ! = 0 { throw("stack not a power of 2") } if stk.lo+n < stk.hi { throw("bad stack size") } if stackDebug >= 1 { println("stackfree", v, n) memclrNoHeapPointers(v, n) // for testing, clobber stack data } if debug.efence ! = 0 || stackFromSystem ! = 0 { if debug.efence ! = 0 || stackFaultOnFree ! = 0 { sysFault(v, n) } else { sysFree(v, n, &memstats.stacks_sys) } return } if msanenabled { msanfree(v, n) } if n < _FixedStack<<_NumStackOrders && n < _StackCacheSize { order := uint8(0) n2 := n for n2 > _FixedStack { order++ n2 >>= 1 } x := gclinkptr(v) if stackNoCache ! = 0 || gp.m.p == 0 || gp.m.preemptoff ! = "" { lock(&stackpool[order].item.mu) stackpoolfree(x, order) unlock(&stackpool[order].item.mu) } else { c := gp.m.p.ptr().mcache if c.stackcache[order].size >= _StackCacheSize { stackcacherelease(c, order) } x.ptr().next = c.stackcache[order].list c.stackcache[order].list = x c.stackcache[order].size += n } } else { s  := spanOfUnchecked(uintptr(v)) if s.state.get() ! = mSpanManual { println(hex(s.base()), v) throw("bad span state") } if gcphase == _GCoff { // Free the stack immediately if we're // sweeping. osStackFree(s) mheap_.freeManual(s, spanAllocStack) } else { // If the GC is running, we can't return a // stack span to the heap because it could be // reused as a heap span, and this state // change would race with GC. Add it to the // large stack cache instead. log2npage := stacklog2(s.npages) lock(&stackLarge.lock) stackLarge.free[log2npage].insert(s) unlock(&stackLarge.lock) } } }Copy the code

As a developer

If two structure types have the same internal structure, they can be converted using an unsafe pointer.

type A struct { A int8 B string C float32 } type B struct { D int8 E string F float32 } a := A{A: 1, B: "Hello world", C: 5.0} / / b: = b / / can't convert b: (a) = * (*) b (unsafe. The Pointer (&) a) FMT) Printf (" % v ", b) / / {5} 1 hello worldCopy the code

The unsafe operation is for memory addresses. If the unsafe operation is an unsafe operation, the memory cannot be allocated