深入理解?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-07
GO語言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口
這篇文章主要介紹了GO語言gin框架實(shí)現(xiàn)管理員認(rèn)證登陸接口,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
go開源項(xiàng)目用戶名密碼驗(yàn)證的邏輯鬼才寫法
這篇文章主要為大家介紹了go開源項(xiàng)目中發(fā)現(xiàn)的一個(gè)邏輯鬼才寫法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Golang中 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-01
vscode配置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-06
go打包aar及flutter調(diào)用aar流程詳解
這篇文章主要為大家介紹了go打包aar及flutter調(diào)用aar流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03

