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语言的string和slice是值拷贝吗?

package main import "fmt" func main() { var str string = "12345" tmpstr := str fmt.Pri...
  • frank0712105003
  • frank0712105003
  • 2016-03-18 12:06:24
  • 794

Golang黑科技之——string与[]byte转换

我们知道,相对于C语言,golang是类型安全的语言。但是安全的代价就是性能的妥协。 下面我们通过Golang中的“黑科技”来一窥Golang不想让我们看到的“秘密”——string的底层数据。 ...
  • vipally
  • vipally
  • 2016-10-27 00:09:19
  • 21591

golang 一行代码 把array/slice转成逗号分隔的字符串

strings.Replace(strings.Trim(fmt.Sprint(array_or_slice), "[]"), " ", ",&quo...
  • u010476094
  • u010476094
  • 2018-03-12 23:46:41
  • 221

Golang(Go语言)内置函数之copy用法

该函数主要是切片(slice)的拷贝,不支持数组 将第二个slice里的元素拷贝到第一个slice里,拷贝的长度为两个slice中长度较小的长度值 示例: s := []int{1,...
  • QQ245671051
  • QQ245671051
  • 2016-02-24 21:32:16
  • 8773

go string []byte相互转换

string 不能直接和byte数组转换 string可以和byte的切片转换 1,string 转为[]byte var str string = "test" var da...
  • a64180190
  • a64180190
  • 2017-08-01 14:45:01
  • 8976

Go语言string与[]byte类型转化避免拷贝

在Go语言中string类型与[]byte强制类型转化的是后会发生内存拷贝,这是由于这两种类型的特性所决定的; string类型是不允许修改内容,[]byte是可以修改的。 下面提供两个函数使用...
  • gdutliuyun827
  • gdutliuyun827
  • 2016-11-30 15:39:36
  • 5195

Go语言slice的那些坑

Go语言Google开发的适用于多核编程的语言。我感觉它像是C语言的现代版本,简单,并发支持友好,部署轻松。GO语言中保留关键字就只有25个,这也足以说明它的学习成本并不高。 然而,Go语言里面sli...
  • zhanchenxing
  • zhanchenxing
  • 2015-12-03 10:44:51
  • 471

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

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

go中string和slice no-copy转换

在go里面,string和slice的互换是需要进行内存拷贝的,虽然在底层,它们都只是用 pointer + len来表示的一段内存。 通常,我们不会在意string和slice的转换带来的内存...
  • siddontang
  • siddontang
  • 2014-04-12 17:10:23
  • 5130

golang里如何将一个struct指针转换成slice

废话不说了,直接上代码 package main import "unsafe" import "fmt" func abc() { type T struct { a int b i...
  • HopingWhite
  • HopingWhite
  • 2013-03-12 11:18:04
  • 4363
收藏助手
不良信息举报
您举报文章:go中string和slice no-copy转换
举报原因:
原因补充:

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