Go类型转换内存拷贝优化以及三元符的实现

Go类型转换内存拷贝优化以及三元符的实现

1.函数实现三元符

注意此方法 参数会执行一遍 且返回需要类型推断

func TriGraph(condition bool, a interface{}, b interface{}) interface{} {
	if condition {
		return a
	} else {
		return b
	}
}
// 使用
TriGraph(1 > 2, 1, 2) // 返回2
// 若需要使用指定类型方法 需要 接口推断 interface.(需要的类型);switch interface.(type)

2.没有内存拷贝的类型转换

强制类型转换都会导致内存拷贝

  • string的本质:reflect.StringHeader{};StringHeader是字符串的运行时表示形式
  • slice的本质:reflect.SliceHeader{};SliceHeader是切片的运行时表示
  • go指针的本质:unsafe.Pointer{}、uintptr{}
type StringHeader struct {  // 字符串的底层结构
 Data uintptr
 Len  int
}
type SliceHeader struct {  // 切片的底层结构
 Data uintptr
 Len  int
 Cap  int
}
1.unsafe.Pointer(&a) 生成unsafe.Pointer指针
2.(*reflect.StringHeader)(unsafe.Pointer(&a)) unsafe.Pointer指针转成底层StringHeader结构的指针
3.(*[]byte)(unsafe.Pointer(&b)) 可以把b底层结构体转成byte的切片的指针
4.再通过 *转为指针指向的内容  之后获取时 通过长度遍历 每个元素的长度由指针类型确定 如[]byte切片 指针每个元素遍历1个字节

a :="aaaa"
b := *(*reflect.StringHeader)(unsafe.Pointer(&a))
c := *(*[]byte)(unsafe.Pointer(&b))  
fmt.Printf("%v",c)

string和[]byte直接类型转换;注意字符串转换后的结果只可读不能修改

func byteToString(b []byte) string { 
	return *(*string)(unsafe.Pointer(&b))
}
func stringToByte(str string) []byte { // 直接创建的字符串转byte数组 不可修改 且数组长度len与字符串的字节长度一致 切片cap长度没有界限不可用 len:6 cap:824633761944
	return *(*[]byte)(unsafe.Pointer(&str))
}
// 直接转换 可以互换
a := "中文test"
bytes := *(*[]byte)(unsafe.Pointer(&a))
// bytes[0] = 11 修改会报错 只读 unexpected fault address xx 因为原数组是字符串的底层数组 字符串不可修改
a = *(*string)(unsafe.Pointer(&bytes))
// 修改限制测试
b := []byte{97}
b = stringToByte(byteToString(b))
b[0] = 99 // 此处可以修改 数组指向程序创建的byte数组 可修改
str := "ztest1"
b = stringToByte(str)
b[0] = 99  // 此处不可修改 数组指向字符串的底层数组 只可读

结构体和[]byte互相转换,用于优化encoding/binary;结构体转byte数组相当于把结构体指针首地址赋值给切片Data

type Test struct {
    A int
    B int
}

// 获取结构体占用的字节大小 用于len和cap的赋值
var sizeOfStruct = int(unsafe.Sizeof(Test{}))

// 填充[]byte的数据结构 相当于序列化
// 结构体的数据指针int类型
func StructToBytes(t *Test) []byte {
    var x reflect.SliceHeader // 切片的底层结构
    x.Len, x.Cap = sizeOfStruct, sizeOfStruct
    x.Data = uintptr(unsafe.Pointer(t))
    return *(*[]byte)(unsafe.Pointer(&x))
}

// 相当于反序列化
// unsafe.Pointer(&b):取[]byte首地址
// (*reflect.SliceHeader)(unsafe.Pointer(&b)) : 强制转换其为reflect.SliceHeader指针
// (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data : 将slice的数据指针取出来
// unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data) : 将uint指针转成任意指针
// (*Test)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&b)).Data)):成功转换
func BytesToStruct(b []byte) *Test {
    return (*Test)(unsafe.Pointer(
                (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data))
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值