
本文介绍使用 go 语言解析 word 文档(.docx 和 .doc)以提取全部纯文本内容的实用方法,重点讲解基于 zip/xml 解析 .docx 的原理与实现,并指出 .doc 的兼容性挑战及替代方案。
本文介绍使用 go 语言解析 word 文档(.docx 和 .doc)以提取全部纯文本内容的实用方法,重点讲解基于 zip/xml 解析 .docx 的原理与实现,并指出 .doc 的兼容性挑战及替代方案。
在 Go 生态中,原生不支持直接读取 Word 文档,但可通过第三方库或底层协议解析实现文本提取。其中,.docx 格式是开放标准(Office Open XML),本质为 ZIP 压缩包,内含结构化 XML 文件;而 .doc 是微软私有二进制格式(OLE 复合文档),解析难度高、生态支持弱。
✅ 推荐方案:优先处理 .docx.docx 文件解压后,核心文本通常位于 word/document.xml 中。以下是一个轻量级解析示例(无需引入大型依赖):
package main
import (
"archive/zip"
"encoding/xml"
"fmt"
"io"
"os"
"strings"
)
type Document struct {
Body struct {
P []Paragraph `xml:"p"`
} `xml:"body"`
}
type Paragraph struct {
R []Run `xml:"r"`
}
type Run struct {
T string `xml:"t"`
}
func extractDocxText(filename string) (string, error) {
r, err := zip.OpenReader(filename)
if err != nil {
return "", fmt.Errorf("failed to open docx: %w", err)
}
defer r.Close()
var docXML io.ReadCloser
for _, f := range r.File {
if f.Name == "word/document.xml" {
docXML, err = f.Open()
if err != nil {
return "", fmt.Errorf("failed to open document.xml: %w", err)
}
break
}
}
if docXML == nil {
return "", fmt.Errorf("document.xml not found in %s", filename)
}
defer docXML.Close()
var doc Document
if err := xml.NewDecoder(docXML).Decode(&doc); err != nil {
return "", fmt.Errorf("failed to decode XML: %w", err)
}
var sb strings.Builder
for _, p := range doc.Body.P {
for _, r := range p.R {
sb.WriteString(r.T)
}
sb.WriteString("\n")
}
return sb.String(), nil
}
func main() {
text, err := extractDocxText("example.docx")
if err != nil {
panic(err)
}
fmt.Print(text)
}⚠️ 注意事项:
- 上述代码仅提取
<t></t>标签中的文本,未处理富文本样式、页眉页脚、注释、表格嵌套等复杂结构;如需完整语义还原,建议使用成熟库如github.com/nguyenthenguyen/docx,它已封装 XML 解析、样式忽略、段落合并等逻辑。 - 对于
.doc(97–2003 二进制格式),Go 社区缺乏稳定、维护良好的原生解析器。可行替代路径包括:
• 调用系统命令(如antiword或catdoc工具)通过os/exec执行外部转换;
• 使用 LibreOffice CLI 无头模式转为.txt或.docx后再解析(适合服务端可控环境);
• 强烈建议推动上游文档统一为.docx,规避.doc技术债务。
? 总结:
对 .docx,推荐采用 nguyenthenguyen/docx 库(简洁、专注、轻量),其核心思路正是解压 ZIP + 提取并清洗 document.xml 中的文本节点;对 .doc,应评估业务必要性,优先考虑格式迁移或外部工具桥接。切勿自行逆向解析 OLE 结构——既低效又易出错。

















