go 中byte与string的底层转换及问题
普通强转
用关键字进行强转,底层会发生拷贝,两个变量互不影响。
代码示例:
s:="012345"
b:=[]byte(s)
s1:=string(b)
fmt.Println(s1)
b[0]='9'
fmt.Println(s1)
=== RUN Test_强转
012345
012345
--- PASS: Test_强转 (0.00s)
PASS
运用底层编程强转
1 byte to string
go支持中文字符做为变量
func Test_运用底层编程byteToString(t *testing.T) {
var b = []byte{'1', '2', '3', '4'}
s := *(*string)(unsafe.Pointer(&b))
fmt.Println(s)
}
=== RUN Test_运用底层编程byteToString存在的问题
1234
--- PASS: Test_运用底层编程byteToString存在的问题 (0.00s)
PASS
存在问题
由于底层没有copy,导致字符串并不是常量。在常规理解中,字符串一经生成,便不会改变,经底层强转后字符串变得可以改变。虽然用底层强转效率变高,但是也产生了新问题。
func Test_运用底层编程byteToString存在的问题(t *testing.T) {
var b = []byte{'1', '2', '3', '4'}
s := *(*string)(unsafe.Pointer(&b))
fmt.Println(s)
b[0]='9'
fmt.Println(s)
}
=== RUN Test_运用底层编程byteToString存在的问题
1234
9234
--- PASS: Test_运用底层编程byteToString存在的问题 (0.00s)
PASS
2 string to byte
具体实现:
func Test_StringToByte(t *testing.T) {
var s ="1234"
strPtr := (*[2]uintptr)(unsafe.Pointer(&s))
res := [3]uintptr{strPtr[0], strPtr[1], strPtr[1]}
b := *(*[]byte)(unsafe.Pointer(&res))
fmt.Println(b)
}
=== RUN Test_StringToByte
[49 50 51 52]
--- PASS: Test_StringToByte (0.00s)
PASS
存在问题
由于 stirng类型是常量,所以会存储在程序的常量区,这里面的数据是不容改动的,否则程序会崩溃。但我们将字符串强转成byte后,byte与string共享内存,byte可以进行修改操作是合理合规的,于是绕过了编译器的检查执行了常量区内存修改。
func Test_StringToByte存在问题(t *testing.T) {
var s ="1234"
strPtr := (*[2]uintptr)(unsafe.Pointer(&s))
res := [3]uintptr{strPtr[0], strPtr[1], strPtr[1]}
b := *(*[]byte)(unsafe.Pointer(&res))
fmt.Println(b)
b[0]='9'
}
=== RUN Test_StringToByte存在问题
[49 50 51 52]
unexpected fault address 0x54a1d3
fatal error: fault
[signal 0xc0000005 code=0x1 addr=0x54a1d3 pc=0x4fe930]
goroutine 5 [running]:
runtime.throw(0x54a45a, 0x5)
C:/Go1.12.4/src/runtime/panic.go:617 +0x79 fp=0xc00009ff08 sp=0xc00009fed8 pc=0x42e479
runtime.sigpanic()
C:/Go1.12.4/src/runtime/signal_windows.go:236 +0x23c fp=0xc00009ff38 sp=0xc00009ff08 pc=0x4404cc
prcitf/go%e5%90%84%e7%a7%8d%e5%8f%98%e9%87%8f%e5%b8%b8%e9%87%8f%e7%b1%bb%e5%9e%8b%e5%9f%ba%e7%a1%80%e7%94%a8%e6%b3%95/string.Test_StringToByte存在问题(0xc000094100)
D:/GO/src/prcitf/go各种变量常量类型基础用法/string/强转_test.go:56 +0xb0 fp=0xc00009ffa8 sp=0xc00009ff38 pc=0x4fe930
testing.tRunner(0xc000094100, 0x554bb0)
C:/Go1.12.4/src/testing/testing.go:865 +0xc7 fp=0xc00009ffd0 sp=0xc00009ffa8 pc=0x4c27a7
runtime.goexit()
C:/Go1.12.4/src/runtime/asm_amd64.s:1337 +0x1 fp=0xc00009ffd8 sp=0xc00009ffd0 pc=0x459441
created by testing.(*T).Run
C:/Go1.12.4/src/testing/testing.go:916 +0x361
goroutine 1 [chan receive]:
testing.(*T).Run(0xc000094100, 0x550293, 0x1d, 0x554bb0, 0x472d01)
C:/Go1.12.4/src/testing/testing.go:917 +0x388
testing.runTests.func1(0xc000094000)
C:/Go1.12.4/src/testing/testing.go:1157 +0x7f
testing.tRunner(0xc000094000, 0xc00006be30)
C:/Go1.12.4/src/testing/testing.go:865 +0xc7
testing.runTests(0xc0000044a0, 0x646220, 0x5, 0x5, 0x0)
C:/Go1.12.4/src/testing/testing.go:1155 +0x2b0
testing.(*M).Run(0xc000088000, 0x0)
C:/Go1.12.4/src/testing/testing.go:1072 +0x169
main.main()
_testmain.go:50 +0x145
Process finished with exit code 1