Go語言rune與字符串轉(zhuǎn)換的密切關(guān)系解析
介紹rune類型
golang中rune與字符串轉(zhuǎn)換的密切關(guān)系
rune
類型是 Go 語言的一種特殊數(shù)字類型。在 builtin/builtin.go
文件中,它的定義是type rune = int32
.官方對(duì)它是這么解釋的:rune
是類型 int32
的別名,在所有方面都等價(jià)于它,用來區(qū)分字符值跟整數(shù)值.使用單引號(hào)定義 ,返回采用 UTF-8 編碼的 Unicode 碼點(diǎn).Go 語言通過 rune
處理中文,支持國(guó)際化多語言。
為什么要給int32取一個(gè)別名rune呢,為什么不直接使用int32?
這是因?yàn)閯e名的使用在大型項(xiàng)目重構(gòu)中作用最為明顯,它能解決代碼升級(jí)或遷移過程中可能存在的類型兼容性問題。在go語言中還有另外一個(gè)類型別名也是用來處理字符的,要知道在go語言中可沒有char這個(gè)類型,因此對(duì)于字符的處理就要特別對(duì)待。
rune如何處理字符?
rune主要表示字符碼點(diǎn),特別在處理中文方面尤其有效。下面是例子
func main() { s := "我是一個(gè)gophers" fmt.Println(len(s)) fmt.Println(len([]rune(s))) } 運(yùn)行結(jié)果: 19 11
通過對(duì)比我們可以發(fā)現(xiàn)中文字符每個(gè)占據(jù)3個(gè)字節(jié),如果使用byte則需要三個(gè)不同的值,而使用rune剛好可以完整表達(dá)。
引出golang中關(guān)于字符串的說明
- Go 源代碼始終為 UTF-8。
- 字符串可以包含任意字節(jié)。
- 字符串文字中不包含字節(jié)級(jí)轉(zhuǎn)義符時(shí)字符串始終包含有效的 UTF-8 序列。
- 代表 Unicode 碼點(diǎn)的字節(jié)序列稱為
rune
。 - 在 Go 中不會(huì)保證字符串中的字符被規(guī)范化。
值得注意的地方
在前面已經(jīng)提到過,golang中沒有char這個(gè)概念,有的只是byte(uint8)單個(gè)字符的代表。因此要如何實(shí)現(xiàn)string呢?這個(gè)待會(huì)再講。我們現(xiàn)在主要介紹string遍歷過程中的問題。請(qǐng)看下面的例子
func main() { s := "我是一個(gè)gophers" for i, v := range s { fmt.Printf("第%d個(gè)值,類型為%T結(jié)果為:%v\n", i, v, string(v)) } for i, v := range s { fmt.Printf("第%d個(gè)值,類型為%T結(jié)果為:%v\n", i, v, string(s[i])) } } 運(yùn)行結(jié)果: 第0個(gè)值,類型為int32結(jié)果為:我 第3個(gè)值,類型為int32結(jié)果為:是 第6個(gè)值,類型為int32結(jié)果為:一 第9個(gè)值,類型為int32結(jié)果為:個(gè) 第12個(gè)值,類型為int32結(jié)果為:g 第13個(gè)值,類型為int32結(jié)果為:o 第14個(gè)值,類型為int32結(jié)果為:p 第15個(gè)值,類型為int32結(jié)果為:h 第16個(gè)值,類型為int32結(jié)果為:e 第17個(gè)值,類型為int32結(jié)果為:r 第18個(gè)值,類型為int32結(jié)果為:s ------------------------------------------- 第0個(gè)值,類型為int32結(jié)果為:? 第3個(gè)值,類型為int32結(jié)果為:? 第6個(gè)值,類型為int32結(jié)果為:? 第9個(gè)值,類型為int32結(jié)果為:? 第12個(gè)值,類型為int32結(jié)果為:g 第13個(gè)值,類型為int32結(jié)果為:o 第14個(gè)值,類型為int32結(jié)果為:p 第15個(gè)值,類型為int32結(jié)果為:h 第16個(gè)值,類型為int32結(jié)果為:e 第17個(gè)值,類型為int32結(jié)果為:r 第18個(gè)值,類型為int32結(jié)果為:s
通過比對(duì)和循環(huán)我們可以得知,golang中對(duì)于string的循環(huán),如果是中文則需要注意他的下標(biāo)序號(hào)是以3
為差值,字符是以1
為差值.通過s[i]
和v
的比對(duì)可以知道為什么golang中需要選擇rune作為字符串的轉(zhuǎn)換值.如果轉(zhuǎn)化是一個(gè)中文的話,一個(gè)字節(jié)的byte是無法容納的,而rune解決了這個(gè)問題.
介紹string類型
關(guān)于string類型,在go標(biāo)準(zhǔn)庫(kù)builtin中有如下說明:
// string is the set of all strings of 8-bit bytes, conventionally but not // necessarily representing UTF-8-encoded text. A string may be empty, but // not nil. Values of string type are immutable. type string string
也就是說:string是8位字節(jié)的集合,通常但不一定代表UTF-8編碼的文本.string可以為空,但是不能為nil.string的值是不能改變的. 而在go語言的源碼中我們可以看到string的構(gòu)成:
type stringStruct struct { str unsafe.Pointer len int }
stringStruct
就是string
的一個(gè)對(duì)象,這個(gè)str
就是一個(gè)指向字符數(shù)組首位的一個(gè)指針.len
就是這個(gè)字符串的長(zhǎng)度.那么這個(gè)數(shù)組指的是什么呢?其實(shí)就是一個(gè)[]byte
,string內(nèi)部就是通過這個(gè)字符切片組成的。而這個(gè)str就是指向了這個(gè)切片的首地址.因此也解釋了一個(gè)現(xiàn)象,為什么[]byte
中的值可以被修改,而string
中的值無法被修改.也正因如此copy內(nèi)置函數(shù)才可以將string類型復(fù)制為[]byte類型.
字符串的值不能被更改,但可以被替換. string在底層都是結(jié)構(gòu)體stringStruct{str: str_point, len: str_len},string結(jié)構(gòu)體的str指針指向的是一個(gè)字符常量的地址,這個(gè)地址里面的內(nèi)容是不可以被改變的,因?yàn)樗侵蛔x的,但是這個(gè)指針可以指向不同的地址.
為什么替換字符時(shí)string比[]byte效率慢?
由于每次替換string
的值時(shí),string
的str
指針無法進(jìn)行改變指向,因此程序內(nèi)部就需要去新開辟一個(gè)指針指向新的[]byte
,然后先前分配的string
內(nèi)存就會(huì)被GC所回收.這是導(dǎo)致string相較于[]byte操作低效的根本原因.
思考string、byte、rune之間的關(guān)系
Go語言把字符分 byte
和 rune
兩種類型處理.byte
是類型 unit8
的別名,用于存放占 1 字節(jié)的 ASCII 字符,如英文字符,返回的是字符原始字節(jié).rune
是類型 int32
的別名,用于存放多字節(jié)字符,如占 3 字節(jié)的中文字符,返回的是字符 Unicode 碼點(diǎn)值.
總結(jié)
- string無法進(jìn)行修改,只能進(jìn)行替換
- string底層由一個(gè)指針指向[]byte
- rune主要用來表示碼點(diǎn)并處理大于1字節(jié)小于4個(gè)字節(jié)的特殊字符
- 中文字符每個(gè)碼點(diǎn)占據(jù)多個(gè)字節(jié),并且在string循環(huán)中通過rune表示
以上就是Go語言rune與字符串轉(zhuǎn)換的密切關(guān)系解析的詳細(xì)內(nèi)容,更多關(guān)于Go rune字符串轉(zhuǎn)換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- golang中字符串和數(shù)字轉(zhuǎn)換方法
- Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換
- Go?基本數(shù)據(jù)類型與字符串相互轉(zhuǎn)換方法小結(jié)
- Go中基本數(shù)據(jù)類型和字符串表示之間轉(zhuǎn)換詳解
- Golang中int類型和字符串類型相互轉(zhuǎn)換的實(shí)現(xiàn)方法
- Go如何實(shí)現(xiàn)json字符串與各類struct相互轉(zhuǎn)換
- 淺談Go中數(shù)字轉(zhuǎn)換字符串的正確姿勢(shì)
- go語言實(shí)現(xiàn)字符串與其它類型轉(zhuǎn)換(strconv包)
相關(guān)文章
Go語言反射reflect.Value實(shí)現(xiàn)方法的調(diào)用
本文主要介紹了Go語言反射reflect.Value實(shí)現(xiàn)方法的調(diào)用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05golang struct擴(kuò)展函數(shù)參數(shù)命名警告解決方法
今天在使用VSCode編寫golang代碼時(shí),定義一個(gè)struct,擴(kuò)展幾個(gè)方法,需要的朋友可以參考下2017-02-02使用Go Validator有效驗(yàn)證數(shù)據(jù)示例分析
作為一名開發(fā)者,確保Go應(yīng)用中處理的數(shù)據(jù)是有效和準(zhǔn)確的非常重要,Go Validator是一個(gè)開源的數(shù)據(jù)驗(yàn)證庫(kù),為Go結(jié)構(gòu)體提供強(qiáng)大且易于使用的數(shù)據(jù)驗(yàn)證功能,本篇文章將介紹Go Validator庫(kù)的主要特點(diǎn)以及如何在Go應(yīng)用中使用它來有效驗(yàn)證數(shù)據(jù)2023-12-12Go語言實(shí)現(xiàn)關(guān)閉http請(qǐng)求的方式總結(jié)
面試的時(shí)候問到如何關(guān)閉http請(qǐng)求,一般人脫口而出的是關(guān)閉response.body,這是錯(cuò)誤的。本文為大家整理了三個(gè)正確關(guān)閉http請(qǐng)求的方法,希望對(duì)大家有所幫助2023-02-02Golang分布式鎖簡(jiǎn)單案例實(shí)現(xiàn)流程
分布式鎖是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式。如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源,那么訪問這些資源時(shí),需要通過一些互斥手段來防止彼此之間的干擾以保證一致性,在這種情況下,就需要使用分布式鎖了2022-12-12