够,但仅限于小数据、不区分大小写、无索引的简单匹配;大数据量需逐行处理,复杂需求应选用regexp、结构化索引或全文搜索引擎。
strings.Contains 做基础文本搜索够不够?够,但仅限于小数据、不区分大小写、无索引的简单匹配。比如读取一个配置文件内容后快速找某行是否含 "timeout",直接用 strings.Contains(line, "timeout") 最省事。但它不支持通配、正则、模糊或前缀加速,数据量一过几千行,反复扫描就明显变慢。
常见错误是把整个大字符串(如 10MB 日志)一次性读进内存再调 strings.Contains,结果程序 RSS 暴涨。实际应逐行处理:
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "ERROR") {
fmt.Println(line)
}
}
regexp 包regexp 是 Go 标准库里最常被低估的搜索工具。它比 strings.Contains 多出模式能力,又比引入全文引擎轻量得多。注意:编译正则表达式有开销,别在循环里反复调 regexp.Compile。
var errRegex = regexp.MustCompile(`\bERROR\b`)
regexp.MustCompile(`(?i)\berror\b`)
errRegex.FindStringSubmatch(lineBytes),返回 []byte,避免 string 转换开销^GET)比 .*timeout.* 快得多;FindStringIndex 比 FindAllString 内存更友好比如你有一批 []User,要查 name contains "li" AND age > 25,直接 for 循环 + if 判断没问题;但一旦加到 3 个条件或数据超 1 万条,就得考虑提前剪枝或缓存索引。
实操建议:
sort.Slice 按高频查询字段(如 age)排序,再用 sort.Search 二分定位范围,减少遍历量map[string][]int 索引(如 nameIndex["li"] = [2, 8, 15]),代价是内存换时间json.Unmarshal —— 预解析好结构体切片,搜索只操作内存对象bleve 或 meilisearch?出现以下任一情况,说明已超出标准库能力边界:
"status:active AND NOT deleted")Go 生态里 bleve 是纯本地、可嵌入的首选,但它的查询 DSL 和索引构建逻辑比 SQL 更陡峭;如果服务可接受 HTTP 调用,meilisearch 的 Go client(meilisearch-go)上手更快,不过得额外运维一个进程。
最容易被忽略的是 schema 设计阶段 —— 比如没给 content 字段设 index:true,搜不到不是代码问题,是配置漏了。