Go 2.0 该如何满足开发者的期待?

作者 | Seth Vargo译者 | 弯月
出品 | CSDN(ID:CSDNnews)
虽然 Go 是我最喜欢的编程语言之一 , 但它远不够完美 。 在过去的 10 年里 , 我使用 Go 构建了很多小型个人项目和大型应用程序 。 自 2009 年第一版发布以来 , Go 有了很大变化 , 但我希望通过本文表达我认为 Go 仍有待改进的一些领域 。
在此之前 , 首先声明一点:我并不是在批评 Go 开发团队或个人的贡献 。 我的目的是让 Go 成为最好的编程语言 。
Go 2.0 该如何满足开发者的期待?
文章图片

现代模板引擎
Go的标准库有两个模板包:text/template 和 html/template 。 二者使用的语法大致相同 , 但 html/template 会处理实体转义和一些其他特定于 Web 的构造 。 然而不幸的是 , 对于一些高级的用例 , 这两个库都不够强大 , 依然需要进行大量开发 。

  • 编译时错误 。 与 Go本身不同 , Go 的模板包允许将整数作为字符串传递 , 但会在运行时报错 。 这意味着 , 开发人员无法依赖类型系统 , 他们需要严格测试模板中所有可能的输入 。 Go 的模板包应该支持编译时类型检查 。
  • 与Go语言一致的range子句 。 虽然我使用 Go 已有10 年之久 , 但仍然不太理解 Go 模板中 range 子句的顺序 , 因为它有时与Go是相反的 。 例如 , 如果使用两个参数 , 那么模板引擎与标准库是一致的:
{{ range $a, $b := .Items }} // [$a = 0,$b = "foo"]
for a, b := range items { // [a = 0, b ="foo"]
然而 , 当只有一个参数时 , 模板引擎就会返回值 , 而Go会返回索引:
{{ range $a := .Items }} // [$a ="foo"]
【Go 2.0 该如何满足开发者的期待?】for a := range items { // [a = 0]
Go的模板包应该与标准库相一致 。
  • 多提供标准功能 , 减少反射的使用 。 我认为大多数开发人员永远不需要使用反射 。 但是 , 如果想实现的功能超出了基本的加减法 , 那么 Go 的模板包就会强迫你使用反射 , 因为它的内置函数非常少 , 只能满足一小部分用例 。
在编写完 Consul Template(https://github.com/hashicorp/consul-template)之后 , 我明显感觉到标准的 Go 模板功能不足以满足用户的需求 。 超过一半的问题都与使用 Go 的模板语言有关 。 如今 , Consul Template 拥有 50 多个“辅助”功能 , 其中绝大多数都应该由标准模板语言提供 。
不仅仅是我遇到了这个问题 , Hugo 有一个广泛的辅助函数列表(https://gohugo.io/functions/) , 其中的绝大多数都应该由标准模板语言提供 。 即使在我最近的一个项目中 , 也无法避免使用反射 。
Go的模板语言确实需要更广泛的函数集 。
  • 条件短路 。 Go 的模板语言总是在子句中对整个条件进行求值 , 这会产生一些非常可笑的错误(直到运行时才会显示出来 。 )考虑以下情况 , 假设 $foo 可能为 nil:
{{ if( and$foo $foo.Bar) }}虽然代码看上去没问题 , 但是两个 and 条件都需要求值 , 也就是说表达式中没有短路逻辑 。 如果 $foo 为 nil , 就会引发运行时异常 。
为了解决这个问题 , 你必须分割条件子句:
{{ if$foo }} {{ if$foo.Bar }}{{ end}}Go的模板语言应该像标准库一样运行 , 在遇到第一个真值条件后就停止 。
  • 特定于 Web 的小工具 。 多年来 , 我一直是一名 Ruby on Rails 开发人员 , 我时常感叹于用 Ruby on Rails 构建漂亮的 Web 应用程序是多么容易 。 然而使用 Go 的模板语言 , 即使是最简单的任务 , 比如输出句子中的每一个单词 , 初学者也无法完成 , 尤其是与 Rails 的 Enumerable#to_sentence 相比 。

    特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。