Files
excel-search-tool/go/README.md
T
2026-09-21 21:04:43 +08:00

12 KiB
Raw Blame History

Excel 关键字搜索工具(Go 版)

跨 Excel / Word / CSV / 文本 文件批量关键字检索工具,纯 Go 实现,编译为独立可执行文件,无需 Python/Pandas 运行时。支持 OOXML 格式(.xlsx/.xlsm/.xltx/.xltm、.docx/.docm)与 .csv、.txt 的并发扫描,内置文件级缓存加速重复搜索,并提供区分大小写、完整单词、子目录递归、文件类型过滤等搜索选项。

  • 模块名:excel-search(单 Go module)
  • Go 版本要求:≥ 1.22(开发机实测 1.27.1)
  • 核心依赖:github.com/xuri/excelize/v2 v2.8.1

一、三种交付形态

入口 路径 形态 适用场景
桌面版 cmd/desktop/ 本地 HTTP 服务 + Edge 应用模式窗口 日常使用,双击即用,无控制台
WebUI 版 cmd/webui/ 本地 HTTP 服务 + 浏览器打开 不想用 Edge 应用窗口,用默认浏览器
CLI 版 cmd/searcher/ 命令行工具 脚本化、集成到批处理/CI

三者共享同一套搜索引擎(internal/search),行为一致。


二、目录结构与文件说明

go/
├── go.mod                     # 模块定义(module excel-search),声明 go 版本与直接依赖
├── go.sum                     # 依赖校验和锁定文件,保证构建可复现(勿手改)
├── Makefile                   # Linux/macOS/CI 构建脚本(build/test/vet/fmt/frontend/clean)
├── build.bat                  # Windows 一键构建脚本(无 make 环境使用)
├── .gitignore                 # 忽略 bin/、*.exe、logs/、.cache/、node_modules/ 等产物
├── .golangci.yml              # golangci-lint 静态检查配置(在 CI 或本地非沙箱环境运行)
│
├── cmd/                       # 可执行程序入口(每个子目录一个 main 包)
│   ├── desktop/
│   │   ├── main.go            # 桌面版入口:HTTP 路由 + 历史记录 + 心跳守卫 + 优雅关闭,
│   │   │                      #   前端页面以 htmlUI 字符串常量内嵌,样式经 go:embed 注入
│   │   └── style.css          # 编译产物:由 frontend 生成的 Tailwind 静态样式(勿手改)
│   ├── webui/
│   │   ├── main.go            # WebUI 入口:go:embed 内嵌 static/*,FileServer 托管静态页
│   │   └── static/
│   │       ├── index.html     # WebUI 前端页面(引用本地 style.css,无 CDN)
│   │       └── style.css      # 编译产物:由 frontend 生成的 Tailwind 静态样式(勿手改)
│   └── searcher/
│       └── main.go            # CLI 入口:flag 解析(-dir/-keyword/-json/-workers/-version)
│
├── internal/                  # 内部包(仅本模块可导入,不对外暴露)
│   ├── config/
│   │   └── config.go          # 配置加载:从环境变量读取,带默认值(EXCEL_SEARCH_*)
│   ├── logging/
│   │   └── logging.go         # 结构化日志:slog 初始化(text/json)+ request_id 生成
│   ├── model/
│   │   └── result.go          # 数据模型:SearchResult 结构体(含 JSON tag)
│   └── search/
│       ├── scanner.go         # 搜索引擎核心:worker pool + 全链路 context 取消 + 文件级缓存
│       ├── options.go         # 搜索选项模型:SearchOptions + FileType + 扩展名分类
│       ├── matcher.go         # 匹配器:Unicode NFC 规范化 + 大小写折叠 + 完整单词边界
│       ├── word.go            # Word 解析:.docx/.docm 的 word/document.xml 段落提取
│       ├── scanner_test.go    # 单元测试:大小写/完整单词/文件类型/递归/docx/缓存隔离
│       └── matcher_test.go    # 匹配器单元测试
│
└── frontend/                  # 前端构建工具链(仅在需要修改样式时使用)
    ├── package.json           # npm 依赖声明(devDependency: tailwindcss ^3.4)
    ├── package-lock.json      # npm 依赖锁文件(保证 npm install 可复现)
    ├── tailwind.config.js     # Tailwind 配置:content 扫描 cmd/desktop/main.go 与 webui html
    ├── input.css              # Tailwind 输入文件(@tailwind base/components/utilities)
    └── dist/
        └── style.css          # 生成的静态样式(构建后复制到两个 embed 位置)

关键设计说明

  1. style.css 是编译产物:cmd/desktop/style.css 与 cmd/webui/static/style.css 内容相同,均由 frontend/ 预编译生成,并已 go:embed 进二进制。不要直接手工编辑,改样式走 frontend/ 流程(见下文「前端样式编译」)。

  2. 搜索引擎只有一份:internal/search/scanner.go,桌面版/WebUI/CLI 共用,不存在重复实现。

  3. 运行时生成目录(已 gitignore,无需提交):

    • logs/app.log —— 结构化日志(desktop/webui 写文件,CLI 写 stderr)
    • .cache/ —— 搜索缓存与搜索历史(search_history.json)

三、编译详细步骤

1. 前置条件

依赖 版本 是否必需 说明
Go ≥ 1.22 ✅ 必需 编译与运行
Node.js + npm 任意较新版 ⚠️ 可选 仅修改样式、重新生成 CSS 时需要

检查环境:

go version      # 需 ≥ go1.22
node --version  # 可选,仅前端样式需要

2. 拉取依赖(可选)

go build 会自动下载依赖,也可手动预拉取:

cd /path/to/go
go mod download
go mod tidy     # 整理 go.mod/go.sum(新增/移除依赖后执行)

3. 编译可执行文件

产物默认输出到 bin/,该目录已被 gitignore。以下命令在 go/ 目录内执行。

方式一:Go 原生命令(逐个编译)

# 桌面版
go build -trimpath -ldflags "-s -w" -o bin/excel-search-desktop.exe ./cmd/desktop

# WebUI 版
go build -trimpath -ldflags "-s -w" -o bin/excel-search-webui.exe ./cmd/webui

# CLI 版
go build -trimpath -ldflags "-s -w" -o bin/excel-searcher.exe ./cmd/searcher

参数说明:

  • -trimpath:从二进制中剥离本机绝对路径,便于复现构建
  • -ldflags "-s -w":去除符号表与调试信息,减小体积
  • -o bin/xxx.exe:指定输出路径与文件名

方式二:Windows 一键脚本

build.bat

脚本会依次编译三个入口到 bin/,版本号可用环境变量覆盖:

set VERSION=v1.2.3
build.bat

方式三:Make(Linux / macOS / CI)

make build        # 编译三个入口
make frontend     # 先重建前端 CSS,再编译(完整发布流程)
make              # 等价于 make frontend build

4. 注入版本号

三入口均内置 version 变量(默认 dev),通过 -ldflags 注入:

VERSION=v1.2.3

go build -trimpath \
  -ldflags "-s -w -X main.version=$VERSION" \
  -o bin/excel-searcher.exe ./cmd/searcher

# 验证
./bin/excel-searcher.exe -version   # 输出 v1.2.3

build.bat 与 Makefile 已内置该逻辑(VERSION 环境变量,默认取 git describe 或 dev)。

5. 前端样式编译(仅修改样式时)

日常编译无需执行此步骤——cmd/*/style.css 已作为编译产物提交。仅当修改了 HTML 里的 class 或 frontend/input.css 时才需要重新生成。

cd frontend
npm install        # 首次执行,安装 tailwindcss(生成 node_modules/,已 gitignore)
npm run build      # 生成 dist/style.css(tailwindcss -c ... --minify)

# 将产物复制到两个 embed 位置
cp dist/style.css ../cmd/desktop/style.css
cp dist/style.css ../cmd/webui/static/style.css

或直接用 Make:

make frontend

6. 交叉编译

纯 Go 依赖(excelize 无 CGO),可轻松交叉编译到其他平台:

# 例:在 Windows 上编译 Linux 版
GOOS=linux GOARCH=amd64 go build -trimpath -ldflags "-s -w" \
  -o bin/excel-searcher-linux-amd64 ./cmd/searcher

# 例:编译 macOS 版
GOOS=darwin GOARCH=arm64 go build -trimpath -ldflags "-s -w" \
  -o bin/excel-searcher-darwin-arm64 ./cmd/searcher

注意:go test -race 依赖 CGO 工具链,交叉编译竞态检测需目标平台原生编译。

7. 测试与静态检查

# 单元测试
go test ./...

# 竞态检测(需 gcc/CGO,建议 Linux CI 或安装 MinGW)
go test -race ./...

# 静态检查
go vet ./...
gofmt -l .        # 输出为空表示格式规范

# 更全面的 lint(需先安装 golangci-lint)
golangci-lint run ./...

四、运行方式

桌面版(excel-search-desktop.exe)

双击运行,自动启动本地服务并用 Edge 应用模式窗口打开。窗口关闭后,后端检测到心跳超时(30s)自动优雅退出。

WebUI 版(excel-search-webui.exe)

双击运行,控制台打印访问地址并自动打开默认浏览器。

CLI 版(excel-searcher.exe)

# 基本用法(默认:不区分大小写 + 模糊匹配(关闭完整单词)+ 递归子目录 + 全部文件类型)
excel-searcher -dir <目录> -keyword <关键字>

# 输出 JSON(便于脚本处理)
excel-searcher -dir ./data -keyword 关键词 -json

# 区分大小写(默认不区分)
excel-searcher -dir ./data -keyword Phone -case-sensitive

# 完整单词匹配(默认关闭,开启后要求关键字前后均为单词边界)
excel-searcher -dir ./data -keyword 手机 -whole-word

# 仅搜索根目录,不递归子目录(默认递归)
excel-searcher -dir ./data -keyword 关键词 -include-subdirectories=false

# 按文件类型过滤:all | excel | word | csv
excel-searcher -dir ./data -keyword 关键词 -file-type excel

# 指定并发 worker 数
excel-searcher -dir ./data -keyword 关键词 -workers 16

# 查看版本
excel-searcher -version

搜索选项说明

选项 默认值 含义
区分大小写 -case-sensitive 不勾选 勾选后按大小写精确匹配;不勾选按 Unicode 大小写折叠匹配
完整单词 -whole-word 不勾选 勾选后要求关键字前后均为单词边界(非字母/数字/下划线);不勾选为模糊子串匹配
包含子目录 -include-subdirectories 勾选 勾选后递归扫描子目录;不勾选仅扫描根目录
文件类型 -file-type all all(全部支持格式)/ excel / word / csv

完整单词边界说明:边界字符为字母、数字、Unicode 组合标记与下划线。中文/日文汉字属于字母,默认不勾选完整单词(模糊子串匹配),搜索「手机」会匹配「苹果手机壳」这类内部子串;需要精确按词匹配时勾选完整单词即可。WebUI/桌面版的 HTTP 请求中,这些选项通过 options 对象传递(字段名与上文相同,布尔字段可显式传 false)。


五、配置项(环境变量)

环境变量 默认值 生效入口 说明
EXCEL_SEARCH_HOST 127.0.0.1 desktop/webui HTTP 监听地址
EXCEL_SEARCH_PORT 0(随机) desktop/webui HTTP 端口
EXCEL_SEARCH_WORKERS 8 desktop/webui/searcher 并发 worker 数(CLI 可用 -workers 覆盖)
EXCEL_SEARCH_TIMEOUT_SECONDS 600 desktop/webui 单次搜索超时
EXCEL_SEARCH_LOG_DIR logs desktop/webui 日志目录
EXCEL_SEARCH_LOG_FORMAT text 全部 日志格式:text 或 json
EXCEL_SEARCH_CACHE_DIR .cache 全部 搜索缓存目录

示例(Windows PowerShell):

$env:EXCEL_SEARCH_LOG_FORMAT = "json"
$env:EXCEL_SEARCH_WORKERS = "16"
.\bin\excel-search-desktop.exe

六、常见问题

Q:桌面版窗口一闪而过 / 白屏? 先确认 .exe 与源码同目录运行时能否生成 logs/app.log,查看日志定位。白屏多与前端样式未编译有关——确认 cmd/desktop/style.css 存在(或重新执行 make frontend)。

Q:CLI 报 Search failed? 检查 -dir 路径是否存在、是否有权限;用 -json 观察输出。搜索超时请缩小目录范围或调低并发。

Q:如何彻底清理?

make clean          # 删除 bin/、.cache/、logs/
rm -rf frontend/node_modules   # 删除前端依赖