Golang中比strings.Contains更高效的字符串查找替代方案
Golang中比strings.Contains更高效的字符串查找替代方案
更好的替代 strings.Contains 的方法,因为 string.Contains 会消耗更多的 CPU。
2 回复
strings.Contains 所调用的 strings.Index 实现已经过高度优化。
您提到“快得多”。比什么快得多?您是如何测量的?
更多关于Golang中比strings.Contains更高效的字符串查找替代方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中,确实有比strings.Contains更高效的字符串查找方案,具体取决于使用场景。以下是几种替代方法:
1. bytes.Contains(处理字节切片)
如果数据源是[]byte,直接使用bytes.Contains避免字符串转换:
package main
import (
"bytes"
"fmt"
)
func main() {
data := []byte("Hello, Golang world!")
sub := []byte("Golang")
if bytes.Contains(data, sub) {
fmt.Println("Found")
}
}
2. strings.Index + 直接比较
对于只需要检查存在性的场景,strings.Index返回位置更高效:
package main
import (
"strings"
"fmt"
)
func main() {
s := "Hello, Golang world!"
substr := "Golang"
if strings.Index(s, substr) != -1 {
fmt.Println("Found")
}
}
3. Boyer-Moore算法(长文本搜索)
对于大文本搜索,使用第三方Boyer-Moore实现:
// 安装:go get github.com/cloudflare/ahocorasick
package main
import (
"fmt"
"github.com/cloudflare/ahocorasick"
)
func main() {
matcher := ahocorasick.NewStringMatcher([]string{"Golang", "Go"})
matches := matcher.Match([]byte("Hello, Golang world!"))
if len(matches) > 0 {
fmt.Println("Found at positions:", matches)
}
}
4. Rabin-Karp算法(多模式匹配)
package main
import (
"fmt"
"hash/fnv"
)
func rabinKarp(text, pattern string) bool {
if len(pattern) > len(text) {
return false
}
var h1, h2 uint32
hash := fnv.New32a()
hash.Write([]byte(pattern))
h1 = hash.Sum32()
hash.Reset()
hash.Write([]byte(text[:len(pattern)]))
h2 = hash.Sum32()
for i := 0; i <= len(text)-len(pattern); i++ {
if h1 == h2 && text[i:i+len(pattern)] == pattern {
return true
}
if i < len(text)-len(pattern) {
// 滚动哈希更新
h2 = updateHash(h2, text[i], text[i+len(pattern)])
}
}
return false
}
func updateHash(hash uint32, out, in byte) uint32 {
// 简化的哈希更新逻辑
return (hash-uint32(out))*31 + uint32(in)
}
func main() {
fmt.Println(rabinKarp("Hello, Golang world!", "Golang"))
}
5. 预编译正则表达式(重复使用)
package main
import (
"fmt"
"regexp"
)
func main() {
// 预编译正则表达式
re := regexp.MustCompile(`Golang`)
// 重复使用编译后的正则
for i := 0; i < 1000; i++ {
if re.MatchString("Hello, Golang world!") {
// 匹配成功
}
}
}
性能对比示例
package main
import (
"strings"
"testing"
)
func BenchmarkContains(b *testing.B) {
s := strings.Repeat("a", 1000) + "Golang" + strings.Repeat("b", 1000)
substr := "Golang"
b.ResetTimer()
for i := 0; i < b.N; i++ {
strings.Contains(s, substr)
}
}
func BenchmarkIndex(b *testing.B) {
s := strings.Repeat("a", 1000) + "Golang" + strings.Repeat("b", 1000)
substr := "Golang"
b.ResetTimer()
for i := 0; i < b.N; i++ {
strings.Index(s, substr) != -1
}
}
选择建议:
- 小文本:
strings.Index通常比strings.Contains稍快 - 字节数据:使用
bytes.Contains - 多次搜索相同模式:预编译正则表达式
- 大文本或多模式:考虑Boyer-Moore或Aho-Corasick算法
实际性能差异需要通过基准测试验证,因为Go的strings.Contains内部已经做了优化。

