深入理解?Go?中的字符串
字符串的本質(zhì)
在編程語言中,字符串發(fā)揮著重要的角色。字符串背后的數(shù)據(jù)結(jié)構(gòu)一般有兩種類型:
- 一種在編譯時(shí)指定長度,不能修改
- 一種具有動(dòng)態(tài)的長度,可以修改。
比如:與Python 中的字符串一樣,Go 語言中的字符串不能被修改,只能被訪問。
在 Python 中,如果改變一個(gè)字符串的值會(huì)得到如下結(jié)果:
>>> hi = "Hello" >>> hi 'Hello' >>> hi[0] = 'h' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object does not support item assignment >>>
同理,在 Go 中也一樣:
package main import "fmt" func main() { var hello = "Hello" hello[1] = 'h' fmt.Println(hello) } // # command-line-arguments // string_in_go/main.go:8:11: cannot assign to hello[1] (strings are immutable)
字符串的終止方式有兩種:
- 一種是 C 語言的隱式聲明,以字符 “\0” 作為終止符
- 一種是 Go 語言的顯式聲明
Go 語言的 string 的表示結(jié)構(gòu)如下:
type StringHeader struct { Data uintptr // Data 指向底層的字符數(shù)組 Len int // Len 用來表示字符串的長度 }
字符串的本質(zhì)上是一串字符數(shù)組,每個(gè)字符都在存儲(chǔ)時(shí)對(duì)應(yīng)了一個(gè)或多個(gè)整數(shù)。用這些整數(shù)來表示字符,比如打印 hello
的字節(jié)數(shù)組如下:
package main import "fmt" func main() { var hello = "Hello" for i := 0; i < len(hello); i++ { fmt.Printf("%x ", hello[i]) } } // Output: 48 65 6c 6c 6f
字符串的底層原理
字符串有特殊標(biāo)識(shí),有兩種聲明方式:
var s1 string = `hello world`
var s2 string = "hello world"
字符串常量在詞法解析階段最終會(huì)被標(biāo)記為 StringLit 類型的 Token 并被傳遞到編譯的下一個(gè)階段。
在語法分析階段,采取遞歸下降的方式讀取 UTF-8 字符,單撇號(hào)或雙引號(hào)是字符串的標(biāo)識(shí)。
分析的邏輯位于 syntax/scanner.go 文件中:
func (s *scanner) stdString() { ok := true s.nextch() for { if s.ch == '"' { s.nextch() break } if s.ch == '\\' { s.nextch() if !s.escape('"') { ok = false } continue } if s.ch == '\n' { s.errorf("newline in string") ok = false break } if s.ch < 0 { s.errorAtf(0, "string not terminated") ok = false break } s.nextch() } s.setLit(StringLit, ok) } func (s *scanner) rawString() { ok := true s.nextch() for { if s.ch == '`' { s.nextch() break } if s.ch < 0 { s.errorAtf(0, "string not terminated") ok = false break } s.nextch() } // We leave CRs in the string since they are part of the // literal (even though they are not part of the literal // value). s.setLit(StringLit, ok) }
從上面的代碼可以看到,Go 中有兩種字符串的檢查:一種是標(biāo)準(zhǔn)字符串以雙引號(hào)定義 ""
,如 "Hello,World"
, 還有一種是原始字符串,用 \\
定義的, 因此針對(duì)兩種字符串有兩種語法分析函數(shù):
- 如果是單撇號(hào),則調(diào)用
rawString
函數(shù) - 如果是雙引號(hào),則調(diào)用
stdString
函數(shù)
到此這篇關(guān)于深入理解 Go 中的字符串的文章就介紹到這了,更多相關(guān)Go 字符串內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Go語言單元測試中如何解決MySQL存儲(chǔ)依賴問題
MySQL?存儲(chǔ)就是一個(gè)非常常見的外部依賴,這篇文章主要來和大家一起探討在?Go?語言中編寫單元測試時(shí),如何解決?MySQL?存儲(chǔ)依賴,需要的可以參考一下2023-07-07GO語言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口
這篇文章主要介紹了GO語言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10go開源項(xiàng)目用戶名密碼驗(yàn)證的邏輯鬼才寫法
這篇文章主要為大家介紹了go開源項(xiàng)目中發(fā)現(xiàn)的一個(gè)邏輯鬼才寫法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Golang中 import cycle not allowed 問題
這篇文章主要介紹了Golang中 import cycle not allowed 問題的解決方法,問題從描述到解決都非常詳細(xì),需要的小伙伴可以參考一下2022-03-03詳解go-zero如何使用validator進(jìn)行參數(shù)校驗(yàn)
這篇文章主要介紹了如何使用validator庫做參數(shù)校驗(yàn)的一些十分實(shí)用的使用技巧,包括翻譯校驗(yàn)錯(cuò)誤提示信息、自定義提示信息的字段名稱、自定義校驗(yàn)方法等,感興趣的可以了解下2024-01-01vscode配置go開發(fā)環(huán)境的實(shí)戰(zhàn)過程
vscode配置go的開發(fā)環(huán)境很簡單,下面這篇文章主要給大家介紹了關(guān)于vscode配置go開發(fā)環(huán)境的實(shí)戰(zhàn)過程,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06go打包aar及flutter調(diào)用aar流程詳解
這篇文章主要為大家介紹了go打包aar及flutter調(diào)用aar流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03