GOLANG中string([]byte)生成的string是重新分配内存之后吧[]byte的东西转换成string填进去,然后新的string不可变。

因为GO中的string类型是只读不可改变的类型,实际中我们经常会遇到改变一个字符串中的某几个字符,如果通过go中不可变的string类型来做比较麻烦,可以让原数据是[]byte类型,在改变其中几个字符的时候直接通过下标修改[]byte里面的内容,在需要string的时候通过string([]byte)生成,这有可能提高效率,还不会产生太多的子字符串浪费内存,同时导致GC任务加重。这个操作需要注意的是,string([]byte)新生成的string是重新开辟了一块内存来保存(s1 := string(byte1)),所以在强制转换之后,如果修改原来[]byte的某几个字符(byte1[1] = 'x'),这强制转换之后的string不会跟随改变(s1[1]还是原来的字符,而不是后来改变的'x')。看如下分析过程。

package main

//仿造string的底层结构
type FackeString struct {
	ptr	*byte
	len  int
}

//仿造[]byte的底层结构
type FackeByteSlice struct {
	ptr	*byte
	len  int
	cap int
}

func main()  {
	var tmp FackeString
	var byte1 = []byte("hai")

	s1 := string(byte1) 
   //s1是通过强制转换[]byte而来,s1底层的dataPtr与[]byte底层的ptr指向不同的内存地址,
   
   //下面是证明:
	
    //利用unsafe包,强制吧byte1的起始地址看成FackeByteSlice的起始地址,并赋值给tmpByte
	tmpByte := *((*FackeByteSlice)(unsafe.Pointer(&byte1)))
    //打印byte1的一些信息:
	fmt.Printf("size of bytes :%d, len(byte1):%d, cap(byte1):%d,&byte1[0]:%p\n",
		unsafe.Sizeof(byte1), len(byte1), cap(byte1), &byte1[0])

    //通过tmpByte查看byte1里面的东西:
	fmt.Printf("tmpByte-> len:%d, cap:%d, ptr:%p\n",
		tmpByte.len, tmpByte.cap, tmpByte.ptr )
    /*这里输出:
    size of bytes :24, len(byte1):3, cap(byte1):8, &byte1[0]:0xc04205a208
    tmpByte-> len:3, cap:8, ptr:0xc04205a208

    */

    //强制把s1的起始地址看成FackeString 的起始地址,并赋值给tmp 变量
	tmp = *((*FackeString)(unsafe.Pointer(&s1)))
    //通过tmp查看s1里面的东西
	fmt.Printf("len of string :%d, addr of data:%p, len of s1:%d\n",
		len(s1), tmp.ptr, tmp.len)
    /*这里输出:
    len of string :3, addr of data:0xc04205a220, len of s1:3
    这里tmp.ptr != tmpByte.ptr

    */
    //进一步的证明
    byte1[1] = 'o'  //修改byte[1]
	fmt.Printf("s1:%s, data addr: %x  \n",
		s1, *((*uintptr)(unsafe.Pointer(&s1))) )
    //输出:s1:hai, data addr: c04205a220 
    //修改了byte[1]之后,s1还是原来的hai。
}

浪费时间在这里做这些,而不去泡妞,就为了得到开头的那个结论,可以回头再看看,也不知道值不值得呢~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值