语言变化
Golang1.17 对该语言带来了三项小改进。
切片到数组指针的转换:在新版本中,[]T类型的表达式s可以转换为数组指针类型*[N]T。对于转换结果数组a,其索引范围需要满足以下条件:
a[i]==s[i], 0=i N
如果len(s)小于N,程序将会panic
unsafe.Add:unsafe.Add(ptr, len) 将len 添加到ptr 并返回更新后的指针unsafe.Pointer(uintptr(ptr) + uintptr(len))。
unsafe.Slice:对于T*类型的ptr表达式,unsafe.Slice(ptr, len)函数返回一个[]T类型的切片。下面的数组以ptr 开头,范围为len。
添加了包不安全增强功能,以简化编写符合unsafe.Pointer 的安全规则,但规则保持不变。特别是,正确使用unsafe.Pointer的现有程序仍然有效,新程序必须遵循规则才能使用unsafe.Add或unsafe.Slice。
请注意,从切片到数组指针的新转换是第一个类型转换,可能会在运行时出现恐慌。
港口
达尔文
Golang支持macOS,要求版本为10.13 Sierra或更高版本;
视窗
Windows平台Go 1.17增加了对ARM 64位架构(windows/arm64端口)的支持,并支持cgo。
开放BSD
OpenBSD 上的新版本64 位MIPS 架构(openbsd/mips64) 支持cgo。
在Go 1.16 中,OpenBSD(penbsd/amd64 和openbsd/arm64)系统调用是通过64 位x86 和64 位ARM 架构上的libc 进行的。在Go 1.17 中,在OpenBSD 上的32 位x86 和32 位ARM 架构(openbsd/386 和openbsd/arm 端)上进行相同的调用。这确保了与OpenBSD 6.9 及以上版本的兼容性,这需要对libc 进行系统调用以获取非静态golang 二进制文件。
ARM64
新版本的Golang程序在64位ARM上维护堆栈帧指针,这对于所有操作系统都是相同的架构。之前的堆栈帧指针仅在Linux、macOS 和iOS 上可用。
loong64 GOARCH 值保留
主要的Golang编译器尚不支持LoongArch架构,保留GOARCH值“loong64”。除非正在使用GOARCH 值,否则Go 工具现在会忽略名为*_loong64.go 的Go 文件。
工具链
执行命令
模块图细化
如果模块指定转到1.17 或更高版本。模块图仅包括直接依赖的go 1.17 模块,而不包括它们完整的传递依赖关系。
为了使go 命令正确解析压缩的模块依赖关系图,每个模块的go.mod 文件需要包含有关与该模块关联的传递依赖关系的更多详细信息。如果模块的go.mod 文件的go 版本为1.17,则其go.mod 文件需要显式指定每个提供带有require 指令的传递导入包的模块。
go.mod 模块图缩减所需的文件包括将任何包的导入加载到主模块中所需的所有依赖项。如果主模块指定为go 1.17或更高版本,则go工具不再读取或下载它,并且在其请求中也不需要它。该模块位于主go.mod中。
由于扩展了Go 1.17 的go.mod 文件的显式扩展,go 1.17 中的新间接依赖项需要在单独的require 块中维护。
为了方便升级到Go 1.17 精简模块图,go mod tidy 子命令现在支持-go 选项,将现有模块的go.mod 文件的go 版本转换为Go 1.17。你可以运行:
go mod tidy -go=1.17
默认情况下,go mod tidy 会验证相对于主模块的所选依赖版本是否与之前的Go 版本使用的版本相同,并保留go.sum 版本所需的条目。
-compat 标志允许覆盖版本以支持旧版本,最高可达go.mod 文件中go 指令中指定的版本。
go mod tidy -compat=1.17
请注意,即使主模块使用-compat=1.17 进行转换,需要该模块的go 1.16 或更早版本的用户仍然可以使用它,前提是该包仅使用兼容的语言和库功能。
go mod graph 子命令还支持-go 标志,这会导致报告的Go 版本看到的图表显示可能的依赖关系,否则这些依赖关系将被简化。
模块弃用注释
去拿
go get -insecure 标志已被删除。当需要使用不安全的妥协来获取依赖项时,需要设置GOINSECURE 环境变量。 -insecure 标志还用于绕过模块和验证。为此,请使用GOPRIVATE 或GONOSUMDB。
Go get 是一个在安装非主模块(不带-d 选项)时打印弃用警告的命令。应使用go install cmd@version 安装特定版本。您可以使用后缀,例如@latest 或@v1.2.3。在Go 1.18中,-d标志将默认启用,并且go get将仅用于更改依赖关系go.mod。
go.mod 文件缺少go 指令
如果主模块的go.mod 文件不包含go 指令,并且go 命令无法更新go.mod 文件,则go 命令会假定go 版本为1.11,而不是当前版本。 (在go1.12中go mod init会自动添加go指令。)
如果模块依赖项缺少显式go.mod 文件,或其go.mod 文件不包含go 指令,则go 命令现在假定go 版本1.16 而不是当前版本。
供应商内容
如果主模块指定go 1.17 或更高版本,go modvendor 现在会使用go 版本注释vendor/modules.txt。当从供应商的源代码构建模块的包时,每个供应商模块都有自己的go.mod 文件。 go版本会有注释。
如果主模块指定go 1.17 或更高版本,go modvendor 现在会忽略供应商依赖项的go.mod 和go.sum 文件,否则可能会干扰go 命令为调用供应商树识别正确的模块根。
密码提示
使用SSH 获取Git 存储库时,go 命令现在默认禁止显示SSH 密码提示和Git Credential Manager 提示。使用受密码保护的SSH 访问私有Git 存储库的用户可以配置ssh-agent 以允许go 命令访问受密码保护的SSH 密钥。
去模组下载
当不指定参数调用go mod download时,下载的模块的sum值将不再保存到go.sum中。可能仍然有需要为go.mod 和go.sum 加载的构建列表。这与Go 1.15 中的默认行为一致。要保存所有模块的总和值,请使用
go mod 下载全部
//go:构建线
go 命令现在可以理解//go:build 行并使用它们而不是//+build 行。新语法使用布尔表达式并且不易出错。从版本1.17 开始,完全支持新语法,并且所有Go 文件都应更新为在两种形式中具有相同的含义。为了帮助用户迁移,gofmt 现在自动同步这两种表单。
去跑步
go run 现在接受带有版本后缀的参数(例如go run example.com/cmd@v1.0.0)。这会导致go run 在模块感知模式下构建和运行包,忽略当前目录或任何父目录中的go.mod 文件。用于运行可执行文件而不安装它们或更改当前模块的依赖项。
戈夫姆特
gofmt(和go fmt)现在将//go:build 行与//+build 行同步。如果文件只有//+build 行,它们将被移动到文件中的适当位置并与添加的//go:build 行匹配。否则, //+build 行将根据现有的//go:build 行进行调整。
兽医
//go: 构建行和//+build 行之间不匹配的新警告
vet 工具现在可以验证//go:build 和//+build 行是否位于文件的正确部分并且彼此匹配。如果它们不匹配,可以使用gofmt 来修复它们。
无缓冲通道上的Signal.Notify 调用警告
Vet 工具现在会在signal.Notify 输入信号发送到无缓冲通道时发出警告。当signal.Notify 不阻塞时使用无缓冲通道有丢失信号的风险。例如:
c :=make(chan os.Signal)//当在读取channell之前已经发送了无缓冲信号c时,无缓冲信号c将会丢失signal.Notify(c, os.Interrupt)c :=make(chan os.信号)
signal.Notify 的用户应使用具有足够缓冲空间的通道,以跟上预期的信号速率。
Is、As 和Unwrap 方法的新警告
现在,当命名方法As、Is 或Unwrap 实现具有不同类型错误签名且与预期错误不匹配的接口时,Vet 工具会向您发出警告。 error.{As,Is,Unwrap} 函数以统一的方式实现相同的方法,而不是单独实现Is(error) bool、As(interface{}) bool 或Unwrap() error。 error.{As,Is,Unwrap} 将忽略具有相同方法名称但不同签名的方法。例如:
type MyError struct {hint string }func (m MyError) Error() string { . } //MyError 实现error.func (MyError) Is(target interface{}) bool { . } //目标是接口{ } 而不是错误。 func Foo() bool {x, y :=MyError{'A'}, MyError{'B'} return errors.Is(x, y) //返回false,因为x !=y 并且MyError 没有`Is(错误)布尔`函数}
覆盖
覆盖工具现在使用优化的解析器golang.org/x/tools/cover,这使得在解析大型覆盖配置文件时性能显着提高。
编译器
Go 1.17 通过使用寄存器而不是堆栈存储来实现传递函数参数和结果的新方法。基准测试表明,编译性能提高了约5%,编译后的二进制文件大小减少了约2%。此功能目前在Linux、macOS 和Windows 64 位架构(linux/amd64、darwin/amd64 和windows/amd64)上启用。
此更改不会影响任何安全Go 代码的功能,并且不会影响大多数汇编代码。但它可能会影响访问函数参数时违反此unsafe.Pointer 规则的代码,或者依赖于涉及比较函数代码指针的未记录行为。
为了保持与现有汇编函数的兼容性,编译器生成适配器函数。新的基于寄存器的调用约定和之前的基于堆栈的调用约定之间的调用约定。这些适配器通常对用户是不可见的,除了汇编代码中Go函数的地址或者取地址之外。 Go代码中使用reflect.ValueOf(fn).Pointer()或unsafe.Pointer的汇编函数将返回地址适配器。依赖这些代码指针值的代码可能不会按预期运行。在两种情况下,适配器也可能会产生非常小的性能开销:通过Go 的fun 值间接调用汇编函数,以及从汇编调用Go 函数。
运行时堆栈跟踪的格式(在发生未捕获的恐慌时或调用runtime.Stack 时打印)已得到改进。以前,函数参数以基于内存的十六进制字布局打印。现在,源代码中的每个参数都会单独打印,并用逗号分隔。聚合类型(结构体、数组、字符串、切片、接口和复合体)参数由大括号分隔。需要注意的是,如果参数的值仅存在于寄存器中而不存储到内存中,则该参数可能不准确。不再打印函数返回值(通常不准确)。
包含闭包的函数现在可以内联。这一更改的一个影响是,带有闭包的函数可能会为内联指针函数的每个位置生成不同的闭包代码。 Go 函数值无法直接比较,但此更改可能会揭示使用Reflect 或unsafe.Pointer 的代码中的错误,以绕过此语言限制并通过代码指针比较函数。
连接器
当链接器使用外部链接模式时,默认链接是使用cgo程序时,当使用-I选项调用链接器时,该选项现在将传递给外部链接器-Wl,--dynamic-linker选项。
核心库
铜矿
runtime/cgo 包现在提供了一个新工具,允许将任何Go 值转换为可用于在C 和Golang 中传递值的安全表示形式。
URL查询解析
net/url 和net/http 之前接受';' (分号)作为URL 查询中的设置分隔符。在新版本中,带有分号的非百分比编码设置将被拒绝,并且net/htt 服务器会将包含分号的请求记录到Server.ErrorLog 日志中。
例如,在Go 1.17 之前请求URL:cc?a=1;b=2c=3 将返回map[a:[1] b:[2] c:[3]],现在返回map[c:[3]]。
当遇到这样的查询字符串时,URL.Query和Request.FormValue会忽略任何包含分号的设置,ParseQuery返回剩余的设置和错误,Request.ParseForm和Request.ParseMultipartForm返回错误,但仍然将Reques基于其他配置设置字段。
net/http 用户可以使用AllowQuerySemicolons 处理程序包装器来执行此操作。它也不会触发ErrorLog 日志记录警告。
请注意,接受分号作为查询分隔符可能会导致安全问题。
TLS 严格ALPN
设置Config.NextProtos 时,服务器现在会强制配置协议与客户端建议的ALPN 协议进行协调。如果没有相互支持的协议,连接将被关闭。根据RFC 7301的要求,将触发no_application_protocol警报,可以缓解ALPACA跨协议攻击。
作为例外,当服务器的Config.NextProtos 包含“h2”值时,将允许不支持ALPN 的HTTP/1.1 客户端进行连接。
其他库更改
存档/zip
新增方法File.OpenRaw、Writer.CreateRaw、Writer.Copy,在关注运行性能时可以使用。
压缩/lzw
NewReader 函数保证返回一个新的值类型Reader,NewWriter 保证返回一个新的值类型Writer。这些新类型实现Reset 方法(Reader.Reset、Writer.Reset)以允许重用Reader 或Writer。
加密/ed25519
crypto/ed25519 软件包已被重写,以将所有amd64 和arm64 上的操作改进为两倍。
加密/椭圆
CurveParams 方法现在自动调用更快、更安全的专用已知曲线(P-224、P-256 和P-521)的实现。
请注意,这是一种尽力而为的方法,应用程序应避免使用通用的恒定时间CurveParams 方法,而应使用专用的Curv 实现,例如P256。
P521 曲线实现已使用法定加密项目生成的代码重写,该代码基于形式验证的算术模型运算。现在支持amd64 和arm 64。
加密货币/兰特
crypto/rand 包现在在macOS 上使用getentropy 系统调用,在Solaris、Illumos 和DragonFlyBSD 系统上使用getrandom 系统调用。
加密/tls
新的Conn.HandshakeContext 方法允许用户控制取消正在进行的TLS 握手。可以通过新的ClientHelloInfo.Context 和CertificateRequestInfo.Context 方法从各种回调访问提供的上下文。握手完成后取消上下文没有任何效果。
密码套件排序现在已由crypto/tls 完全打包。目前,密码套件是根据其安全性、性能以及对本地和对等硬件的硬件支持来订购的。
Config.CipherSuites 字段现在被忽略,请使用Config.PreferServerCipherSuites 字段。请注意,Config.CipherSuites 仍然允许应用程序选择要启用的TLS 1.0-1.2 密码套件。
3DES 密码套件已移至InsecureCipherSuites。默认情况下它们仍然处于启用状态,但只是作为最后的手段。
从下一版本Go 1.18 开始,crypto/tls 客户端的Config.MinVersion 将默认使用TLS 1.2,禁用TLS 1.0 和TLS 1.1。应用程序将能够覆盖对显式设置Config.MinVersion 的更改。但它不会影响crypto/tls 服务器。
加密/x509
如果提供的私钥与父公钥不匹配,CreateCertificate 将返回错误。生成的证书将无法验证。
临时GODEBUG=x509ignoreCN=0 标志已被删除。
ParseCertificate 已被重写,现在消耗的资源减少了约70%。除了错误消息之外,行为没有改变。
在BSD 系统上,/etc/ssl/certs 现在搜索可信根。这增加了对新系统受信任证书存储FreeBSD 12.2+ 的支持。
从Go 1.18 的下一版本开始,crypto/x509 将拒绝使用SHA-1 哈希函数签名的证书。但自签名根证书没有限制。
数据库/sql
如果实现了io.Close 接口的连接器字段中的类型,则DB.Close 方法现在将关闭。
新的NullInt16 和NullByte 结构表示可能为null 的int16 和字节值。这些可以用作目标Scan 方法,类似于NullString。
调试/精灵
添加了SHT_MIPS_ABIFLAGS 常量。
编码/二进制
binary.Uvarint 仅读取10 个字节,以避免浪费计算。如果需要超过10 个字节,则返回的字节数为-11。
以前的Go 版本在读取错误编码的varint 时可能会返回较大的负数。
编码/csv
新的Reader.FieldPos 方法返回最近返回的记录中与起始行和列Read 相对应的给定字段。
编码/xml
当指令中出现注释时,它们现在被替换为单个空格,而不是完全省略。
带有前导、尾随或多个冒号的无效元素或属性名称现在不加修改地存储到Name.Local 字段中。
旗帜
开始/构建
新的Context.ToolTags 字段包含适合当前Go 的构建标签工具链配置。
转到/格式化
Sourc 和Nod 现在与//+build 行同步运行//go:build 行。如果文件只有//+build 行,它们将被移动到文件中的适当位置,并且匹配的//go:build 行将自动添加。否则, //+build 行将根据任何现有的//go:build 行进行调整。
去/解析器
新的SkipObjectResolution Modevalue 指示解析器在解析时跳过这些指令。这可以提高解析速度。
图像
图像类型(RGBA、Gray16 等)启用新的RGBA64Image 接口。之前实现的具体类型draw.Image现在也实现了draw.RGBA64Image,一个新的图像/绘图包装。
IO/文件系统
新的FileInfoToDirEntry 函数将FileInfo 转换为DirEntry。
数学
math 包现在定义了三个附加常量:MaxUint、MaxInt 和MinInt。对于32 位系统,值范围为2^32-1、2^31-1 和-2^31。对于64 位系统,值范围为2^64 - 1、2^63-1 和-2^63。
哑剧
在Unix 系统上,MIME 类型由本地系统的共享MIME 信息数据库表示。
哑剧/多部分
现在将filepath.Base 应用到返回值。缓解接受多部分消息的应用程序中潜在的路径遍历漏洞,例如对名为Request.FormFile 的服务器的net/http 调用。
网
新的IP.IsPrivate 方法返回该地址是根据RFC 1918 标准的私有IPv4 地址还是根据RFC 4193 标准的本地IPv6 地址。
Go DNS 解析器在解析纯IPv4 或纯IPv6 网络上的地址时仅发送一个DNS 查询,而不是查询两个地址族。
ErrClosed 哨兵错误和ParseError 错误类型现在由net.Error 接口实现。
ParseIP 和ParseCIDR 函数现在拒绝包含零的十进制IPv4 地址。这些组件在模块中被解释为十进制,但被操作系统视为八进制。如果Go 应用程序用于验证IP 地址,然后以原始形式与将该组件解释为八进制的非Go 应用程序一起使用,则这种不匹配可能会导致安全问题。一般来说,建议在验证后始终对值进行重新编码,以避免此类问题。
网络/http
在客户端或服务器中执行TLS 握手时,net/http 包现在使用新的(*tls.Conn).HandshakeContext 和请求上下文。
现在,将服务器ReadTimeout 或WriteTimeout 字段设置为负值表示不超时,而不是立即超时。
现在,当请求具有多个主机标头时,ReadReques 函数会返回错误。
ServeMux 现在在生成URL 重定向时始终使用相对URL Location 标头。以前,请求的完整URL 会被回显,这可能会导致意外结果。
现在,在解释由处理的某些HTTP 标头时,会忽略或拒绝非ASCII 字符。
如果Request.ParseForm 在调用Request.ParseMultipartForm 时返回错误,则后者现在将继续填充Request.MultipartForm。
网/http/httptest
现在,当提供的代码不是有效的三位数HTTP 状态代码时,ResponseRecorder.WriteHeader 会触发紧急情况。这符合ResponseWriter 实现的行为。
网络/网址
新方法Values.Has 报告是否设置了查询参数。
操作系统
反映
新的Value.CanConver 方法报告值是否可以转换为类型。如果切片太短,这可用于避免将切片转换为数组指针类型时发生恐慌。以前使用Type.ConvertibleTo 就足够了,但新方法允许的从切片到数组的转换可能会触发指针类型的恐慌,即使该类型是可转换的
新的StructField.IsExported 和Method.IsExported 方法报告是否导出结构体字段或类型方法。它们提供了一种更具可读性的替代方法来检查PkgPath 是否为空。
新的VisibleFields 函数返回结构类型中的所有可见字段,包括匿名结构成员中的字段。
当使用负长度调用ArrayOf 函数时,会引发恐慌。
检查Type.ConvertibleTo 方法不再足以保证调用Value.Convert 不会出现恐慌。如果切片的长度小于N,则在将`[]T`转换为`*[N]T`时可能会触发panic。
运行时间/指标
添加了新指标来跟踪分配和释放的总字节数和对象。还添加了跟踪goroutine 调度延迟分布的新指标。
运行时/pprof
区块配置文件不再偏向于支持不频繁的长事件和频繁的短事件。
字符串转换
strconv 包现在使用Ulf Adams 的Ry 算法来格式化浮点数。该算法提高了大多数输入的性能,并且在最坏的情况下速度提高了99% 以上。
新的QuotedPrefix 函数返回输入开头的带引号的字符串(如Unquote 所理解的)。
字符串
Builder.WriteRune 方法现在为负符文值写入替换字符U+FFFD。
同步/原子
atomic.Value 为其他原子操作提供Swa 和CompareAndSwap 方法。
系统调用
获取Q
ueuedCompletionStatus和PostQueuedCompletionStatus功能现已弃用。这些函数具有不正确的签名golang.org/x/sys/windows打包。 在类Unix系统上,子进程的进程组现在设置为阻塞信号。这避免了发送SIGTTOU当父进程在后台进程组中时发送给子进程。 Windows版本的SysProcAttr有两个新字段:AdditionalInheritedHandles是新要子继承的附加句柄列表过程。ParentProcess允许指定新进程的父进程。 常数MSG_CMSG_CLOEXEC现在定义在DragonFly和所有OpenBSD系统(它已经在 一些 OpenBSD 系统和所有FreeBSD、NetBSD 和Linux 系统)。 常数SYS_WAIT6和WEXITED 现在在NetBSD 系统上定义(SYS_WAIT6曾是已经在DragonFly和FreeBSD系统上定义; EXITED已经在 Darwin、DragonFly、 FreeBSD、Linux 和 Solaris 系统)。 test 添加了一个新的测试标志 -shuffle它控制测试和基准测试的执行顺序。 新的T.Setenv和B.Setenv方法支持在持续时间内设置环境变量测试或基准。 text/template/parse 新的SkipFuncCheck Mode值将模板解析器更改为不验证函数是否已定义。 time Time类型新提供GoString方法用于在打印时返回更有用的值%#v格式说明符在 fmt打包。 新的Time.IsDST方法可以用来检查时间是否在其配置的位置处于夏令时。 新的Time.UnixMilli和Time.UnixMicro方法返回UTC时间1970年1月1日以来经过的毫秒数和微秒数。 新的UnixMilli和UnixMicro功能返回本地Time对应于给定的Unix时间。 该包现在接受逗号“,”作为解析和格式化时间时小数秒的分隔符。例如,以下时间格式是合法的: 2006-01-02 15:04:05,999999999 -0700 MSTMon Jan _2 15:04:05,000000 2006Monday, January 2 15:04:05,000 2006 新常数Layout定义参考时间。 unicode Is, IsGraphic, IsLetter, IsLower, IsMark, IsNumber, IsPrint, IsPunct, IsSpace, IsSymbol,和IsUpper函数对负符文值返false。
用户评论
这goroutine终于更新了!
有12位网友表示赞同!
一直在等这个版本啊!看眼表新增的功能,感觉很期待!
有8位网友表示赞同!
希望能优化一下GC性能吧,一直是Golang的痛点!
有8位网友表示赞同!
新版的API看起来很有意思,需要好好学习一下。
有8位网友表示赞同!
什么时候能看到基于新版本的开源游戏呢?
有9位网友表示赞同!
golang越来越强大啦!支持下Go语言!
有20位网友表示赞同!
这个版本修复了哪些bug啊?应该比较稳定了吧?
有6位网友表示赞同!
终于可以尝鲜了,下载体验一下!
有10位网友表示赞同!
1.17的发布会什么时候直播呢?想去看看
有6位网友表示赞同!
希望能对游戏开发有更大的帮助!
有16位网友表示赞同!
新的特性会不会影响到现有的项目兼容性啊?
有14位网友表示赞同!
感觉这版本针对开发者做了很多优化,好评!
有9位网友表示赞同!
玩游戏的也要关注技术更新嘛!
有6位网友表示赞同!
这个版本有哪些新游戏可以使用呢?分享一下吧!
有19位网友表示赞同!
一直喜欢用Golang开发,期待这个版本的发布很久了!
有11位网友表示赞同!
希望这版本能带来更多创新和惊喜!
有8位网友表示赞同!
这个版本对人工智能应用有什么帮助呢?!
有5位网友表示赞同!
新功能会带来哪些新的游戏体验呢?我很想知道!
有19位网友表示赞同!
对于新手来说,新版本的Golang入门是否更方便呢?
有11位网友表示赞同!
希望官方能够加大力度宣传推广!让更多人知道Golang。
有17位网友表示赞同!