Go 博客
介绍 Gofix
下一个 Go 版本将在几个基本的 Go 包中包含重大的 API 更改。除非更新为使用新的 API,否则实现 HTTP 服务器处理程序、调用net.Dial
、调用os.Open
或使用 reflect 包的代码将无法构建。现在我们的版本更加稳定且频率更低,这将成为一种常见情况。这些 API 更改中的每一个都发生在不同的每周快照中,并且可能本身是可以管理的;然而,总的来说,它们代表了更新现有代码的大量手动工作。
Gofix 是一种新的工具,它减少了更新现有代码所需的工作量。它从源文件中读取程序,查找旧 API 的用法,将其重写为使用当前 API,并将程序写回文件。并非所有 API 更改都保留旧 API 的所有功能,因此 gofix 并非总能完美地完成工作。当 gofix 无法重写旧 API 的用法时,它会打印一条警告,给出用法的文件名和行号,以便开发人员检查和重写代码。Gofix 处理简单、重复、乏味的变化,以便开发人员可以专注于真正值得关注的变化。
每次我们进行重大 API 更改时,我们都会向 gofix 添加代码来处理转换,尽可能地进行机械化操作。当您更新到新的 Go 版本并且您的代码不再构建时,只需在您的源目录上运行 gofix。
您可以扩展 gofix 以支持对您自己的 API 的更改。gofix 程序是围绕称为修复程序的插件的简单驱动程序,每个插件都处理特定的 API 更改。现在,编写新的修复程序需要对 go/ast 语法树进行一些扫描和重写,通常与 API 更改的复杂程度成正比。如果您想探索,netdialFix
、osopenFix
、httpserverFix
和reflectFix
都是说明性的示例,复杂程度依次递增。
当然,我们也编写 Go 代码,我们的代码与您的代码一样受这些 API 更改的影响。通常,我们会在 API 更改的同时编写 gofix 支持,然后使用 gofix 重写主源树中的用法。我们使用 gofix 来更新其他 Go 代码库和我们的个人项目。我们甚至在需要针对新的 Go 版本构建时使用 gofix 来更新 Google 的内部源代码树。
例如,gofix 可以重写类似于fmt/print.go
中的此代码段
switch f := value.(type) {
case *reflect.BoolValue:
p.fmtBool(f.Get(), verb, field)
case *reflect.IntValue:
p.fmtInt64(f.Get(), verb, field)
// ...
case reflect.ArrayOrSliceValue:
// Byte slices are special.
if f.Type().(reflect.ArrayOrSliceType).Elem().Kind() == reflect.Uint8 {
// ...
}
// ...
}
以使其适应新的 reflect API
switch f := value; f.Kind() {
case reflect.Bool:
p.fmtBool(f.Bool(), verb, field)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
p.fmtInt64(f.Int(), verb, field)
// ...
case reflect.Array, reflect.Slice:
// Byte slices are special.
if f.Type().Elem().Kind() == reflect.Uint8 {
// ...
}
// ...
}
上面几乎每一行都以某种方式发生了变化。重写中涉及的更改非常广泛,但几乎完全是机械的,这正是计算机擅长处理的事情。
Gofix 是可能的,因为 Go 在其标准库中支持将 Go 源文件解析为语法树,以及将这些语法树打印回 Go 源代码。重要的是,Go 打印库以官方格式打印程序(通常通过 gofmt 工具强制执行),允许 gofix 对 Go 程序进行机械更改而不会导致虚假的格式更改。事实上,创建 gofmt 的关键动机之一——也许仅次于避免关于某个特定大括号应该放在哪里进行争论——是简化重写 Go 程序的工具的创建,就像 gofix 所做的那样。
Gofix 已经变得不可或缺。特别是,最近的 reflect 更改如果没有自动转换将难以接受,并且 reflect API 迫切需要重新设计。Gofix 使我们能够修复错误或完全重新思考包 API,而无需担心转换现有代码的成本。我们希望您发现 gofix 与我们一样有用和方便。
下一篇文章:Go 在 Heroku 上
上一篇文章:Godoc:记录 Go 代码
博客索引