概要
複数の文字を置換するときは strings.Replacer でまとめて置換した方が早そうな印象がありました。
しかし strings.Replace のコードの方が -bench の結果がよい状況に出会したので改めて確認しました。
用語
やりたいこと
ABCDE の A を 1 に BC を 23 に置き換えたいとき
用語
(用語に自信がないので以下の使い方で書きます)
- 「文字」
- 上記やりたいことでいうところの、A
 
- 上記やりたいことでいうところの、
- 「文字列」
- 上記やりたいことでいうところの、BC
 
- 上記やりたいことでいうところの、
- 「置き換えたい文字(列)」
- 上記やりたいことでいうところの、AやBC
 
- 上記やりたいことでいうところの、
- 「置換対象文字列」
- 上記やりたいことでいうところの、ABCDE
 
- 上記やりたいことでいうところの、
さっそくまとめ
以下の場合は strings.Replace を複数回実行した方が早そうです。
- 「置き換えたい文字(列)」が少ないとき
- 「文字列」を置き換えたいとき
- 「置換対象文字列」に、「置き換えたい文字(列)」が含まれない場合があるとき
ベンチマーク
以下の通り確認しましたが、よくないところがあれば教えてもらえるとうれしいです。
strings.Replaceのベンチマーク.go
const str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
func BenchmarkStringsReplace(b *testing.B) {
	b.Run("2 strings", func(b *testing.B) {
		b.Run("Replace all", func(b *testing.B) {
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				s := strings.Replace(str, "ABC", "123", -1)
				strings.Replace(s, "DEF", "456", -1)
			}
		})
		b.Run("Replace some", func(b *testing.B) {
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				s := strings.Replace(str, "ABC", "123", -1)
				strings.Replace(s, "456", "___", -1)
			}
		})
	})
}
strings.Replacerのベンチマーク.go
const str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"
func BenchmarkStringsReplacer(b *testing.B) {
	b.Run("2 strings", func(b *testing.B) {
		b.Run("Replace all.", func(b *testing.B) {
			oldnew := []string{
				"ABC", "123",
				"DEF", "456",
			}
			r := strings.NewReplacer(oldnew...)
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				r.Replace(str)
			}
		})
		b.Run("Replace some.", func(b *testing.B) {
			oldnew := []string{
				"ABC", "123",
				"456", "___",
			}
			r := strings.NewReplacer(oldnew...)
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				r.Replace(str)
			}
		})
	})
}
BenchmarkStringsReplace/2_strings/Replace_all-8       	 3911292	       305 ns/op	     320 B/op	       4 allocs/op
BenchmarkStringsReplace/2_strings/Replace_some-8      	 7506202	       164 ns/op	     160 B/op	       2 allocs/op
BenchmarkStringsReplacer/2_strings/Replace_all.-8     	 3955276	       305 ns/op	     192 B/op	       3 allocs/op
BenchmarkStringsReplacer/2_strings/Replace_some.-8    	 4732401	       254 ns/op	     192 B/op	       3 allocs/op
各環境、各バージョンの結果:
https://github.com/abetomo/strings-replace-bench/actions/runs/559930095