Go 2.0发布在即,程序员有太多话要说


新智元报道

来源:go.googlesource.com

编译:三石

【新智元导读】Go 2.0预计公布,在今天HackerNews引发众多讨论,众多Bug即将填补,设计草案抢先预览。

Go语言的开发者正着手准备开发2.0版本,并从以下三个方面发布了初步的设计方案(非官方正式版),以供社区开展讨论:

  • 泛型(generics)
  • 错误处理(error handling)
  • 错误值语义(error value semantics)

Go 2.0的总体目标是解决无法扩展到大型代码库以及无法满足大型项目开发人员需求等问题。

泛型

改进目标

想必大多数用户都对Go语言的泛型会表示无奈,很多网友甚至会说“根本就没有泛型支持”。

Go 2.0的目标是通过允许带有类型参数的参数多态(parametric polymorphism)来解决编写Go库的问题。

除了预期的容器类型之外,还希望能够编写有意义的库来操作任意的map和channel值,并理想地编写能够同时操作[ ]byte和string值的多态函数。

Go的泛型必须明确记录对类型参数的约束,作为调用者和实现之间明确的强制协议。当调用者不满足这些约束或实现超出限制时,编译器需将错误清楚地报告出来。

Go中的多态性应该在编译和运行时都可以实现,这样,有关实现策略的决策就可以留给编译器来决定。这种灵活性将解决Go目前存在的一些难题。

草案设计

设计草案添加了一个新的语法,用于在类型或函数声明中引入类型参数列表,例如:

1type List(type T) []T
2
3func Keys(type K, V)(m map[K]V) []K
4

参数化声明的使用,采用普通调用语法来提供类型参数:

1var ints List(int)
2
3keys := Keys(int, string)(map[int]string{1:"one", 2: "two"})

这些示例中的概括不需要T,K和V类型:任何类型都可以。 通常,实现可能需要约束可以使用的类型。例如,我们可能想要定义一个Set(T),以列表或映射的形式实现,在这种情况下,类型T的值必须能够进行相等的比较。为了表达这一点,设计草案引入了contract的概念。contract就像一个函数体,说明了类型必须支持的操作。 例如,要声明类型T的值必须是可比较的:

1contract Equal(t T) {
2    t == t
3}

错误处理

改进目标

Go 语言的错误处理是基于明确的目的而设计的。用户应该从函数中返回所有可能的错误,并且检查/处理这些返回值。和其他语言相比,这一点可能看起来有些繁琐和不人性化。

Go 2希望错误检查更加轻量级,减少用于错误检查的Go程序文本的数量。

还希望使编写错误处理变得更方便,从而提高程序员花时间处理错误的可能性。

且错误检查和错误处理必须保持显式,即在程序文本中可见。

草案设计

草案设计引入了两种新的句法形式。

首先,它引入一个检查表达式来检查f(x, y, z)或检查err,并标记一个显式错误检查。

其次,它引入了一个定义错误处理程序的handle语句。当错误检查失败时,它将控制转移到最内层处理程序,该处理程序将控制转移到它上面的下一个处理程序,以此类推,直到处理程序执行返回语句为止。例如:

 1func CopyFile(src, dst string) error {
 2    handle err {
 3        return fmt.Errorf("copy %s %s: %v", src, dst, err)
 4    }
 5
 6    r := check os.Open(src)
 7    defer r.Close()
 8
 9    w := check os.Create(dst)
10    handle err {
11        w.Close()
12        os.Remove(dst) // (only if a check fails)
13    }
14
15    check io.Copy(w, r)
16    check w.Close()
17    return nil
18}

在不返回错误的函数中允许check/handle组合。例如,一下是一个有用却很简单的程序功能:

 1func main() {
 2    hex, err := ioutil.ReadAll(os.Stdin)
 3    if err != nil {
 4        log.Fatal(err)
 5    }
 6
 7    data, err := parseHexdump(string(hex))
 8    if err != nil {
 9        log.Fatal(err)
10    }
11
12    os.Stdout.Write(data)
13}

这么写会更简单、清晰:

1func main() {
2    handle err {
3        log.Fatal(err)
4    }
5
6    hex := check ioutil.ReadAll(os.Stdin)
7    data := check parseHexdump(string(hex))
8    os.Stdout.Write(data)
9}

错误值语义

改进目标

也许用户对于Go的程序化的err有许多问题:这是一个 RPCError吗?这是net.OpError吗?它适应net.Error的接口吗?这是os.PathError吗?

对于错误值,第一个问题,就是很难回答上述那些疑问。函数os.IsExist,os.IsNotExist,os.IsPermission和os.IsTimeout是主要问题。它们在通用性方面有两个缺陷:每个函数仅测试一种特定类型的错误,第二,每个函数只能理解非常有限数量的包类型。

第二个问题看似没什么,却也很重要:深度嵌套错误(nested error)的报告太难以阅读,并且没有留给额外的细节空间,比如程序中的相关文件位置。

针对上述存在的两个问题,Go 2首先希望能让程序的错误检查更容易,更不容易出错,以提高实际程序的错误处理和鲁棒性。其次,希望能够以标准格式打印带有附加细节的错误。

草案设计

这里有两个主要问题:错误检查和错误格式化,分别用两个不同的方案解决。需要保持与现有代码的互操作性,并允许包继续定义自身的错误类型的约束,指向定义错误实现可以满足的可选界面。

错误检查(Error inspection)

对于错误检查,设计草案遵循现有包(如github.com/pkg/errors)的规则,并为错误定义了一个可选接口,以返回错误包装链中的下一个错误:

1package errors
2
3type Wrapper interface {
4    Unwrap() error
5}

例如,上面假设的WriteError需要:

1func (e *WriteError) Unwrap() error { return e.Err }

利用这种方法,方案设计中添加了两个新函数对错误打包:

1// Is reports whether err or any of the errors in its chain is equal to target.
2func Is(err, target error) bool
3
4// As checks whether err or any of the errors in its chain is a value of type E.
5// If so, it returns the discovered value of type E, with ok set to true.
6// If not, it returns the zero value of type E, with ok set to false.
7func As(type E)(err error) (e E, ok bool)
8

错误格式(Error formatting)

对于错误格式,设计草案定义了根据错误来实现的可选接口:

1package errors
2
3type Formatter interface {
4    Format(p Printer) (next error)
5}

原文发布于微信公众号 - 新智元(AI_era)

原文发表时间:2018-08-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏工科狗和生物喵

【计算机本科补全计划】指令:计算机的语言(MIPS) Part3

正文之前 今天学的很尴尬,因为有事情,而且新认识了两个计算机学院的保研大佬,不得不感叹我找的导师之强,第一个去上交的,是被金老师推荐去的,听说是跟了目前亚洲第一...

3218
来自专栏java一日一条

编写难于测试的代码的5种方式

有一次,我在一个讲座上听到主持人问听众如何故意编写难于测试的代码。在场的小伙伴都惊呆了,因为没有任何人会故意写这种糟糕的代码。我记得他们甚至给不出一个好的答案。

1122
来自专栏Golang语言社区

无辜的goroutine

简介: 本文主要是针对一些对于goroutine的“指控”提出我自己的看法,特别是轩脉刃的一篇博客文章《论go语言中goroutine的使用》提出了gorout...

36011
来自专栏Golang语言社区

Go语言的 10 个实用技术--转

十条有用的 Go 技术   这里是我过去几年中编写的大量 Go 代码的经验总结而来的自己的最佳实践。我相信它们具有弹性的。这里的弹性是指:   某个应用需要适配...

3577
来自专栏大闲人柴毛毛

柴毛毛大话设计模式——开发常用的设计模式梳理

写在最前 本文是笔者的一点经验总结,主要介绍几种在Web开发中使用频率较高的设计模式。 本文篇幅较长,建议各位同学挑选感兴趣的设计模式阅读。 在阅读的同时,也...

4817
来自专栏python学习路

二、Python介绍

Python 是一门什么样的语言? python是一门动态解释性的强类型定义语言。 编程语言主要从以下几个角度为进行分类,编译型和解释型、静态语言和动态语言、...

3544
来自专栏魂祭心

原 Introduction to the

3569
来自专栏极客猴

基础知识 | 使用 Python 将数据写到 CSV 文件

我们从网上爬取数据,最后一步会考虑如何存储数据。如果数据量不大,往往不会选择存储到数据库,而是选择存储到文件中,例如文本文件、CSV 文件、xls 文件等。因为...

982
来自专栏C/C++基础

CVTE2016春季实习校招技术一面回忆(C++后台开发岗)

2016.3.15,参加了CVTE的技术面,很不幸,我和我的两位小伙伴均跪在了一面。先将当日的面试内容汇总如下,供后来者参考。我们三人各自也都总结了失败的原因,...

511
来自专栏葡萄城控件技术团队

C#开发人员应该知道的13件事情

本文讲述了C#开发人员应该了解到的13件事情,希望对C#开发人员有所帮助。 1. 开发过程 开发过程是错误和缺陷开始的地方。使用工具可以帮助你在发布之后,解决掉...

2209

扫码关注云+社区

领取腾讯云代金券