Go 1 Release Notes

Introduction to Go 1

Go version 1, Go 1 for short, defines a language and a set of core libraries that provide a stable foundation for creating reliable products, projects, and publications.

Go 1的驱动动力在于其用户的稳定性. 人们应该能够编写Go程序,并期望它们能够在多年的时间内(包括在Google App Engine这样的生产环境中)继续编译和运行而不会发生变化. 同样,人们应该能够撰写有关Go的书,能够说出该书所描述的Go版本,并且该版本号在以后仍然有意义.

在Go 1中编译的代码几乎没有例外,应该继续编译并在该版本的整个生命周期中运行,即使我们发布更新和错误修复程序(例如Go 1.1、1.2等)也是如此. 除关键修复程序外,对Go 1后续发行版的语言和库进行的更改可能会添加功能,但不会破坏现有的Go 1程序. Go 1兼容性文档更详细地说明了兼容性准则.

Go 1代表了今天使用的Go,而不是对该语言的全面重新思考. 我们避免了设计新功能,而是专注于清理问题和不一致之处并提高可移植性. 我们已经考虑了一段时间,对Go语言和程序包进行了许多更改,并对其进行了原型制作,但并未发布,主要是因为它们很重要且向后不兼容. Go 1是将它们发布的机会,这从长远来看是有帮助的,但也意味着Go 1引入了旧程序的不兼容性. 幸运的是, go fix工具可以自动执行使程序达到Go 1标准所需的大部分工作.

本文档概述了Go 1中的主要更改,这些更改将影响程序员更新现有代码. 它的参考点是以前的版本r60(标记为r60.3). 它还说明了如何从r60更新代码以在Go 1下运行.

Changes to the language

Append

通过append预声明的可变参数函数,可以轻松地通过在最后添加元素来增加切片. 通常的用法是在生成输出时将字节添加到字节片的末尾. 但是, append没有提供将字符串追加到[]byte ,这是另一种常见情况.

    greeting := []byte{}
    greeting = append(greeting, []byte("hello ")...)

类似于copy的类似属性,Go 1允许将字符串直接(按字节)附加到字节片上,从而减少了字符串和字节片之间的摩擦. 不再需要转换:

    greeting = append(greeting, "world"...)

更新 :这是一项新功能,因此无需更改现有代码.

Close

close预先声明的功能为发送方提供了一种机制,可以发出信号通知不再发送任何值. 这for在通道上实现for range循环很重要,在其他情况下也很有帮助. 部分是设计使然,部分是因为否则可能会发生竞争状况,因此该类仅用于在通道上发送的goroutine,而不用于goroutine接收数据. 但是,在Go 1之前,没有进行编译时检查是否正确使用了close .

为了弥合这一差距,Go 1至少部分禁止在仅接收通道上close . 试图关闭这样的通道是编译时错误.

    var c chan int
    var csend chan<- int = c
    var crecv <-chan int = c
    close(c)     // legal
    close(csend) // legal
    close(crecv) // illegal

更新 :尝试关闭仅接收通道的现有代码即使在Go 1之前也是错误的,应予以修复. 编译器现在将拒绝此类代码.

Composite literals

在Go 1中,数组,切片或映射类型的复合文字可以忽略元素的初始化程序的类型说明(如果它们是指针类型). 此示例中的所有四个初始化都是合法的; 在Go 1之前,最后一个是非法的.

    type Date struct {
        month string
        day   int
    }
    // Struct values, fully qualified; always legal.
    holiday1 := []Date{
        Date{"Feb", 14},
        Date{"Nov", 11},
        Date{"Dec", 25},
    }
    // Struct values, type name elided; always legal.
    holiday2 := []Date{
        {"Feb", 14},
        {"Nov", 11},
        {"Dec", 25},
    }
    // Pointers, fully qualified, always legal.
    holiday3 := []*Date{
        &Date{"Feb", 14},
        &Date{"Nov", 11},
        &Date{"Dec", 25},
    }
    // Pointers, type name elided; legal in Go 1.
    holiday4 := []*Date{
        {"Feb", 14},
        {"Nov", 11},
        {"Dec", 25},
    }

Updating: This change has no effect on existing code, but the command gofmt -s applied to existing source will, among other things, elide explicit element types wherever permitted.

Goroutines during init

旧语言定义了在初始化过程中执行的go语句会创建goroutine,但是它们直到整个程序初始化完成后才开始运行. 这在许多地方引入了笨拙性,实际上限制了init构造的实用性:如果在初始化期间可能有另一个包使用该库,则该库将被迫避免使用goroutines. 进行此设计是出于简单和安全的原因,但是,随着我们对语言的信心增强,似乎没有必要. 在初始化期间运行goroutine不会比在正常执行期间运行goroutine复杂或不安全.

在Go 1中,可以从init例程和全局初始化表达式中调用使用goroutine的代码,而不会引入死锁.

var PackageGlobal int

func init() {
    c := make(chan int)
    go initializationFunction(c)
    PackageGlobal = <-c
}

更新 :这是一项新功能,因此现有代码无需更改,尽管依赖于goroutine的代码有可能在main断开之前未启动. 标准存储库中没有这样的代码.

The rune type

语言规范允许int类型为32或64位宽,但是即使在64位平台上,当前的实现也将int设置为32位. 在64位平台上最好将int为64位. (对大型切片进行索引会产生重要的后果.)但是,此更改将在使用旧语言处理Unicode字符时浪费空间,因为int类型还用于保存Unicode代码点:每个代码点将浪费额外的32位存储空间如果int从32位增加到64位.

为了使更改为64位int可行,Go 1引入了一个新的基本类型rune ,以表示单个Unicode代码点. 它是int32的别名,类似于byte作为uint8的别名.

现在,诸如'a''語' '\u0345''\u0345'类的字符文字具有默认类型rune ,类似于具有默认类型float64 1.0 . 除非另外指定,否则初始化为字符常量的变量将具有rune类型.

库已更新为在适当时使用rune而不是int . 例如,函数unicode.ToLower和亲戚现在可以使用并返回rune .

    delta := 'δ' // delta has type rune.
    var DELTA rune
    DELTA = unicode.ToUpper(delta)
    epsilon := unicode.ToLower(DELTA + 1)
    if epsilon != 'δ'+1 {
        log.Fatal("inconsistent casing for Greek")
    }

更新 :大多数源代码将不受此影响,因为来自:=初始化程序的类型推断会静默引入新类型,并从那里传播. 某些代码可能会得到类型错误,而普通的转换将解决该错误.

The error type

Go 1引入了一个新的内置类型error ,其具有以下定义:

    type error interface {
        Error() string
    }

由于这种类型的后果全部在软件包库中,因此将在下面进行讨论.

Deleting from maps

用旧的语言,要从映射m删除键为k的条目,请写一条语句,

    m[k] = value, false

This syntax was a peculiar special case, the only two-to-one assignment. It required passing a value (usually ignored) that is evaluated but discarded, plus a boolean that was nearly always the constant false. It did the job but was odd and a point of contention.

在Go 1中,语法已消失; 而是有一个新的内置函数delete . 通话

    delete(m, k)

将删除由表达式m[k]检索的地图条目. 没有返回值. 删除不存在的条目是无操作.

更新 :运行go fix可以很明显地将忽略的值安全地从程序中丢弃,并且false引用预定义的布尔常量时,将运行m[k] = value, false形式的表达式转换为delete(m, k) . 该修复工具将标记该语法的其他用途,以供程序员检查.

Iterating in maps

旧的语言规范没有定义地图的迭代顺序,实际上,它在各个硬件平台上都不同. 这导致对地图进行迭代的测试是脆弱且不可移植的,具有令人不愉快的特性,即测试可能始终在一台计算机上通过而在另一台计算机上中断.

在Go 1中,即使使用同一映射多次运行同一循环,使用for range语句遍历一个映射时访问元素的顺序也被定义为不可预测. 代码不应假定以任何特定顺序访问元素.

这种变化意味着依赖于迭代顺序的代码很可能会提前中断,并在问题出现之前很长时间就被修复. 同样重要的是,即使程序正在使用范围循环从映射中选择元素,它也允许映射实现确保更好的映射平衡.

    m := map[string]int{"Sunday": 0, "Monday": 1}
    for name, value := range m {
        // This loop should not assume Sunday will be visited first.
        f(name, value)
    }

更新 :这是工具无法提供帮助的一项更改. 现有的大多数代码将不受影响,但是某些程序可能会中断或行为异常; 我们建议您手动检查地图上的所有范围语句,以确保它们不依赖于迭代顺序. 标准存储库中有一些这样的例子. 他们已经修复. 请注意,依赖于未指定的迭代顺序已经是不正确的. 此更改编码了不可预测性.

Multiple assignment

语言规范长期以来一直保证在赋值任何左侧表达式之前都会先评估右侧表达式. 为了保证可预测的行为,Go 1进一步完善了规范.

如果赋值语句的左侧包含需要求值的表达式,例如函数调用或数组索引操作,则将在分配任何变量值之前使用通常的从左至右规则来完成这些操作. 评估完所有内容后,实际分配将按从左到右的顺序进行.

这些示例说明了行为.

    sa := []int{1, 2, 3}
    i := 0
    i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2

    sb := []int{1, 2, 3}
    j := 0
    sb[j], j = 2, 1 // sets sb[0] = 2, j = 1

    sc := []int{1, 2, 3}
    sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)

更新 :这是工具无法提供帮助但不太可能损坏的一种更改. 此更改不会破坏标准存储库中的代码,并且依赖于先前未指定行为的代码已经不正确.

Returns and shadowed variables

一个常见的错误是在分配给与结果变量同名但不相同的变量的变量后,使用return (不带参数). 这种情况称为阴影 :结果变量已被内部范围中声明的具有相同名称的另一个变量阴影.

在具有命名返回值的函数中,如果任何命名的返回值在return语句的位置被遮盖,Go 1编译器将禁止不带参数的return语句. (这不是规范的一部分,因为这是我们仍在探索的领域;这种情况类似于编译器拒绝不以显式return语句结尾的函数.)

该函数隐式返回一个阴影返回值,并且将被编译器拒绝:

    func Bug() (i, j, k int) {
        for i = 0; i < 5; i++ {
            for j := 0; j < 5; j++ { // Redeclares j.
                k += i*j
                if k > 100 {
                    return // Rejected: j is shadowed here.
                }
            }
        }
        return // OK: j is not shadowed here.
    }

更新 :以这种方式返回影子的代码将被编译器拒绝,并且需要手工进行修复. 标准存储库中出现的少数情况多数是错误.

Copying structs with unexported fields

旧的语言不允许程序包复制包含属于其他程序包的未导出字段的结构值. 但是,方法接收者有一个例外. 同样, copyappend的实现从未遵守该限制.

Go 1 will allow packages to copy struct values containing unexported fields from other packages. Besides resolving the inconsistency, this change admits a new kind of API: a package can return an opaque value without resorting to a pointer or interface. The new implementations of time.Time and reflect.Value are examples of types taking advantage of this new property.

例如,如果包p包含定义,

    type Struct struct {
        Public int
        secret int
    }
    func NewStruct(a int) Struct {  // Note: not a pointer.
        return Struct{a, f(a)}
    }
    func (s Struct) String() string {
        return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
    }

导入p的包可以随意分配和复制p.Struct类型的值. 在幕后,未分配的字段将被分配和复制,就像它们已被导出一样,但是客户端代码永远不会意识到它们. 代码

    import "p"

    myStruct := p.NewStruct(23)
    copyOfMyStruct := myStruct
    fmt.Println(myStruct, copyOfMyStruct)

将显示该结构的secret字段已被复制到新值.

更新 :这是一项新功能,因此无需更改现有代码.

Equality

在Go 1之前,该语言未在struct和array值上定义相等性. 这意味着,除其他外,结构和数组不能用作映射键. 另一方面,Go确实在函数和映射值上定义了相等性. 当存在闭包时(两个闭包相等吗?),函数相等是有问题的,而映射相等比较的是指针,而不是映射内容,通常不是用户想要的.

Go 1解决了这些问题. 首先,可以比较结构和数组的相等性和不相等性( ==!= ),因此可以用作映射键,前提是它们是由也定义了相等性的元素组成的,使用逐元素比较.

    type Day struct {
        long  string
        short string
    }
    Christmas := Day{"Christmas", "XMas"}
    Thanksgiving := Day{"Thanksgiving", "Turkey"}
    holiday := map[Day]bool{
        Christmas:    true,
        Thanksgiving: true,
    }
    fmt.Printf("Christmas is a holiday: %t\n", holiday[Christmas])

其次,Go 1删除了函数值的相等性定义,但与nil进行比较除外. 最后,除了与nil进行比较外,地图相等性也消失了.

请注意,对于片来说,相等性仍然是未定义的,因此通常无法进行计算. 还要注意的是有序比较运算符( < <= > >= )仍在未定义结构和数组.

更新 :结构和数组相等是一项新功能,因此无需更改现有代码. 依赖函数或映射相等性的现有代码将被编译器拒绝,并且需要手工进行修复. 很少有程序会受到影响,但此修复程序可能需要重新设计.

The package hierarchy

Go 1解决了旧标准库中的许多缺陷,并清理了许多程序包,使它们在内部更一致且更易于移植.

本节介绍如何在Go 1中重新排列软件包.一些已移动,一些已重命名,一些已删除. 新软件包将在后面的部分中介绍.

The package hierarchy

Go 1具有重新排列的包层次结构,该包层次结构将相关项目分组为子目录. 例如, utf8utf16现在占据unicode子目录. 此外, 有些软件包已移到code.google.com/p/go存储库中,而其他 软件包则被彻底删除.

旧路 新路

asn1 encoding/asn1
csv encoding/csv
gob encoding/gob
json encoding/json
xml encoding/xml

exp/template/html html/template

big math/big
cmath math/cmplx
rand math/rand

http net/http
http/cgi net/http/cgi
http/fcgi net/http/fcgi
http/httptest net/http/httptest
http/pprof net/http/pprof
mail net/mail
rpc net/rpc
rpc/jsonrpc net/rpc/jsonrpc
smtp net/smtp
url net/url

exec os/exec

scanner text/scanner
tabwriter text/tabwriter
template text/template
template/parse text/template/parse

utf8 unicode/utf8
utf16 unicode/utf16

请注意,旧的cmathexp/template/html软件包的软件包名称已更改为cmplxtemplate .

更新 :运行go fix将更新保留在标准存储库中的软件包的所有导入和软件包重命名. 导入不再位于标准存储库中的软件包的程序将需要手动进行编辑.

The package tree exp

由于它们不是标准化的,因此exp目录下的软件包在标准的Go 1发行版中将不可用,尽管对于希望使用它们的开发人员来说,它们将以源代码形式在存储库中提供.

在Go 1发布时,有几个软件包已经移到exp之下:

(†EscapeStringUnescapeString类型保留在包html ).

所有这些软件包都可以以相同的名称使用,前缀为exp/exp/ebnf等.

同样, utf8.String类型已移至其自己的包exp/utf8string .

最后, gotype命令现在位于exp/gotype ,而ebnflint现在位于exp/ebnflint . 如果已安装,则它们现在位于$GOROOT/bin/tool .

更新 :使用exp软件包的代码将需要手动更新,或者从具有exp可用的安装中进行编译. go fix工具或编译器会抱怨这种用法.

The package tree old

因为不推荐使用,所以old目录下的软件包在标准Go 1发行版中将不可用,尽管对于希望使用它们的开发人员来说,它们将以源代码形式提供.

新位置中的软件包是:

更新 :使用old软件包的代码将需要手动更新,或者从具有old版本的安装中进行编译. 在go fix工具会发出警告等用途.

Deleted packages

Go 1会直接删除几个软件包:

以及命令gotry .

更新 :使用container/vector代码应更新为直接使用切片. 有关一些建议,请参见Go语言社区Wiki . 使用其他软件包(应该几乎为零)的代码将需要重新考虑.

Packages moving to subrepositories

Go 1已将许多软件包移至其他存储库,通常是主Go存储库的子存储 . 下表列出了旧的和新的导入路径:

Old New

crypto/bcrypt code.google.com/p/go.crypto/bcrypt
crypto/blowfish code.google.com/p/go.crypto/blowfish
crypto/cast5 code.google.com/p/go.crypto/cast5
crypto/md4 code.google.com/p/go.crypto/md4
crypto/ocsp code.google.com/p/go.crypto/ocsp
crypto/openpgp code.google.com/p/go.crypto/openpgp
crypto/openpgp/armor code.google.com/p/go.crypto/openpgp/armor
crypto/openpgp/elgamal code.google.com/p/go.crypto/openpgp/elgamal
crypto/openpgp/errors code.google.com/p/go.crypto/openpgp/errors
crypto/openpgp/packet code.google.com/p/go.crypto/openpgp/packet
crypto/openpgp/s2k code.google.com/p/go.crypto/openpgp/s2k
crypto/ripemd160 code.google.com/p/go.crypto/ripemd160
crypto/twofish code.google.com/p/go.crypto/twofish
crypto/xtea code.google.com/p/go.crypto/xtea
exp/ssh code.google.com/p/go.crypto/ssh

image/bmp code.google.com/p/go.image/bmp
image/tiff code.google.com/p/go.image/tiff

net/dict code.google.com/p/go.net/dict
net/websocket code.google.com/p/go.net/websocket
exp/spdy code.google.com/p/go.net/spdy

encoding/git85 code.google.com/p/go.codereview/git85
patch code.google.com/p/go.codereview/patch

exp/wingui code.google.com/p/gowingui

更新 :运行go fix将更新这些软件包的导入,以使用新的导入路径. 依赖于这些软件包的安装将需要使用go get命令进行安装.

Major changes to the library

This section describes significant changes to the core libraries, the ones that affect the most programs.

The error type and errors package

os.Error在包os的放置大部分是历史性的:实现包os时首先出现错误,并且在当时它们与系统有关. 从那时起,很明显,错误比操作系统更根本. 例如,最好在os依赖的软件包中使用Errors ,例如syscall . 另外,在os中出现Error会导致对os许多依赖关系,否则这些依赖关系将不存在.

Go 1通过引入内置error接口类型和包含实用程序功能的单独errors包(类似于bytesstrings )解决了这些问题. 它将os.NewError替换为errors.New ,从而使错误在环境中的位置更加重要.

因此,广泛使用的String方法不会导致error接口的意外满足,因此error接口使用该方法的名称Error

    type error interface {
        Error() string
    }

fmt库会自动调用Error ,就像对String所做的那样,以便于打印错误值.

type SyntaxError struct {
    File    string
    Line    int
    Message string
}

func (se *SyntaxError) Error() string {
    return fmt.Sprintf("%s:%d: %s", se.File, se.Line, se.Message)
}

所有标准软件包均已更新,可以使用新界面. 旧的os.Error消失了.

一个新的包errors包含函数

func New(text string) error

将字符串变成错误. 它替换了旧的os.NewError .

    var ErrSyntax = errors.New("syntax error")

更新 :运行go fix将更新几乎所有受更改影响的代码. 使用String方法定义错误类型的代码将需要手动更新,以将方法重命名为Error .

System call errors

早于os.Error (以及几乎所有其他内容)的旧syscall程序包将错误作为int值返回. 反过来, os包转发了许多此类错误,例如EINVAL ,但在每个平台上使用了一组不同的错误. 此行为令人不愉快且无法携带.

在围棋1, syscall封装,而不是返回一个error的系统调用错误. 在Unix上,实现是通过syscall.Errno类型完成的,该类型可以满足error并替换旧的os.Errno .

影响os.EINVAL和亲属的变化在其他地方描述.

更新 :运行go fix将更新几乎所有受更改影响的代码. 无论如何,大多数代码应使用os软件包而不是syscall ,因此不会受到影响.

Time

在编程语言中,良好的支持始终是时间的挑战. 旧的Go time包具有int64单位,没有实类型安全,并且绝对时间和持续时间之间没有区别.

因此,Go 1库中最全面的更改之一就是对time包进行了彻底的重新设计. 现在不再有整数整数纳秒作为int64以及用于处理人类单位(例如小时和年)的单独的*time.Time类型,现在有两种基本类型: time.Time (一个值,因此*消失了) ,代表时刻. 和time.Duration ,代表一个间隔. 两者都具有纳秒分辨率. Time可以代表古代过去和遥远的未来的任何时间,而Duration只能跨越正负约290年. 在这些类型上有一些方法,以及许多有用的预定义的恒定持续时间,例如time.Second .

在这些新方法中,有诸如Time.AddTime.Sub类的东西,其中Time.Add将一个Duration添加到一个TimeTime.Sub减去两个Times来生成一个Duration .

最重要的语义变化是Unix时代(1970年1月1日)现在仅与提到Unix的那些函数和方法有关: time.Unix以及Time类型的UnixUnixNano方法. 特别地, time.Now返回time.Time值,而不是,在旧的API,整数纳秒自Unix纪元计数.

// sleepUntil sleeps until the specified time. It returns immediately if it's too late.
func sleepUntil(wakeup time.Time) {
    now := time.Now() // A Time.
    if !wakeup.After(now) {
        return
    }
    delta := wakeup.Sub(now) // A Duration.
    fmt.Printf("Sleeping for %.3fs\n", delta.Seconds())
    time.Sleep(delta)
}

新的类型,方法和常量已通过所有使用时间的标准包(例如os及其文件时间戳的表示)传播.

更新go fix工具将更新旧time包的许多用法以使用新的类型和方法,尽管它不会替换表示每秒纳秒的1e9值. 另外,由于某些值的类型发生变化,因此修复工具重写的某些表达式可能需要进一步的手工编辑; 在这种情况下,重写将包括用于旧功能的正确功能或方法,但类型可能错误或需要进一步分析.

Minor changes to the library

本节描述较小的更改,例如对不那么常用的软件包的更改,或影响到少数几个不需要运行go fix更改. 此类别包括Go 1中的新软件包.它们共同提高了可移植性,使行为规范化,并使界面更加现代和类似于Go.

The archive/zip package

在Go 1中, *zip.Writer不再具有Write方法. 它的存在是一个错误.

更新 :受影响的代码很少,编译器会捕获它们,必须手动对其进行更新.

The bufio package

在Go 1中, bufio.NewReaderSizebufio.NewWriterSize函数不再针对无效尺寸返回错误. 如果参数大小太小或无效,则会对其进行调整.

更新 :运行go fix将更新将错误分配给_的调用. 未固定的调用将被编译器捕获,并且必须手动进行更新.

The compress/flate, compress/gzip and compress/zlib packages

在Go 1中,如果它们采用压缩级别,则NewWriterXxx函数compress/flatecompress/gzipcompress/zlib均返回(*Writer, error) ,否则返回*Writer . 软件包gzipCompressorDecompressor类型已重命名为WriterReader . 包flateWrongValueError型已被删除.

更新 Running go fix将更新旧名称和将错误分配给_的调用. 未固定的调用将被编译器捕获,并且必须手动进行更新.

The crypto/aes and crypto/des packages

在Go 1中,已删除了Reset方法. Go不能保证不会复制内存,因此此方法具有误导性.

特定于密码的类型*aes.Cipher*des.Cipher*des.TripleDESCipher已被删除,以支持cipher.Block .

正在更新 :删除对"重置"的调用. 将特定密码类型的使用替换为cipher.Block.

The crypto/elliptic package

在Go 1中,已将elliptic.Curve设置为允许替代实现的接口. 曲线参数已移至elliptic.CurveParams结构.

更新*elliptic.Curve现有用户将需要更改为简单的elliptic.Curve . 调用MarshalUnmarshalGenerateKey现在是crypto/elliptic函数,需要使用elliptic.Curve作为其第一个参数.

The crypto/hmac package

在Go 1中,哈希专用功能(例如hmac.NewMD5已从crypto/hmac删除. 相反, hmac.New需要一个返回的功能hash.Hash ,如md5.New .

更新 :运行go fix将执行所需的更改.

The crypto/x509 package

在Go 1中, crypto/x509CreateCertificate函数和CreateCRL方法已更改为采用interface{} ,而以前它们采用的是*rsa.PublicKey*rsa.PrivateKey . 这将允许将来实现其他公钥算法.

正在更新 :无需更改.

The encoding/binary package

在Go 1中, binary.TotalSize函数已由Size代替,它使用interface{}参数而不是reflect.Value .

更新 :受影响的代码很少,编译器会捕获它们,必须手动对其进行更新.

The encoding/xml package

在Go 1中, xml包的设计与其他封送处理包(例如encoding/gob设计更加接近.

旧的Parser类型被重命名为Decoder并具有新的Decode方法. 还引入了Encoder类型.

MarshalUnmarshal函数现在可以使用[]byte值. 要使用流,请使用新的EncoderDecoder类型.

当编组或解编值时,字段标记中支持的标志的格式已更改为更接近json包( `xml:"name,flag"` ). 字段标记,字段名称以及XML属性和元素名称之间的匹配现在区分大小写. XMLName字段标记(如果存在)还必须与被封送的XML元素的名称匹配.

更新 :运行go fix将更新该软件包的大多数用法,除了对Unmarshal某些调用. 必须特别注意字段标签,因为修复工具不会更新它们,如果不手工修复,它们在某些情况下会无声地表现. 例如,原来的"attr"现在写为",attr"而普通的"attr"仍然有效,但含义不同.

The expvar package

在Go 1中, RemoveAll函数已被删除. *Map上的Iter函数和Iter方法已由Do(*Map).Do取代.

更新 :使用expvar大多数代码无需更改. 可以更新使用Iter的罕见代码,以将闭包传递给Do以实现相同的效果.

The flag package

在Go 1中,接口flag.Value略有变化. Set方法现在返回一个error而不是bool来指示成功或失败.

还有一种新的标志Duration ,用于支持指定时间间隔的参数值. 对于这样的标志值必须被定单位,就像time.Duration其格式化: 10s1h30m等.

var timeout = flag.Duration("timeout", 30*time.Second, "how long to wait for completion")

更新 :实现自己的标志的程序将需要进行较小的手动修复以更新其Set方法. Duration标志是新的,不影响现有代码.

The go/* packages

下几个包go有小幅修正的API.

go/scannergo/parsergo/printergo/doc包中为配置模式标志引入了具体的Mode类型.

已从go/scanner软件包中删除了模式AllowIllegalCharsInsertSemis . 它们对于扫描除Go源文件以外的文本非常有用. 相反,应将text/scanner程序包用于此目的.

现在,提供给扫描仪的Init方法的ErrorHandler只是一个函数,而不是一个接口. 所述ErrorVector类型已赞成(现有)的被除去ErrorList类型和ErrorVector方法已被迁移. 而不是嵌入的的ErrorVector在扫描仪的客户,现在客户应保持ErrorList .

go/parser软件包提供的一组解析函数已简化为主要的解析函数ParseFile和几个便捷函数ParseDirParseExpr .

go/printer软件包支持其他配置模式SourcePos ; 如果设置,打印机将发出//line注释,以便生成的输出包含原始源代码位置信息. 新型CommentedNode可用于提供与任意相关的注释ast.Node (到现在为止只ast.File进行注释信息).

删除了Doc后缀,简化了go/doc包的类型名称: PackageDoc现在是PackageValueDocValue ,等等.而且,所有类型现在都一致地具有Name字段(或Names ,对于Value类型而言)并且Type.Factories已成为Type.Funcs . 无需调用doc.NewPackageDoc(pkg, importpath) ,而是使用以下方法创建软件包的文档:

    doc.New(pkg, importpath, mode)

其中new mode参数指定操作模式:如果设置为AllDecls ,则将AllDecls所有声明(不仅是导出的声明). 功能NewFileDoc被删除,并且功能CommentText已成为法Textast.CommentGroup .

在包go/token ,所述token.FileSet方法Files (其原本返回的信道*token.File或多个)已被替换为迭代Iterate接受一个函数参数来代替.

在包go/build ,API已几乎完全替换. 该软件包仍会计算Go软件包信息,但不会运行构建: CmdScript类型已消失. (要构建代码,请改用新的go命令.) DirInfo类型现在命名为Package . FindTreeScanDir被替代ImportImportDir .

更新 :使用go软件包的代码必须手动更新; 编译器将拒绝不正确的使用. 与任何go/doc类型结合使用的模板可能需要手动修复; 重命名的字段将导致运行时错误.

The hash package

在Go 1中, hash.Hash的定义包括一个新方法BlockSize . 此新方法主要在密码库中使用.

hash.Hash接口的Sum方法现在带有[]byte参数,哈希值将附加到该参数. 可以通过在调用中添加nil参数来重新创建以前的行为.

更新 :现有的hash.Hash实现hash.Hash将需要添加BlockSize方法. 一次处理输入一个字节的BlockSize可以实现BlockSize返回1.运行go fix将更新对hash.Hash的各种实现的Sum方法的hash.Hash .

更新 :由于软件包的功能是新的,因此无需更新.

The http package

在Go 1中, http包被重构,将一些实用程序放入httputil子目录中. HTTP客户端很少需要这些片段. 受影响的项目是:

Request.RawURL字段已删除; 这是一个历史文物.

现在,如果尝试两次注册相同的模式,则HandleHandleFunc函数以及类似名称的ServeMux方法会ServeMux紧急情况.

更新 :运行go fix将更新少数受影响的RawURL ,但必须手动修复RawURL使用.

The image package

image包进行了许多小的更改,重新排列和重命名.

大多数颜色处理代码已移至其自己的包image/color . 对于移动的元素,会出现对称性. 例如, image.RGBA每个像素都是color.RGBA .

旧的image/ycbcr程序包经过重命名已折叠到imageimage/color程序包中.

旧的image.ColorImage类型仍在image包中,但已重命名为image.Uniform ,而image.Tiled已被删除.

该表列出了重命名.

Old New

image.Color color.Color
image.ColorModel color.Model
image.ColorModelFunc color.ModelFunc
image.PalettedColorModel color.Palette

image.RGBAColor color.RGBA
image.RGBA64Color color.RGBA64
image.NRGBAColor color.NRGBA
image.NRGBA64Color color.NRGBA64
image.AlphaColor color.Alpha
image.Alpha16Color color.Alpha16
image.GrayColor color.Gray
image.Gray16Color color.Gray16

image.RGBAColorModel color.RGBAModel
image.RGBA64ColorModel color.RGBA64Model
image.NRGBAColorModel color.NRGBAModel
image.NRGBA64ColorModel color.NRGBA64Model
image.AlphaColorModel color.AlphaModel
image.Alpha16ColorModel color.Alpha16Model
image.GrayColorModel color.GrayModel
image.Gray16ColorModel color.Gray16Model

ycbcr.RGBToYCbCr color.RGBToYCbCr
ycbcr.YCbCrToRGB color.YCbCrToRGB
ycbcr.YCbCrColorModel color.YCbCrModel
ycbcr.YCbCrColor color.YCbCr
ycbcr.YCbCr image.YCbCr

ycbcr.SubsampleRatio444 image.YCbCrSubsampleRatio444
ycbcr.SubsampleRatio422 image.YCbCrSubsampleRatio422
ycbcr.SubsampleRatio420 image.YCbCrSubsampleRatio420

image.ColorImage image.Uniform

图像包的New功能( NewRGBANewRGBA64等)采取image.Rectangle作为参数,而不是四个整数.

最后,有新的预定义的color.Color变量color.Blackcolor.Whitecolor.Opaquecolor.Transparent .

Updating: Running go fix will update almost all code affected by the change.

The log/syslog package

在Go 1中, syslog.NewLogger函数返回一个错误以及log.Logger .

更新 :受影响的代码很少,编译器会捕获它们,必须手动对其进行更新.

The mime package

在Go 1中,简化了mime包的FormatMediaType函数,使其与ParseMediaType一致. 现在,它使用"text/html"而不是"text""html" .

更新 :受影响的代码很少,编译器会捕获它们,必须手动对其进行更新.

The net package

在Go 1中,各种SetTimeoutSetReadTimeoutSetWriteTimeout方法分别被SetDeadlineSetReadDeadlineSetWriteDeadline取代. 新方法没有设置适用于连接上任何活动的超时值(以纳秒为单位),而是设置了绝对期限(作为time.Time值),在此期限之后,读取和写入将超时并且不再阻塞.

There are also new functions net.DialTimeout to simplify timing out dialing a network address and net.ListenMulticastUDP to allow multicast UDP to listen concurrently across multiple listeners. The net.ListenMulticastUDP function replaces the old JoinGroup and LeaveGroup methods.

更新 :使用旧方法的代码将无法编译,必须手动更新. 语义上的更改使修复工具很难自动更新.

The os package

Time功能已被删除; 呼叫者应使用time包中的Time类型.

Exec功能已被删除; 调用方应使用syscall软件包中的Exec (如果有).

ShellExpand函数已重命名为ExpandEnv .

现在, NewFile函数将使用uintptr fd而不是int . 文件上的Fd方法现在还返回一个uintptr .

os包中不再存在诸如EINVAL错误常量,因为值集随基础操作系统的不同而不同. 有一些新的可移植函数,例如IsPermission用于测试常见的错误属性,还有一些带有更多类似Go的名称的新错误值,例如ErrPermissionErrNotExist .

Getenverror函数已被删除. 要区分不存在的环境变量和空字符串,请使用os.Environsyscall.Getenv .

Process.Wait方法已删除其option参数,并且相关的常量已从程序包中删除. 同样,功能Wait消失了; 仅Process类型的方法持续存在.

Process.Wait返回的Waitmsg类型已被具有访问器方法的可移植性更佳的ProcessState类型所取代,该访问器方法用于恢复有关该过程的信息. 由于Wait的更改, ProcessState值始终描述退出的进程. 可移植性问题以其他方式简化了接口,但是ProcessState.SysProcessState.SysUsage方法返回的值可以类型声明为特定于基础的特定于系统的数据结构,例如Unix上的syscall.WaitStatussyscall.Rusage .

更新 :运行go fix将为Process.Wait删除零参数. 所有其他更改将由编译器捕获,并且必须手动进行更新.

The os.FileInfo type

Go 1重新定义了os.FileInfo类型,将其从结构更改为接口:

    type FileInfo interface {
        Name() string       // base name of the file
        Size() int64        // length in bytes
        Mode() FileMode     // file mode bits
        ModTime() time.Time // modification time
        IsDir() bool        // abbreviation for Mode().IsDir()
        Sys() interface{}   // underlying data source (can return nil)
    }

文件模式信息已移入名为os.FileMode的子类型,该子类型是具有IsDirPermString方法的简单整数类型.

文件模式和属性的特定于系统的详细信息(例如(在Unix上)i-number)已从FileInfo全部删除. 相反,每个操作系统的os包都提供FileInfo接口的实现,该接口具有Sys方法,该方法返回特定于系统的文件元数据表示. 例如,要发现Unix系统上文件的i编号,请像下面这样解压FileInfo

    fi, err := os.Stat("hello.go")
    if err != nil {
        log.Fatal(err)
    }
    // Check that it's a Unix file.
    unixStat, ok := fi.Sys().(*syscall.Stat_t)
    if !ok {
        log.Fatal("hello.go: not a Unix file")
    }
    fmt.Printf("file i-number: %d\n", unixStat.Ino)

假设"hello.go"是一个Unix文件(这是不明智的),则i-number表达式可以被压缩为

    fi.Sys().(*syscall.Stat_t).Ino

The vast majority of uses of FileInfo need only the methods of the standard interface.

os软件包不再包含POSIX错误的包装器,例如ENOENT . 对于需要验证特定错误条件的少数程序,现在有布尔函数IsExistIsNotExistIsPermission .

    f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
    if os.IsExist(err) {
        log.Printf("%s already exists", name)
    }

更新 :运行go fix将更新使用当前os.FileInfoos.FileMode API的旧版本的代码. 需要系统特定文件详细信息的代码将需要手动更新. 使用os包中旧POSIX错误值的代码将无法编译,也需要手动进行更新.

The os/signal package

Go 1中的os/signal包用选择性Notify功能替换了Incoming功能,该功能返回了一个接收所有传入信号的通道,该功能要求在现有通道上传送特定信号.

更新 :必须手动更新代码. 的字面翻译

c := signal.Incoming()

is

c := make(chan os.Signal)
signal.Notify(c) // ask for all signals

但是大多数代码应该列出它要处理的特定信号:

c := make(chan os.Signal)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)

The path/filepath package

在Go 1中,已将path/filepath包的Walk函数更改为采用WalkFunc类型的函数值,而不是Visitor接口值. WalkFunc统一了文件和目录的处理.

    type WalkFunc func(path string, info os.FileInfo, err error) error

即使对于无法打开的文件或目录,也会调用WalkFunc函数. 在这种情况下,错误参数将描述失败. 如果要跳过目录的内容,则该函数应返回值filepath.SkipDir

    markFn := func(path string, info os.FileInfo, err error) error {
        if path == "pictures" { // Will skip walking of directory pictures and its contents.
            return filepath.SkipDir
        }
        if err != nil {
            return err
        }
        log.Println(path)
        return nil
    }
    err := filepath.Walk(".", markFn)
    if err != nil {
        log.Fatal(err)
    }

更新所做的更改简化了大多数代码,但产生了微妙的后果,因此需要手动更新受影响的程序. 编译器将使用旧接口捕获代码.

The regexp package

regexp软件包已被重写. 它具有相同的接口,但它支持的正则表达式的规范已从旧的" egrep"形式更改为RE2 .

更新 :使用包的代码应手动检查其正则表达式.

The runtime package

在Go 1中,软件包runtime导出的许多API已被删除,以支持其他软件包提供的功能. 使用runtime.Type接口或其特定的具体类型实现的代码现在应该使用reflect . 使用runtime.Semacquireruntime.Semrelease代码应在包sync使用通道或抽象. runtime.Allocruntime.Freeruntime.Lookup函数是用于调试内存分配器的不安全API,无法替代.

之前, runtime.MemStats是一个全局变量,用于保存有关内存分配的统计信息,并调用runtime.UpdateMemStats确保它是最新的. 在Go 1中, runtime.MemStats是一种结构类型,代码应使用runtime.ReadMemStats来获取当前统计信息.

该软件包添加了一个新函数runtime.NumCPU ,该函数返回操作系统内核报告的可用于并行执行的CPU数量. 其值可以告知GOMAXPROCS的设置. runtime.Cgocallsruntime.Goroutines函数已重命名为runtime.NumCgoCallruntime.NumGoroutine .

更新 :运行go fix将为功能重命名更新代码. 其他代码将需要手动更新.

The strconv package

在围棋1, strconv包已经显著重新设计,使其转到样和更少的类C,虽然Atoi住在(它类似于int(ParseInt(x, 10, 0))一样, Itoa(x)FormatInt(int64(x), 10) ).一些函数的新变体附加到字节片上,而不是返回字符串,以允许控制分配.

该表总结了重命名; 有关完整的详细信息,请参见软件包文档 .

旧电话 新来电

Atob(x) ParseBool(x)

Atof32(x) ParseFloat(x,32)§
Atof64(x) ParseFloat(x,64)
AtofN(x,n) ParseFloat(x, n)

Atoi(x) Atoi(x)
Atoi(x) ParseInt(x,10,0)§
Atoi64(x) ParseInt(x,10,64)

Atoui(x) ParseUint(x,10,0)§
Atoui64(x) ParseUint(x,10,64)

Btoi64(x,b) ParseInt(x,b,64)
Btoui64(x,b) ParseUint(x,b,64)

Btoa(x) FormatBool(x)

Ftoa32(x,f,p) FormatFloat(float64(x),f,p,32)
Ftoa64(x,f,p) FormatFloat(x,f,p,64)
FtoaN(x,f,p,n) FormatFloat(x,f,p,n)

Itoa(x) Itoa(x)
Itoa(x) FormatInt(int64(x), 10)
Itoa64(x) FormatInt(x,10)

帐户[x,b] FormatInt(int64(x),b)
Itob64(x,b) FormatInt(x,b)

Uitoa(x) FormatUint(uint64(x),10)
Uitoa64(x) FormatUint(x,10)

Uitob(x,b) FormatUint(uint64(x),b)
Uitob64(x,b) FormatUint(x,b)

更新 :运行go fix将更新几乎所有受更改影响的代码.
§ Atoi仍然存在,但AtouiAtof32没有,所以他们可能会要求必须手工添加强制类型转换; go fix工具将对此发出警告.

The template packages

templateexp/template/html包已移至text/templatehtml/template . 更重要的是,简化了这些程序包的接口. 模板语言是相同的,但是"模板集"的概念不复存在,并且软件包的功能和方法也相应地发生了变化,通常是通过消除来实现的.

Template对象可以包含多个命名的模板定义,而不是集合,实际上是为模板调用构造名称空间. 模板可以调用与其关联的任何其他模板,但是只能调用与之关联的那些模板. 关联模板的最简单方法是将它们解析在一起,这通过软件包的新结构变得更加容易.

更新 :导入将通过修复工具进行更新. 否则,单模板使用将在很大程度上不受影响. 需要同时手动更新使用多个模板的代码. text/template文档中的示例可以提供指导.

The testing package

测试包的类型B作为参数传递给基准函数. 在Go 1中, B具有与T类似的新方法,从而可以进行日志记录和故障报告.

func BenchmarkSprintf(b *testing.B) {
    // Verify correctness before running benchmark.
    b.StopTimer()
    got := fmt.Sprintf("%x", 23)
    const expect = "17"
    if expect != got {
        b.Fatalf("expected %q; got %q", expect, got)
    }
    b.StartTimer()
    for i := 0; i < b.N; i++ {
        fmt.Sprintf("%x", 23)
    }
}

更新 :尽管使用printlnpanic基准应该更新为使用新方法,但现有代码不受影响.

The testing/script package

测试/脚本包已被删除. 那是渣

更新 :可能不会影响任何代码.

The unsafe package

在Go 1中,已删除函数unsafe.Typeofunsafe.Reflectunsafe.Unreflectunsafe.Newunsafe.NewArray ; 他们复制了package reflect提供的更安全的功能.

更新 :必须重写使用这些功能的代码才能使用包reflect . 作为示例,对编码/目标协议缓冲区库的更改可能会有所帮助.

The url package

在Go 1中,已删除或替换了url.URL类型的几个字段.

现在, String方法可以根据需要使用所有URL的字段来预测地重建编码的URL字符串. 结果字符串也将不再具有密码转义.

Raw字段已被删除. 在大多数情况下,可以使用String方法代替它.

类型为*net.UserinfoUser字段替换了RawUserinfo字段. 可以使用新的net.Usernet.UserPassword函数创建此类型的值. 该EscapeUserinfoUnescapeUserinfo功能也不见了.

RawAuthority字段已被删除. HostUser字段中提供了相同的信息.

RawPath字段和EncodedPath方法已被删除. 根URL中的路径信息(在模式之后带有斜线)现在仅在" Path字段中以解码形式提供. 有时,可能需要编码数据来获取在解码过程中丢失的信息. 必须通过访问构建URL的数据来处理这些情况.

具有非根目录路径的URL,例如"mailto:dev@golang.org?subject=Hi" ,也"mailto:dev@golang.org?subject=Hi"不同的方式处理. OpaquePath布尔字段已删除,并引入了新的Opaque字符串字段来保存此类URL的编码路径. 在Go 1中,引用的URL解析为:

    URL{
        Scheme: "mailto",
        Opaque: "dev@golang.org",
        RawQuery: "subject=Hi",
    }

新的RequestURI方法已添加到URL .

ParseWithReference函数已重命名为ParseWithFragment .

更新 :使用旧字段的代码将无法编译,必须手动更新. 语义上的更改使修复工具很难自动更新.

The go command

Go 1引入了go命令 ,这是一个用于获取,构建和安装Go软件包和命令的工具. go命令取消了makefile文件,而是使用Go源代码查找依赖项并确定构建条件. 大多数现有的Go程序将不再需要构建makefile.

有关go命令的入门知识,请参阅如何编写Go代码 ;有关完整详细信息,请参见go命令文档 .

更新 :依赖于Go项目的旧基于makefile的旧构建基础结构( Make.pkgMake.cmd等)的项目应切换到使用go命令来构建Go代码,并在必要时重写其makefile以执行任何辅助构建任务.

The cgo command

在Go 1中, cgo命令使用另一个_cgo_export.h文件,该文件是为包含//export行的包生成的. _cgo_export.h文件现在以C序言注释开头,因此导出的函数定义可以使用在那里定义的类型. 这具有多次编译前导的效果,因此使用//export的程序包不得在C前导中放置函数定义或变量初始化.

Packaged releases

与Go 1相关的最重大更改之一是预包装的可下载发行版的可用性. 它们可用于体系结构和操作系统(包括Windows)的许多组合,并且列表会不断增加. 安装详细信息在" 入门"页面上进行了描述,而发行版本身在下载页面上列出.

by  ICOPY.SITE