相對(duì)于C語言,golang是類型安全的語言。但是安全的代價(jià)就是性能的妥協(xié)。
下面我們通過Golang中的“黑科技”來一窺Golang不想讓我們看到的“秘密”——string的底層數(shù)據(jù)。
通過reflect包,我們可以知道,在Golang底層,string和slice其實(shí)都是struct:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
其中Data是一個(gè)指針,指向?qū)嶋H的數(shù)據(jù)地址,Len表示數(shù)據(jù)長度。
但是,在string和[]byte轉(zhuǎn)換過程中,Golang究竟悄悄幫我們做了什么,來達(dá)到安全的目的?
在Golang語言規(guī)范里面,string數(shù)據(jù)是禁止修改的,試圖通過&s[0], &b[0]取得string和slice數(shù)據(jù)指針地址也是不能通過編譯的。
下面,我們就通過Golang的“黑科技”來一窺Golang背后的“秘密”。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
以上4個(gè)函數(shù)的神奇之處在于,通過unsafe.Pointer和reflect.XXXHeader取到了數(shù)據(jù)首地址,并實(shí)現(xiàn)了string和[]byte的直接轉(zhuǎn)換(這些操作在語言層面是禁止的)。
下面我們就通過這幾個(gè)“黑科技”來測(cè)試一下語言底層的秘密:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
結(jié)論如下:
1.string常量會(huì)在編譯期分配到只讀段,對(duì)應(yīng)數(shù)據(jù)地址不可寫入,并且相同的string常量不會(huì)重復(fù)存儲(chǔ)。
2.fmt.Sprintf生成的字符串分配在堆上,對(duì)應(yīng)數(shù)據(jù)地址可修改。
3.常量空字符串有數(shù)據(jù)地址,動(dòng)態(tài)生成的字符串沒有設(shè)置數(shù)據(jù)地址
4.Golang string和[]byte轉(zhuǎn)換,會(huì)將數(shù)據(jù)復(fù)制到堆上,返回?cái)?shù)據(jù)指向復(fù)制的數(shù)據(jù)
5.動(dòng)態(tài)生成的字符串,即使內(nèi)容一樣,數(shù)據(jù)也是在不同的空間
6.只有動(dòng)態(tài)生成的string,數(shù)據(jù)可以被黑科技修改
8.string和[]byte通過復(fù)制轉(zhuǎn)換,性能損失接近4倍
我將測(cè)試代碼放在這里,歡迎參考:
https://github.com/vipally/gx/blob/master/unsafe/string_test.go
參考資料:
[1] Go語言黑魔法 http://studygolang.com/articles/2909