go 内存二进制数据操作
go 内存二进制数据直接操作
以数字类型为例
int(linux/macos 为int32,windows 为int64). 如果不清楚可以使用unsafe.Sizeof函数来查看(函数出来的值*8就是int位数)
若不使用内存二进制数据操作,你需要在每次获取数字内容时调用binary.BigEndian/LittleEndian的方法来计算出数字大小。而具体是大端还是小端计算由系统决定.(win 小端,linux/macos 大端)
import (
"binary"
"crypto/rand"
"fmt"
)
func main(){
var buff []byte=make([]byte,4)
//创建一个随机数进
_,err:=rand.Reader.Read(buff)
if err!=nil{
panic("random number failed "+err.Error())
}
//获取这个随机数的值
fmt.Println(binary.BigEndian.Uint32(buff))
}
直接操纵内存获取
import (
"unsafe"
"crypto/rand"
)
type Pointer[T any] struct{
T *T
buff []byte
}
func NewPointer[T any]()*Pointer[T]{
var t T
var ans = &Pointer[T]{buff:make([]byte,unsafe.Sizeof(t))}//获取类型占用内存字节数
ans.T=(*T)(unsafe.Pointer(&ans.buff[0]))//将指针关联过去
return ans
}
func (s *Pointer[T])Bytes()[]byte{
return s.buff
}
func main(){
ptr:=NewPointer[int]()
_,err:=rand.Reader.Read(ptr.Bytes())
if err!=nil{
panic("random number failed "+err.Error())
}
fmt.Println(*ptr.T)//就像读取正常指针一样读取
}
多种类型复用同一块内存
//以混合两种类型作为示范
type Union[T1 any,T2 any] struct{
T1 *T1
T2 *T2
b []byte
}
func NewUnion[T1 any,T2 any]()*Union[T1,T2]{
var (
t1 T1
t2 T2
)
maxsize:=unsafe.Sizeof(t1)
t2size:=unsafe.Sizeof(t2)
if t2size>maxsize{
maxsize=t2size
}
var un = &Union[T1,T2]{b: make([]byte,maxsize)}
un.T1=(*T1)(unsafe.Pointer(&un.b[0]))
un.T2=(*T2)(unsafe.Pointer(&un.b[0]))
return un
}
func (s *Union[T1,T2])Bytes()[]byte{
return s.b
}
func main(){
un:=NewUnion[int,float64]()
*un.T1 = 23//存储23 int值
*un.T2 = 178.5//需要作为float类型是设置为float类型
}
2024.03.20
获取对象底层原始二进制数组.
unsafe.Slice[T any](t *T,lenght int)
这是这个函数的构造,会返回一个长度为length 的T数组,这里将其转换为byte指针传入,类型长度通过unsafe.Sizeof计算出,两波配合就能拿到该类型的底层数组。
func GetRawBytes[T any](t *T) []byte {
return unsafe.Slice((*byte)(unsafe.Pointer(t)), unsafe.Sizeof(*t))
}