Commit 82f96cf9 authored by AlexStocks's avatar AlexStocks

Add: slice <--> string

parent 1a40fd3a
// Copyright 2016 ~ 2018 AlexStocks(https://github.com/AlexStocks).
// All rights reserved. Use of this source code is
// governed by Apache License 2.0.
package gxstrings
import (
"reflect"
)
func IsNil(i interface{}) bool {
if i == nil {
return true
}
if reflect.ValueOf(i).IsNil() {
return true
}
return false
}
// Copyright 2016 ~ 2018 AlexStocks(https://github.com/AlexStocks).
// All rights reserved. Use of this source code is
// governed by Apache License 2.0.
// http://blog.csdn.net/siddontang/article/details/23541587
// reflect.StringHeader和reflect.SliceHeader的结构体只相差末尾一个字段(cap)
// vitess代码,一种很hack的做法,string和slice的转换只需要拷贝底层的指针,而不是内存拷贝。
package gxstrings
import (
"reflect"
"unsafe"
)
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
}
// returns &s[0], which is not allowed in go
func StringPointer(s string) unsafe.Pointer {
p := (*reflect.StringHeader)(unsafe.Pointer(&s))
return unsafe.Pointer(p.Data)
}
// returns &b[0], which is not allowed in go
func BytePointer(b []byte) unsafe.Pointer {
p := (*reflect.SliceHeader)(unsafe.Pointer(&b))
return unsafe.Pointer(p.Data)
}
package gxstrings
import (
"testing"
)
// go test -v slice_test.go slice.go
// slice转string之后,如果slice的值有变化,string也会跟着改变
func TestString(t *testing.T) {
b := []byte("hello world")
a := String(b)
b[0] = 'a'
println(a) //output aello world
}
func TestSlice(t *testing.T) {
// 编译器会把 "hello, world" 这个字符串常量的字节数组分配在没有写权限的 memory segment
a := "hello world"
b := Slice(a)
// !!! 上面这个崩溃在defer里面是recover不回来的,真的就崩溃了,原因可能就跟c的非法内存访问一样,os不跟你玩了
// b[0] = 'a' //这里就等着崩溃吧
//但是可以这样,因为go又重新给b分配了内存
b = append(b, "hello world"...)
println(String(b)) // output: hello worldhello world
}
func TestSlice2(t *testing.T) {
// 你可以动态生成一个字符串,使其分配在可写的区域,比如 gc heap,那么就不会崩溃了。
a := string([]byte("hello world"))
b := Slice(a)
b = append(b, "hello world"...)
println(String(b)) // output: hello worldhello world
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment