国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 網站 > 幫助中心 > 正文

Go 高效截取字符串的一些思考

2024-07-09 22:41:07
字體:
來源:轉載
供稿:網友

最近我在Go Forum 中發現了String size of 20 character 的問題,“hollowaykeanho” 給出了相關的答案,而我從中發現了截取字符串的方案并非最理想的方法,因此做了一系列實驗并獲得高效截取字符串的方法,這篇文章將逐步講解我實踐的過程。

字節切片截取

這正是 “hollowaykeanho” 給出的第一個方案,我想也是很多人想到的第一個方案,利用 go 的內置切片語法截取字符串:

s := "abcdef"fmt.Println(s[1:4])

我們很快就了解到這是按字節截取,在處理 ASCII 單字節字符串截取,沒有什么比這更完美的方案了,中文往往占多個字節,在 utf8 編碼中是3個字節,如下程序我們將獲得亂碼數據:

s := "Go 語言"fmt.Println(s[1:4])

殺手锏 - 類型轉換 []rune

“hollowaykeanho” 給出的第二個方案就是將字符串轉換為 []rune,然后按切片語法截取,再把結果轉成字符串。

s := "Go 語言"rs := []rune(s)fmt.Println(strings(rs[1:4]))

首先我們得到了正確的結果,這是最大的進步。不過我對類型轉換一直比較謹慎,我擔心它的性能問題,因此我嘗試在搜索引擎和各大論壇查找答案,但是我得到最多的還是這個方案,似乎這已經是唯一的解。

我嘗試寫個性能測試評測它的性能:

package benchmarkimport (  "testing")var benchmarkSubString = "Go語言是Google開發的一種靜態強類型、編譯型、并發型,并具有垃圾回收功能的編程語言。為了方便搜索和識別,有時會將其稱為Golang。"var benchmarkSubStringLength = 20func SubStrRunes(s string, length int) string {  if utf8.RuneCountInString(s) > length {    rs := []rune(s)    return string(rs[:length])  }  return s}func BenchmarkSubStrRunes(b *testing.B) {  for i := 0; i < b.N; i++ {    SubStrRunes(benchmarkSubString, benchmarkSubStringLength)  }}

我得到了讓我有些吃驚的結果:

goos: darwingoarch: amd64pkg: github.com/thinkeridea/go-extend/exunicode/exutf8/benchmarkBenchmarkSubStrRunes-8      872253       1363 ns/op       336 B/op     2 allocs/opPASSok   github.com/thinkeridea/go-extend/exunicode/exutf8/benchmark   2.120s

對 69 個的字符串截取前 20 個字符需要大概 1.3 微秒,這極大的超出了我的心里預期,我發現因為類型轉換帶來了內存分配,這產生了一個新的字符串,并且類型轉換需要大量的計算。

救命稻草 - utf8.DecodeRuneInString

我想改善類型轉換帶來的額外運算和內存分配,我仔細的梳理了一遍 strings 包,發現并沒有相關的工具,這時我想到了 utf8 包,它提供了多字節計算相關的工具,實話說我對它并不熟悉,或者說沒有主動(直接)使用過它,我查看了它所有的文檔發現 utf8.DecodeRuneInString 函數可以轉換單個字符,并給出字符占用字節的數量,我嘗試了如此下的實驗:

package benchmarkimport (  "testing"  "unicode/utf8")var benchmarkSubString = "Go語言是Google開發的一種靜態強類型、編譯型、并發型,并具有垃圾回收功能的編程語言。為了方便搜索和識別,有時會將其稱為Golang。"var benchmarkSubStringLength = 20func SubStrDecodeRuneInString(s string, length int) string {  var size, n int  for i := 0; i < length && n < len(s); i++ {    _, size = utf8.DecodeRuneInString(s[n:])    n += size  }  return s[:n]}func BenchmarkSubStrDecodeRuneInString(b *testing.B) {  for i := 0; i < b.N; i++ {    SubStrDecodeRuneInString(benchmarkSubString, benchmarkSubStringLength)  }}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 安远县| 肥西县| 疏附县| 万源市| 阿巴嘎旗| 曲麻莱县| 黔江区| 武穴市| 滦平县| 饶平县| 临洮县| 衡南县| 清镇市| 和田县| 麦盖提县| 曲阳县| 称多县| 常宁市| 韶关市| 婺源县| 温宿县| 如东县| 栖霞市| 青川县| 射阳县| 天等县| 南和县| 都江堰市| 怀安县| 玉树县| 荃湾区| 隆德县| 同江市| 萍乡市| 睢宁县| 惠水县| 革吉县| 会理县| 察雅县| 双江| 辽阳县|