網站首頁 編程語言 正文
前言
字符串拼接是老生常談了。在 Go 語言中,常見的拼接字符串的方法有:用+
號,或者使用fmt
包的Sprintf
。
str1 := "a" + "b" // str1: "ab" str2 := fmt.Sprintf("%s%s", "a", "b") // str2: "ab"
字符串低層是不可修改的,所以每次拼接字符串,都需要重新分配內存。如果需要頻繁拼接字符串,上面兩種方法可能性能低下。我們寫下壓測代碼
// 使用 + 拼接字符串 func BenchmarkConcatStrWithPlus(b *testing.B) { str := "" for i := 0; i < b.N; i++ { str += "test" } } // 使用 Sprintf 拼接字符串 func BenchmarkConcatStrWithSprintf(b *testing.B) { str := "" for i := 0; i < b.N; i++ { str = fmt.Sprintf("%s%s", str, "test") } }
執行: go test -bench . -benchmem
,得到以下結果。這個壓測結果,留著跟下文的優化后的結果做對比。
goos: darwin
goarch: amd64
pkg: example/string
cpu: Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz
BenchmarkConcatStrWithPlus-8 ? ? ? ? ? ? ?329544 ? ? ? ? ? ? 87040 ns/op ? ? ? ? ?663108 B/op ? ? ? ? ?1 allocs/op
BenchmarkConcatStrWithSprintf-8 ? ? ? ? ? 308691 ? ? ? ? ? ?160075 ns/op ? ? ? ? 1241769 B/op ? ? ? ? ?4 allocs/op
PASS
ok ? ? ?example/string ?78.604s
bytes.Buffer 和 strings.Builder
用法
bytes.Buffer 和 strings.Builder 底層類似,都是用一個 []byte 類型的切片來存字符串。用法也類似,零值可以直接使用。
bytes.Buffer 拼接字符串:
var buf bytes.Buffer // 拼接 "a" 和 "b" buf.WriteString("a") buf.WriteString("b") str := buf.String() // str 等于 "ab"
strings.Builder 拼接字符串:
var sb strings.Builder // 拼接 "a" 和 "b" sb.WriteString("a") sb.WriteString("b") str := sb.String() // str 等于 "ab"
并且,兩者都提供了 Reset 方法,很方便結合 Sync.Pool
使用。
區別
需要注意的是,String()
方法實現還是有些許區別的,摘取 bytes.Buffer 的String
方法的源碼注釋:
// String returns the contents of the unread portion of the buffer // as a string. If the Buffer is a nil pointer, it returns "<nil>". // // To build strings more efficiently, see the strings.Builder type. func (b *Buffer) String() string {
bytes.Buffer 的 String
方法會把底層 []byte 轉成字符串,這需要另外申請內存,而 strings.Builder 則不用。
性能對比
// 使用 bytes.Buffer 拼接字符串 func BenchmarkConcatStrWithBuf(b *testing.B) { var buf bytes.Buffer for i := 0; i < b.N; i++ { buf.WriteString("test") } _ = buf.String() } // 使用 strings.Builder 拼接字符串 func BenchmarkConcatStrWithSb(b *testing.B) { var sb strings.Builder for i := 0; i < b.N; i++ { sb.WriteString("test") } _ = sb.String() }
執行: go test -bench . -benchmem
,得到以下結果:
BenchmarkConcatStrWithBuf-8 ? ? 87914572 ? ? ? ? ? ? ? ?17.51 ns/op ? ? ? ? ? 16 B/op ? ? ? ? ?0 allocs/op
BenchmarkConcatStrWithSb-8 ? ? ?278124620 ? ? ? ? ? ? ? ?9.562 ns/op ? ? ? ? ?22 B/op ? ? ? ? ?0 allocs/op
PASS
ok ? ? ?example/string ?5.442s
對比上面的壓測,strings.Builder(22 B/op)、bytes.Buffer(16 B/op) 比 Sprintf(1241769 B/op)和 + 號(663108 B/op)在內存方面,差距還是很明顯的。
原文鏈接:https://juejin.cn/post/7168765782082453535
相關推薦
- 2022-07-13 實現基于 session+redis 的防重復提交
- 2022-03-29 Android中的xml解析介紹_Android
- 2023-04-18 react-router?重新加回跳轉攔截功能詳解_React
- 2023-07-02 jQuery和HTML對某個標簽設置只讀或者禁用屬性的方式_jquery
- 2022-04-10 Python語言實現科學計算器_python
- 2022-02-20 Android?WebView實現全屏播放視頻_Android
- 2022-02-17 Pytorch常用的對象類和繼承機制(如果有)
- 2021-11-08 Android如何實現時間線效果_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支