github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/11_reflect/unsafedemo.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/qiuhoude/go-web/prepare/11_reflect/rtype"
     6  	"reflect"
     7  	"unsafe"
     8  )
     9  
    10  func main() {
    11  	//sizeof()
    12  	//alignof()
    13  	//offsetof()
    14  	//offsetof2()
    15  	//unsafePoint()
    16  	s := make([]int, 9, 20)
    17  	var Len = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + unsafe.Sizeof(int(0))))
    18  	fmt.Println(Len, len(s)) // 9 9
    19  
    20  	var Cap = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + unsafe.Sizeof(int(0)) + unsafe.Sizeof(int(0))))
    21  	fmt.Println(Cap, cap(s)) // 20 20
    22  }
    23  
    24  func unsafePoint() {
    25  	i := 10
    26  	ip := &i
    27  	// 指针转换之间强转不能进行强转,只能通过 unsafe.Pointer
    28  	/*
    29  		1. 任何指针都可以转换为unsafe.Pointer
    30  		2. unsafe.Pointer可以转换为任何指针
    31  		3. uintptr可以转换为unsafe.Pointer
    32  		4. unsafe.Pointer可以转换为uintptr
    33  	*/
    34  	var fp *float64 = (*float64)(unsafe.Pointer(ip))
    35  	*fp = *fp * 3
    36  	fmt.Println(i)
    37  
    38  	u := new(rtype.User)
    39  	//u :=&rtype.User{Age:ip}
    40  	fmt.Println(*u)
    41  	u.Age = ip
    42  
    43  	pName := (*string)(unsafe.Pointer(u)) // 将结构体指针 强转成string指针, 可以强转的原因是, user首字段是string类型
    44  	*pName = "qiu"
    45  
    46  	pLove := (*interface{})(unsafe.Pointer(uintptr(unsafe.Pointer(u)) + unsafe.Offsetof(u.Love)))
    47  	*pLove = "name"
    48  
    49  	// 操作lv私有字段
    50  	plv := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(u)) + unsafe.Offsetof(u.Love) + uintptr(unsafe.Sizeof(u.Love))))
    51  	*plv = 14
    52  
    53  	fmt.Println(u)
    54  	(*u).Print("pName--")
    55  
    56  }
    57  
    58  // Sizeof 类型大小
    59  func sizeof() {
    60  	fmt.Println("---------------------Sizeof---------------------")
    61  	fmt.Println("bool ", unsafe.Sizeof(true))
    62  	fmt.Println("int8 ", unsafe.Sizeof(int8(0)))
    63  	fmt.Println("int16 ", unsafe.Sizeof(int16(10)))
    64  	fmt.Println("int32 ", unsafe.Sizeof(int32(10000000)))
    65  	fmt.Println("int64 ", unsafe.Sizeof(int64(10000000000000)))
    66  	fmt.Println("int ", unsafe.Sizeof(int(10000000000000000)))
    67  }
    68  
    69  //Alignof 对齐值, 对齐值一般是2^n,最大不会超过8
    70  func alignof() {
    71  	var b bool
    72  	var i8 int8
    73  	var i16 int16
    74  	var i64 int64
    75  
    76  	var f32 float32
    77  
    78  	var s string
    79  
    80  	var m map[string]string
    81  
    82  	var p *int32
    83  	fmt.Println("---------------------Alignof---------------------")
    84  	fmt.Println("bool ", unsafe.Alignof(b))
    85  	fmt.Println("int8 ", unsafe.Alignof(i8))
    86  	fmt.Println("int16 ", unsafe.Alignof(i16))
    87  	fmt.Println("int64 ", unsafe.Alignof(i64))
    88  	fmt.Println("float32 ", unsafe.Alignof(f32))
    89  	fmt.Println("string ", unsafe.Alignof(s))
    90  	fmt.Println("map[string]string ", unsafe.Alignof(m))
    91  	fmt.Println("*int32 ", unsafe.Alignof(p))
    92  }
    93  
    94  //Offsetof  函数只适用于struct结构体中的字段相对于结构体的内存位置偏移量。结构体的第一个字段的偏移量都是0
    95  func offsetof() {
    96  	var u1 rtype.User1
    97  	fmt.Println("---------------------Offsetof---------------------")
    98  	fmt.Println("byte ", unsafe.Offsetof(u1.B))
    99  	// unsafe.Offsetof(u1.B) 与 reflect.TypeOf(u1).FieldByName("B").Offset等价
   100  	if field, ok := reflect.TypeOf(u1).FieldByName("B"); ok {
   101  		fmt.Println("reflect byte ", field.Offset)
   102  	}
   103  	fmt.Println("int32 ", unsafe.Offsetof(u1.I32))
   104  	fmt.Println("int64 ", unsafe.Offsetof(u1.I64))
   105  	fmt.Println("u1 sizeof ", unsafe.Sizeof(u1)) //排方式不同对齐方式也不同
   106  
   107  }
   108  
   109  func offsetof2() {
   110  	var u1 rtype.User
   111  	u1.Love = true
   112  	u1.Print("prifix")
   113  	fmt.Println("---------------------Offsetof2---------------------")
   114  	fmt.Println("Name ", unsafe.Offsetof(u1.Name))
   115  	fmt.Println("Age ", unsafe.Offsetof(u1.Age))
   116  	fmt.Println("Love ", unsafe.Offsetof(u1.Love))
   117  	fmt.Println("size Love ", unsafe.Sizeof(u1.Love))
   118  	fmt.Println("u1 sizeof ", unsafe.Sizeof(u1))
   119  
   120  }