真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

go語(yǔ)言字符串長(zhǎng)度 go語(yǔ)言 字符串

go語(yǔ)言string之Buffer與Builder

操作字符串離不開字符串的拼接,但是Go中string是只讀類型,大量字符串的拼接會(huì)造成性能問(wèn)題。

專注于為中小企業(yè)提供網(wǎng)站制作、網(wǎng)站設(shè)計(jì)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)汕城免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上1000家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

拼接字符串,無(wú)外乎四種方式,采用“+”,“fmt.Sprintf()”,"bytes.Buffer","strings.Builder"

上面我們創(chuàng)建10萬(wàn)字符串拼接的測(cè)試,可以發(fā)現(xiàn)"bytes.Buffer","strings.Builder"的性能最好,約是“+”的1000倍級(jí)別。

這是由于string是不可修改的,所以在使用“+”進(jìn)行拼接字符串,每次都會(huì)產(chǎn)生申請(qǐng)空間,拼接,復(fù)制等操作,數(shù)據(jù)量大的情況下非常消耗資源和性能。而采用Buffer等方式,都是預(yù)先計(jì)算拼接字符串?dāng)?shù)組的總長(zhǎng)度(如果可以知道長(zhǎng)度),申請(qǐng)空間,底層是slice數(shù)組,可以以append的形式向后進(jìn)行追加。最后在轉(zhuǎn)換為字符串。這申請(qǐng)了不斷申請(qǐng)空間的操作,也減少了空間的使用和拷貝的次數(shù),自然性能也高不少。

bytes.buffer是一個(gè)緩沖byte類型的緩沖器存放著都是byte

是一個(gè)變長(zhǎng)的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一個(gè) 空的 buffer,但是可以使用,底層就是一個(gè) []byte, 字節(jié)切片。

向Buffer中寫數(shù)據(jù),可以看出Buffer中有個(gè)Grow函數(shù)用于對(duì)切片進(jìn)行擴(kuò)容。

從Buffer中讀取數(shù)據(jù)

strings.Builder的方法和bytes.Buffer的方法的命名幾乎一致。

但實(shí)現(xiàn)并不一致,Builder的Write方法直接將字符拼接slice數(shù)組后。

其沒(méi)有提供read方法,但提供了strings.Reader方式

Reader 結(jié)構(gòu):

Buffer:

Builder:

可以看出Buffer和Builder底層都是采用[]byte數(shù)組進(jìn)行裝載數(shù)據(jù)。

先來(lái)說(shuō)說(shuō)Buffer:

創(chuàng)建好Buffer是一個(gè)empty的,off 用于指向讀寫的尾部。

在寫的時(shí)候,先判斷當(dāng)前寫入字符串長(zhǎng)度是否大于Buffer的容量,如果大于就調(diào)用grow進(jìn)行擴(kuò)容,擴(kuò)容申請(qǐng)的長(zhǎng)度為當(dāng)前寫入字符串的長(zhǎng)度。如果當(dāng)前寫入字符串長(zhǎng)度小于最小字節(jié)長(zhǎng)度64,直接創(chuàng)建64長(zhǎng)度的[]byte數(shù)組。如果申請(qǐng)的長(zhǎng)度小于二分之一總?cè)萘繙p去當(dāng)前字符總長(zhǎng)度,說(shuō)明存在很大一部分被使用但已讀,可以將未讀的數(shù)據(jù)滑動(dòng)到數(shù)組頭。如果容量不足,擴(kuò)展2*c + n 。

其String()方法就是將字節(jié)數(shù)組強(qiáng)轉(zhuǎn)為string

Builder是如何實(shí)現(xiàn)的。

Builder采用append的方式向字節(jié)數(shù)組后添加字符串。

從上面可以看出,[]byte的內(nèi)存大小也是以倍數(shù)進(jìn)行申請(qǐng)的,初始大小為 0,第一次為大于當(dāng)前申請(qǐng)的最大 2 的指數(shù),不夠進(jìn)行翻倍.

可以看出如果舊容量小于1024進(jìn)行翻倍,否則擴(kuò)展四分之一。(2048 byte 后,申請(qǐng)策略的調(diào)整)。

其次String()方法與Buffer的string方法也有明顯區(qū)別。Buffer的string是一種強(qiáng)轉(zhuǎn),我們知道在強(qiáng)轉(zhuǎn)的時(shí)候是需要進(jìn)行申請(qǐng)空間,并拷貝的。而Builder只是指針的轉(zhuǎn)換。

這里我們解析一下 *(*string)(unsafe.Pointer(b.buf)) 這個(gè)語(yǔ)句的意思。

先來(lái)了解下unsafe.Pointer 的用法。

也就是說(shuō),unsafe.Pointer 可以轉(zhuǎn)換為任意類型,那么意味著,通過(guò)unsafe.Pointer媒介,程序繞過(guò)類型系統(tǒng),進(jìn)行地址轉(zhuǎn)換而不是拷貝。

即*A = Pointer = *B

就像上面例子一樣,將字節(jié)數(shù)組轉(zhuǎn)為unsafe.Pointer類型,再轉(zhuǎn)為string類型,s和b中內(nèi)容一樣,修改b,s也變了,說(shuō)明b和s是同一個(gè)地址。但是對(duì)s重新賦值后,意味著s的地址指向了“WORLD”,它們所使用的內(nèi)存空間不同了,所以s改變后,b并不會(huì)改變。

所以他們的區(qū)別就在于 bytes.Buffer 是重新申請(qǐng)了一塊空間,存放生成的string變量, 而strings.Builder直接將底層的[]byte轉(zhuǎn)換成了string類型返回了回來(lái),去掉了申請(qǐng)空間的操作。

golang unicode/utf8源碼分析

包 utf-8 實(shí)現(xiàn)的功能和常量用于文章utf8編碼,包含runes和utf8字節(jié)序列的轉(zhuǎn)換功能.在unicode中,一個(gè)中文占兩個(gè)字節(jié),utf-8中一個(gè)中文占三個(gè)字節(jié),golang默認(rèn)的編碼是utf-8編碼,因此默認(rèn)一個(gè)中文占三個(gè)字節(jié),但是golang中的字符串底層實(shí)際上是一個(gè)byte數(shù)組.

Output:

RuneSelf該值的字節(jié)碼值為128,在判斷是否是常規(guī)的ascii碼是使用。hicb字節(jié)碼值為191. FF 的對(duì)應(yīng)的字節(jié)碼為255。

計(jì)算字符串中的rune數(shù)量,原理:首先取出字符串的碼值,然后判斷是不是個(gè)小于128的,如果是小于則直接continue.rune個(gè)數(shù)++.

如果是個(gè)十六進(jìn)制f1.的則是無(wú)效字符,直接continue.rune個(gè)數(shù)++,也就是說(shuō)一個(gè)無(wú)效的字符也當(dāng)成一個(gè)字長(zhǎng)為1的rune.如果字符的碼值在first列表中的值和7按位的結(jié)果為其字長(zhǎng),比如上面示例中的 鋼 。其字長(zhǎng)為三位,第一位的值為 233 .二進(jìn)制形式為 11101001 ;與7按位與后的值為0.從acceptRanges中取出的結(jié)果為{locb, hicb}。也就是標(biāo)識(shí) ox80 到 0xbf 之間的值。而結(jié)果n也就是直接size+3跳過(guò)3個(gè)字節(jié)后,rune個(gè)數(shù)++。其他函數(shù)的處理流程差不多,不再過(guò)多敘述。

示例:

ValidString返回值表明參數(shù)字符串是否是一個(gè)合法的可utf8編碼的字符串。

RuneCount返回參數(shù)中包含的rune數(shù)量,第一個(gè)例子中將 utf8.RuneCountInString ,改成該方法調(diào)用,返回的結(jié)果相同。錯(cuò)誤的和短的被當(dāng)成一個(gè)長(zhǎng)一字節(jié)的rune.單個(gè)字符 H 就表示一個(gè)長(zhǎng)度為1字節(jié)的rune.

該函數(shù)標(biāo)識(shí)參數(shù)是否以一個(gè)可編碼的rune開頭,上面的例子中,因?yàn)樽址且砸粋€(gè)ascii碼值在0-127內(nèi)的字符開頭,所以在執(zhí)行

first[p[0]] 時(shí),取到的是 p[0] 是72,在first列表中,127之前的值都相同都為 0xF0 ,十進(jìn)制標(biāo)識(shí)為240,與7按位與后值為0,所以,直接返回 true .

和FullRune類似,只是參數(shù)為字符串形式

Go中字符串的遍歷

首先說(shuō)一下go中的字符串類型:

字符串就是一串固定長(zhǎng)度的字符連接起來(lái)的字符序列。Go的字符串是由單個(gè)字節(jié)連接起來(lái)的。Go語(yǔ)言的字符串的字節(jié)使用UTF-8編碼標(biāo)識(shí)Unicode文本。

下面介紹字符串的三種遍歷方式,根據(jù)實(shí)際情況選擇即可。

該遍歷方式==缺點(diǎn)==:遍歷是按照字節(jié)遍歷,因此如果有中文等非英文字符,就會(huì)出現(xiàn)亂碼,比如要遍歷"abc北京"這個(gè)字符串,效果如下:

可見這不是我們想要的效果,根據(jù)utf-8中文編碼規(guī)則,我們要str[3]str[4]str[5]三個(gè)字節(jié)合起來(lái)組成“北”字及 str[6]str[7]str[8]合起來(lái)組成“京”字。由此引出下面第二種遍歷方法。

該方式是按照字符遍歷的,所以不會(huì)出現(xiàn)亂碼,如下:

運(yùn)行結(jié)果:

從圖中可以看到第二個(gè)漢子“京”的開始下標(biāo)是6,直接跳過(guò)了4和5,可見確實(shí)依照utf8編碼方式將三個(gè)字節(jié)組合成了一個(gè)漢字,str[3]-str[5]組合成“北”字,str[6]-str[8]組合成了“京”字。

由于下標(biāo)的不確定性,所以引出了下面的遍歷方式。

1 可以先將字符串轉(zhuǎn)成 []rune 切片

2 再用常規(guī)方法進(jìn)行遍歷

運(yùn)行效果:

由此可見下標(biāo)是按1遞增的,沒(méi)有產(chǎn)生跳躍現(xiàn)象。

golang原生數(shù)據(jù)類型

golang原生數(shù)據(jù)類型:按長(zhǎng)度:int8(-128-127)、int16、int32、int64。

布爾型:布爾型的值只可以是常量true或者false。一個(gè)簡(jiǎn)單的例子:varbbool=true。

數(shù)字類型:整型int和浮點(diǎn)型float32、float64,Go語(yǔ)言支持整型和浮點(diǎn)型數(shù)字,并且支持復(fù)數(shù),其中位的運(yùn)算采用補(bǔ)碼。

字符串類型:字符串就是一串固定長(zhǎng)度的字符連接起來(lái)的字符序列。Go的字符串是由單個(gè)字節(jié)連接起來(lái)的。Go語(yǔ)言的字符串的字節(jié)使用UTF-8編碼標(biāo)識(shí)Unicode文本。

派生類型:包括:(a)指針類型(Pointer)(b)數(shù)組類型?結(jié)構(gòu)化類型(struct)(d)Channel類型(e)函數(shù)類型(f)切片類型(g)接口類型(interface)(h)Map類型。


網(wǎng)頁(yè)題目:go語(yǔ)言字符串長(zhǎng)度 go語(yǔ)言 字符串
轉(zhuǎn)載注明:http://weahome.cn/article/hhoojg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部