struct和byte类型转换

struct和byte类型转换

import (
  "fmt"
  "unsafe"
)
type TestStructTobytes struct {
  data int64
}
type SliceMock struct {
  addr uintptr
  len int
  cap int
}

func main() {

  var testStruct = &TestStructTobytes{100}
  Len := unsafe.Sizeof(*testStruct)
  testBytes := &SliceMock{
    addr: uintptr(unsafe.Pointer(testStruct)),
    cap: int(Len),
    len: int(Len),
  }
  data := *(*[]byte)(unsafe.Pointer(testBytes))
  fmt.Println("[]byte is : ", data)
}

运行结果:

[]byte is : [100 0 0 0 0 0 0 0]

因为[]byte底层的数据结构为:

?

struct {
addr uintptr
len int
cap int
}

其中addr为数值的地址,len为当地数值的长度,cap为数值的容量。

转换的时候,需要定义一个和[]byte底层结构一致的struct(如例子中的SliceMock),然后把结构体的地址赋给addr,结构体的大小赋给len和cap。最后将其转换为[]byte类型。

2、将[]byte转换为struct,转换方法如下:

?

import (
  "fmt"
  "unsafe"
)
type TestStructTobytes struct {
  data int64
}
type SliceMock struct {
  addr uintptr
  len int
  cap int
}

func main() {

  var testStruct = &TestStructTobytes{100}
  Len := unsafe.Sizeof(*testStruct)
  testBytes := &SliceMock{
    addr: uintptr(unsafe.Pointer(testStruct)),
    cap: int(Len),
    len: int(Len),
  }
  data := *(*[]byte)(unsafe.Pointer(testBytes))
  fmt.Println("[]byte is : ", data)
  var ptestStruct *TestStructTobytes = *(**TestStructTobytes)(unsafe.Pointer(&data))
  fmt.Println("ptestStruct.data is : ", ptestStruct.data)
}

运行结果:

[]byte is : [100 0 0 0 0 0 0 0]
ptestStruct.data is : 100

从上面的例子中将[]byte转换为struct的代码片段为:

?

var ptestStruct *TestStructTobytes = *(**TestStructTobytes)(unsafe.Pointer(&data))

分析:

由于在golang中编译器不将[]byte视为指针,所以要使用其地址进行转换,由于[]byte底层存放的是指向数据的地址。用[]byte的地址就需要使用双层指针转换,然后再指向其内容,得出来的就是转换对应struct的指针了。



来自为知笔记(Wiz)

上一篇:并发编程之Unsafe魔术类的魔术


下一篇:Java基础之CAS深入解析