Go 2 中你最期待什么功能?

Posted Go语言中文网

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go 2 中你最期待什么功能?相关的知识,希望对你有一定的参考价值。

我仍然把Go模板中的范围子句的顺序弄得一团糟,因为它有时与Go本身的顺序是相反的。对于两个参数,模板引擎与标准库相匹配。

正如许多人所指出的那样,这个特性将出现在开发人员已经很多年了,我真的很喜欢建立漂亮的网络应用程序是如此简单。使用Go的模板语言,即使是最简单的任务 - 例如将一个项目列表打印成一个句子 - 对于初学者来说也是难以企及的,特别是与Rails的Enumerable#to_sentence的相比。

所有这些现有的上游包都可以选择实现该接口。然后,作为库作者,我可以选择接受一个接口log.StructuredLogger,实现者可以做出自己的选择:

func WithLogger(l log.StructuredLogger) Option 
  return func(f *Foo) *Foo 
    f.logger = l
    return f
  

我把这样一个接口的草图快速勾勒了出来。

// StructuredLogger is an interface for structured logging.
type StructuredLogger interface 
  // Log logs a message.
  Log(message string, fields ...LogField)

  // LogAt logs a message at the provided level. Perhaps we could also have
  // Debugf, Infof, etc, but I think that might be too limiting for the standard
  // library.
  LogAt(level LogLevel, message string, fields ...LogField)

  // LogEntry logs a complete log entry. See LogEntry for the default values if
  // any fields are missing.
  LogEntry(entry *LogEntry)


// LogLevel is the underlying log level.
type LogLevel uint8

// LogEntry represents a single log entry.
type LogEntry struct 
  // Level is the log level. If no level is provided, the default level of
  // LevelError is used.
  Level LogLevel

  // Message is the actual log message.
  Message string

  // Fields is the list of structured logging fields. If two fields have the same
  // Name, the later one takes precedence.
  Fields []*LogField


// LogField is a tuple of the named field (a string) and its underlying value.
type LogField struct 
  Name  string
  Value interface

围绕着实际的接口会是什么样子,如何最小化分配,以及如何最大化兼容性,有很多讨论,但目标是定义一个其他日志库可以轻松实现的接口。

在我的Ruby时代,有大量的Ruby版本管理器,每个都有自己的dotfile名称和语法。Fletcher Nichol设法说服了这些Ruby版本管理器的所有维护者,使其标准化为.ruby-version,只需写一个gist[27]。我希望我们能在Go 社区中使用结构化日志记录做类似的事情。

多错误处理

有很多情况,特别是对于后台工作或周期性任务,系统可能会并行处理一些事情或在出现错误时继续处理。在这些情况下,返回一个多重错误是有帮助的。在标准库中没有对处理错误集合的内置支持。

围绕多错误处理有清晰简洁的标准库定义,可以统一社区,减少错误处理不当的风险,正如我们看到的错误包装(wrap)和解包(unwrap)。

针对 JSON Marshal的error

说到error,你知道吗,将error类型嵌入到一个结构字段中,然后将该结构作为JSON进行marshal,将 "error"字段marshal为?

// https://play.golang.org/p/gl7BPJOgmjr
package main

import (
  "encoding/json"
  "fmt"
)

type Response1 struct 
  Err error `json:"error"`


func main() 
  v1 := &Response1Err: fmt.Errorf("oops")
  b1, err := json.Marshal(v1)
  if err != nil 
    panic(err)
  

  // got: "error":
  // want: "error": "oops"
  fmt.Println(string(b1))

至少对于内置的errorString类型,Go应该为.Error()的结果进行marshal。另外,对于Go 2.0来说,当试图marshal一个没有实现自定义marshal逻辑的error类型时,JSON marshal会返回一个错误。

标准库中不再有公共变量

仅举一个例子,http.DefaultClienthttp.DefaultTransport都是具有共享状态的全局变量。http.DefaultClient没有配置超时,这使得DOS你自己的服务和创造瓶颈变得很容易。许多软件包都会突变,http.DefaultClienthttp.DefaultTransport,这可能会浪费开发者数天的资源来追踪错误。

Go 2.0应该把这些东西变成私有的,并通过一个函数调用来公开它们,返回有关变量的唯一分配。另外,Go 2.0还可以实现 "冻结 "的全局变量,这样它们就不能被其他包所改变。

从软件供应链的角度来看,我也担心这类问题。如果我可以开发一个有用的包,秘密地修改http.DefaultTransport,使用一个自定义的RoundTripper,将你的所有流量通过我的服务器输送出去,那将是一个非常糟糕的瞬间。

对缓冲渲染器的本地支持

这更像是一个"不为人所知或有据可查的事情"。大多数示例(包括 Go 文档中的示例)都鼓励执行以下操作,以便通过 Web 请求对 JSON 进行marshal或渲染 html

func toJSON(w http.ResponseWriter, i interface) 
  if err := json.NewEncoder(w).Encode(i); err != nil 
    http.Error(w, "oops", http.StatusInternalServerError)
  


func toHTML(w http.ResponseWriter, tmpl string, i interface) 
  if err := templates.ExecuteTemplate(w, tmpl, i); err != nil 
    http.Error(w, "oops", http.StatusInternalServerError)
  

然而,对于这两种情况,如果i足够大,有可能在发送第一个字节(和200状态码)后,编码/执行失败。在这一点上,请求是无法恢复的,因为你无法改变响应代码。

大体上被接受的缓解方案是先渲染,然后复制到w。这仍然会有很小的出错空间(由于连接问题导致向w写入失败),但它确保在发送第一个字节之前,编码/执行是成功的。然而,在每个请求中分配一个字节片是很昂贵的,所以你通常会使用缓冲池[28]

这种方法非常冗长,并将许多不必要的复杂性推给实现者。相反,如果 Go能自动处理此缓冲池管理,可能会使用EncodePooled等函数,那就更好了。

结束语

Go仍然是我最喜欢的编程语言之一,这就是为什么我觉得可以强调这些批评的原因。与任何编程语言一样,Go也在不断发展。你认为这些是好主意吗?还是说它们是糟糕的建议?请在Twitter[29]上告诉我。

参考资料
[1]

What I\'d like to see in Go 2.0: https://www.sethvargo.com/what-id-like-to-see-in-go-2

[2]

Learning Chef: https://www.amazon.com/Learning-Chef-Configuration-Management-Automation/dp/1491944935

[3]

text/template: https://pkg.go.dev/text/template

[4]

html/template: https://pkg.go.dev/html/template

[5]

Consul Template: https://github.com/hashicorp/consul-template

[6]

Hugo: https://gohugo.io/

[7]

相当广泛的辅助函数列表: https://gohugo.io/functions/

[8]

Exposure Notification: https://g.co/ens

[9]

无法逃脱反射: https://github.com/google/exposure-notifications-verification-server/blob/0ec489ba95137d5be10e1617d1dcdc2d1ee6e5e9/pkg/render/renderer.go#L232-L280

[10]

Go 1.18: https://tip.golang.org/doc/go1.18#text/template

[11]

改善 for-loop 人体工程学设计: https://github.com/golang/go/issues/24282

[12]

在每次迭代中重新定义范围循环变量: https://github.com/golang/go/issues/20733

[13]

会通过统一的伪随机来选择case的: https://golang.org/ref/spec#Select_statements

[14]

log: https://pkg.go.dev/log

[15]

Go 中不乏结构化日志库: https://www.client9.com/logging-packages-in-golang/

[16]

apex/log: https://github.com/apex/log

[17]

go-kit/log: https://github.com/go-kit/kit/tree/master/log

[18]

golang/glog: https://github.com/golang/glog

[19]

hashicorp/go-hclog: https://github.com/hashicorp/go-hclog

[20]

inconshreveable/log15: https://github.com/inconshreveable/log15

[21]

rs/zerolog: https://github.com/rs/zerolog

[22]

sirupsen/logrus: https://github.com/sirupsen/logrus

[23]

uber/zap: https://github.com/uber-go/zap

[24]

go-retry: https://github.com/sethvargo/go-retry

[25]

go-envconfig: https://github.com/sethvargo/go-envconfig

[26]

go-githubactions: https://github.com/sethvargo/go-githubactions

[27]

gist: https://gist.github.com/fnichol/1912050

[28]

使用缓冲池: https://github.com/google/exposure-notifications-verification-server/blob/08797939a56463fe85f0d1b7325374821ee31448/pkg/render/html.go#L65-L91

[29]

Twitter: https://twitter.com/sethvargo



推荐阅读

  • Go 原生并发原语和最佳实践

  • 福利

    我为大家整理了一份从入门到进阶的Go学习资料礼包,包含学习建议:入门看什么,进阶看什么。关注公众号 「polarisxu」,回复 ebook 获取;还可以回复「进群」,和数万 Gopher 交流学习。

    iOS 14四大新功能:哪个是你最期待的?




    iOS 14 可能不是我们所见过的最大的 iOS 更新,但是它的确提供了粉丝多年来一直想要的某些功能。接下来我们就来看看在 iOS 14 中,用户期待多年的四大功能。

    ◎ 重新设计的主屏幕
    iOS 中的小部件通常运行良好,但在 iOS 13 及更早版本中,它们被锁定在主屏幕左侧的“今日”视图中。在 iOS 14 中,今日视图仍然保留,但现在也可以将小部件放置在主屏幕上。

    iOS 14四大新功能:哪个是你最期待的?

    ◎ 画中画
    画中画功能虽然不是什么新鲜的功能,但是几乎在每一版 iOS 的愿望清单上,都可以看到这一诉求。我们在电话上查找其他内容时无法继续查看视频,这是糟糕的用户体验。
    但是在 iOS 14 中,苹果扩展了对画中画的支持。只要 iPhone 屏幕足够大,就可以在屏幕上其它任何地方播放视频。
    ◎ 来电和 Siri 不会占据整个屏幕
    在 iOS 13 及更早版本中,没有什么事情会打扰我们在屏幕上所做的一切,但是来电和 Siri 请求是会产生影响的。在 iOS 14 中,来电将在屏幕顶部显示,可以进行拒绝,接听或忽略等操作。

    iOS 14四大新功能:哪个是你最期待的?

    另一方面,Siri 在屏幕底部也会显示为一个小圆圈,而不是覆盖所有内容。
    ◎ 选择默认应用
    现在 iOS 14 用户可以选择他们喜欢的任何 Web 浏览器和电子邮件应用了。但是在 iOS 13 中,并不能实现。
    在 iOS 14 中,用户可以像在 Mac 上一样在 iPhone 上至少为浏览器和邮件应用选择默认应用了。


    —— 推荐阅读 ——








    (商务合作请联系:lin.chen@office.feng.com)

     你有「在看」吗 ?

    以上是关于Go 2 中你最期待什么功能?的主要内容,如果未能解决你的问题,请参考以下文章

    JS大道至简---来看看JS中你最熟悉的变量和数值的知识吧

    未来五大疯狂科技,选一个你最期待的!

    Go基础之--位操作中你所不知道的用法

    八一建军节阅兵,你最期待哪款战机梯队飞跃天安门,歼-20隐身战斗机如何

    八一建军节阅兵,你最期待哪款战机梯队飞跃天安门,歼-20隐身战斗机如何

    python开源框架,你最中意哪一个?