Go AST解析器生成代码含多余空格/缩进,如何还原原代码?
如何从Go AST生成与原代码完全一致的源代码?
我尝试从Go程序的AST重新生成源代码,将生成的代码与原代码比对时,发现生成的代码部分位置存在多余空格。相关实现代码如下:
fs := token.NewFileSet() f, err := parser.ParseFile(fs, filename, nil, parser.ParseComments) if err != nil { log.Println(err) } cfg := printer.Config{Mode: printer.RawFormat} err = cfg.Fprint(&buffer, fs, f) if err != nil { log.Println(err) } source_code, err := os.ReadFile(filename) if err != nil { log.Println(err) } buffer_source_code := buffer.String()请问如何通过AST生成与原代码完全一致的源代码?
核心原因
Go标准库的parser.ParseFile生成的AST仅保留语法结构信息,不会存储原代码中的空格、缩进、换行等排版细节。哪怕使用printer.RawFormat,也只是禁用printer的自动格式化规则,输出的是AST对应的标准格式代码,无法还原原代码的自定义排版。
解决方案
如果需要严格还原原代码的格式,推荐使用**github.com/dave/dst**库(Dave's Syntax Tree),它扩展了标准AST,在解析时会保留原代码的格式信息,修改AST后也能输出与原代码格式完全一致的代码。
步骤1:安装依赖
go get github.com/dave/dst go get github.com/dave/dst/dstutil
步骤2:修改实现代码
package main import ( "bytes" "log" "os" "github.com/dave/dst" "github.com/dave/dst/dstutil" ) func main() { filename := "your-target-file.go" // 使用dst解析文件,保留格式信息 f, err := dstutil.ParseFile(filename, nil, dstutil.ParseComments) if err != nil { log.Println(err) return } // 若需要对AST进行修改操作,在此处执行 // 生成与原格式一致的代码 var buffer bytes.Buffer err = dst.Fprint(&buffer, f) if err != nil { log.Println(err) return } bufferSourceCode := buffer.String() // 读取原代码用于对比 sourceCode, err := os.ReadFile(filename) if err != nil { log.Println(err) return } // 此时bufferSourceCode与原代码格式完全一致 }
补充说明
如果你的场景不需要修改AST,只是单纯验证,直接读取原文件即可;但如果需要修改AST后保留原代码格式,dst是目前最可靠的方案。标准库的printer和go/format都无法实现严格的原格式还原,因为它们依赖的标准AST不包含排版信息。
内容的提问来源于stack exchange,提问作者jaintapauljp
相关产品推荐
相关产品推荐

