go中string和slice no-copy转换

原创 2014年04月12日 17:10:23

在go里面,string和slice的互换是需要进行内存拷贝的,虽然在底层,它们都只是用 pointer + len来表示的一段内存。

通常,我们不会在意string和slice的转换带来的内存拷贝性能问题,但是总有些地方需要关注的,刚好在看vitess代码的时候,发现了一种很hack的做法,string和slice的转换只需要拷贝底层的指针,而不是内存拷贝。当然这样做的风险各位就要好好担当了:

func String(b []byte) (s string) {
    pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
    pstring.Data = pbytes.Data
    pstring.Len = pbytes.Len
    return
}

func Slice(s string) (b []byte) {
    pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
    pbytes.Data = pstring.Data
    pbytes.Len = pstring.Len
    pbytes.Cap = pstring.Len
    return
}

在我的测试例子中,slice转string之后,如果slice的值有变化,string也会跟着改变,如下:

b := []byte("hello world")

a := String(b)

b[0] = 'a'

println(a)  //output  aello world

但是string转slice之后,就不能更改slice了,如下:

a := "hello world"

b := Slice(a)

b[0] = 'a'  //这里就等着崩溃吧

//但是可以这样,因为go又重新给b分配了内存
b = append(b, "hello world"…)

上面为什么会崩溃我猜想可能是string是immutable的,可能对应的内存地址也是不允许改动的。

另外,上面这个崩溃在defer里面是recover不回来的,真的就崩溃了,原因可能就跟c的非法内存访问一样,os不跟你玩了。

【Go语言】基本类型排序和 slice 排序

Go 是通过 sort 包提供排序和搜索,因为 Go 暂时不支持泛型(将来也不好说支不支持),所以,Go 的 sort 和 search 使用起来跟类型是有关的,或是需要像 c 一样写比较函数等,稍微...
  • u010983881
  • u010983881
  • 2016年09月07日 16:43
  • 3363

go语言中json转成map结构

package main import (     "encoding/json"     "fmt" ) //把请求包定义成一个结构体 type Requestbody struct {     r...
  • zistxym
  • zistxym
  • 2015年02月05日 16:14
  • 14056

go语言的string和slice是值拷贝吗?

package main import "fmt" func main() { var str string = "12345" tmpstr := str fmt.Pri...
  • frank0712105003
  • frank0712105003
  • 2016年03月18日 12:06
  • 703

Go语言Slice操作.

1、基本用法: a = append(a, b...) 例如:list = appened(list,[]int{1,2,3,4}...) 可以用来合并两个列表. 不用这样...
  • fyxichen
  • fyxichen
  • 2015年06月24日 15:35
  • 973

【Go语言】基本类型排序和 slice 排序

Go 是通过 sort 包提供排序和搜索,因为 Go 暂时不支持泛型(将来也不好说支不支持),所以,Go 的 sort 和 search 使用起来跟类型是有关的,或是需要像 c 一样写比较函数等,稍微...
  • u010983881
  • u010983881
  • 2016年09月07日 16:43
  • 3363

[GoLang学习总结]Go语言中的Slice

Slice切片是对底层数组Array的封装,在内存中的存储本质就是数组,体现为连续的内存块,Go语言中的数组定义之后,长度就已经固定了,在使用过程中并不能改变其长度,而Slice就可以看做一个长度可变...
  • tiger435
  • tiger435
  • 2014年03月12日 18:04
  • 2936

go array和slice区别

来源http://www.2cto.com/kf/201401/274536.html
  • lmxmimihuhu
  • lmxmimihuhu
  • 2014年09月19日 22:21
  • 1571

Golang(Go语言)代码技巧之字符串(string)

改变字符串中的某些字符 str := "hello roc"bytes := []byte(str)bytes[1] = 'a'str = string(bytes) //str == "hal...
  • QQ245671051
  • QQ245671051
  • 2016年02月24日 21:32
  • 15199

go语言学习笔记之slice用法

一、slice的概念: Slices(切片)slice是概念上一个结构包含三个域:一个数组的指针、长度和容量。切片支持[]操作符来访问底层数组的元素。内置的len函数返回的切片长度。内置的的cap函...
  • wuwenxiang91322
  • wuwenxiang91322
  • 2013年06月10日 20:03
  • 13691

Go语言核心之美 3.2-slice切片

Slice是长度可变的元素序列(数组不可变),每个元素都有相同的类型。slice类型写作[]T,其中T代表slice中的元素类型;slice和数组写法很像,只是没有指定长度。 数组和slice之间的联...
  • abv123456789
  • abv123456789
  • 2016年03月23日 13:21
  • 4002
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:go中string和slice no-copy转换
举报原因:
原因补充:

(最多只允许输入30个字)