Go 1.18.1 Beta 尝鲜 泛型 FuzzTest workspace mode

Go 1.18.1 Beta 尝鲜

昨天,go 终于发布了 1.18 的 beta 版本, 带来了大家期待已久的泛型,抓紧时间康康能不能赶上热乎的。

下载地址

根据社区昨天发的 Go 1.18 Beta 1 is available, with generics 这次版本更新主要带来的新功能有:

  • 泛型
  • 模糊测试( fuzzing-based tests)
  • workspace mode
  • arm64 和 PPC64 也增加了基于寄存器的调用规约
  • 增加了一个 go version -m 可以记录构建细节
  • 其他,参见 draft release notes for Go 1.18

泛型

在没有泛型之前,假设我们需要求两个数的和,根据运算数的类型,可能需要写很多个函数,如:

package mainfunc SumInt64(a, b int64) int64 {return a + b}func SumFloat64(a, b int64) float64 {return a + b}

有了泛型之后就可以这样写了:

package mainfunc Sum2[V int | int64 | float64 | int32 | float32](a, b V) V {return a + b
}

上面的代码在 [] 中声明了一个泛型 V 它支持 int, int64, int32, float32, float64 五种类型,函数有两个 V 类型的参数 a 和 b 此外函数返回值也是 V 类型

我还是挺好奇如果传入的参数不是这五种会报什么错:

//go:build go1.18
// +build go1.18
package mainimport "fmt"func Sum2[V int64 | float64 | int32 | float32](a, b V) V {return a + b
}func main() {fmt.Println(Sum2[int](1, 2))
}

编译时报错:

# go1.18.1-beta/1.18-beta/generic/generic
.\main.go:20:21: int does not implement int64|float64|int32|float32

注意,在调用 Sum2 时,我们使用 [] 显示地制定了 Vint 类型,在编译器可以推断类型时,这个是可以省略的,也就是可以写作

func main() {fmt.Println(Sum2(1, 2))
}

但这并不是一直有用的,比如你要调用一个没有参数的泛型函数时,如:

func PI[V int | float64]() V {var v Vv = 10.0return v
}func main() {// fmt.Println(PI())  // .\main.go:28:16: cannot infer V fmt.Println(PI[float64]()) // 10
}

此外,都知道 go map 的 key 要求是可比较的类型,因此,go 新增了一个关键字 comparable 表明泛型是一个可比较类型, 当泛型参数作为 map 的 key 时,它必须是可比较的。

//go:build go1.18
// +build go1.18
package mainimport "fmt"func Sum[K comparable, V int64 | float64](m map[K]V) V {var sum Vfor k, v := range m {sum += vfmt.Println(k)}return sum
}func main() {fmt.Println(Sum(map[int64]float64{1: 2.3, 2: 3.3}))
}

是不是觉得每次 int | int64 | float64 | int32 | float32 写太麻烦了,确实,为此 go1.18 提供了泛型接口,你可以像定义接口一样定义一个泛型类型,就像:

type Number interface {int | int8 | int16 | int32 | int64 | float32 | float64
}

在这之后,你就可以使用 Number 来代替这一长串了

模糊测试

模糊测试 (fuzz testing, fuzzing)是一种软件测试技术。其核心思想是将自动或半自动生成的随机数据输入到一个程序中,并监视程序异常,如崩溃,断言(assertion)失败,以发现可能的程序错误,比如内存泄漏。模糊测试常常用于检测软件或计算机系统的安全漏洞。

—— wikipedia 模糊测试

可以看看官网的这个例子

func FuzzHex(f *testing.F) {for _, seed := range [][]byte{{}, {0}, {9}, {0xa}, {0xf}, {1, 2, 3, 4}} {f.Add(seed)}f.Fuzz(func(t *testing.T, in []byte) {enc := hex.EncodeToString(in)out, err := hex.DecodeString(enc)if err != nil {t.Fatalf("%v: decode: %v", in, err)}if !bytes.Equal(in, out) {t.Fatalf("%v: not equal after round trip: %v", in, out)}})
}

运行 go test -fuzz=Fuzz 即可进行模糊测试,用法和普通测试差不多,如果有需要请移步官方文档

workspace mode

这是非常爽的一个功能,想想这样一个场景,为了方便测试,你需要要改某一个功能(有时可能只是一个数值),但这个功能是一个单独的模块,通过 mod 引入,所以你下载了这个包,并用 replace 将其替换成了本地的路径,就像:

module go1.18.1-betago 1.18replace (github.com/json-iterator/go => /usr/bin/go/json-iterator/go
)

然后你就可以开心的改本地的模块了,但问题在于你每次提交代码时都需要回滚改过的 go.mod 否则大家就都用不了了……

workspace mode 就是解决了这样的问题,它引入了一个 go.work 文件,你可以在项目目录下执行 go work init . 来生成它,需要注意的是 workspace mode 只能用在 goMod 中,所以目录下必须有 go.mod 才能生成 go.work, 刚生成的文件内容类似:

go 1.18use ./.

go.work 中我们可以使用 replace:

go 1.18use ./.replace (github.com/json-iterator/go => /usr/bin/go/json-iterator/go
)

go 会优先选择 go.work 中的模块,这样你把 go.work 加入 .gitignore 就可以舒服地改代码了

再看看上面的文件,事实上,在提案上,只有三个元素:

The go.work file has three directives: the go directive, the directory directive, and the replace directive.

在 beta 版中, directory 被改成了 use, 这三个元素的作用是:

  • go: 指明一个 go 版本
  • use: 将包含go.mod文件的目录的绝对或相对路径作为参数。路径的语法与replace指令中的目录替换相同。路径必须是包含go.mod文件的模块目录。go.work文件必须至少包含一个use指令。
use (./tools // golang.org/x/tools./mod   // golang.org/x/mod
)
  • replace: 与 go mod 中的一样

可以简单的理解为 go.work 声明了一个工作目录,这个目录下的成员由 use 声明,在工作目录下执行构建时,会优先使用工作目录下的组件。

看这个例子

cd ~/project/go-beta/work
mkdir a b c
cd a
go mod init github.com/520MianXiangDuiXiang520/a
cd ../b
go mod init github.com/520MianXiangDuiXiang520/b
cd ../c
go mod init c
cd ..
go mod init work

当 work 引用 a b 时,由于这两个项目在 github 上不存在,所以之前只能使用 replace:

module workgo 1.18replace (github.com/520MianXiangDuiXiang520/a => ./agithub.com/520MianXiangDuiXiang520/b => ./bc => ./c
)require (github.com/520MianXiangDuiXiang520/a v0.0.0-00010101000000-000000000000github.com/520MianXiangDuiXiang520/b v0.0.0-00010101000000-000000000000c v0.0.0-00010101000000-000000000000
)

使用 workspace mode 后:

cd ~/project/go-beta/work
go work init . ./a ./b ./c

go mod 中可以只写:

module workgo 1.18

因为他们在同一个工作目录下

基于寄存器的调用规约

在 go 1.17 时就针对 X86-64 的处理器增加了这个,据说函数调用性能能提斯 20%,现在拓展到了 arm64 和 PPC64 但我没有这种处理器的电脑,不过可以对比一下旧版的函数调用方式:

package mainfunc demo(a int64, b int32, c int16, d int8) (int64, int32, int16, int8) {a += 111b += 222c += 333d += 89return a, b, c, d
}func main() {demo(0, 0, 0, 0)
}

在 go 1.14 的环境下,将上面的代码编译并输出汇编代码如下:

go build -gcflags="-l -S" main.go
"".demo STEXT nosplit size=55 args=0x20 locals=0x00x0000 00000 (E:go汇编\01.go:3)  TEXT    "".demo(SB), NOSPLIT|ABIInternal, $0-320x0000 00000 (E:go汇编\01.go:3)  PCDATA  $0, $-20x0000 00000 (E:go汇编\01.go:3)  PCDATA  $1, $-20x0000 00000 (E:go汇编\01.go:3)  FUNCDATA        $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (E:go汇编\01.go:3)  FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (E:go汇编\01.go:3)  FUNCDATA        $2, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (E:go汇编\01.go:4)  PCDATA  $0, $00x0000 00000 (E:go汇编\01.go:4)  PCDATA  $1, $00x0000 00000 (E:go汇编\01.go:4)  MOVQ    "".a+8(SP), AX0x0005 00005 (E:go汇编\01.go:4)  ADDQ    $111, AX0x0009 00009 (E:go汇编\01.go:8)  MOVQ    AX, "".~r4+24(SP)0x000e 00014 (E:go汇编\01.go:5)  MOVL    "".b+16(SP), AX0x0012 00018 (E:\桌面文件\笔记\Note\g o\go汇编\01.go:5)  ADDL    $222, AX0x0017 00023 (E:go汇编\01.go:8)  MOVL    AX, "".~r5+32(SP)0x001b 00027 (E:go汇编\01.go:6)  MOVWLZX "".c+20(SP), AX0x0020 00032 (E:go汇编\01.go:6)  ADDL    $333, AX0x0025 00037 (E:go汇编\01.go:8)  MOVW    AX, "".~r6+36(SP)0x002a 00042 (E:go汇编\01.go:7)  MOVBLZX "".d+22(SP), AX0x002f 00047 (E:go汇编\01.go:7)  ADDL    $89, AX0x0032 00050 (E:go汇编\01.go:8)  MOVB    AL, "".~r7+38(SP)0x0036 00054 (E:go汇编\01.go:8)  RET0x0000 48 8b 44 24 08 48 83 c0 6f 48 89 44 24 18 8b 44  H.D$.H..oH.D$..D0x0010 24 10 05 de 00 00 00 89 44 24 20 0f b7 44 24 14  $.......D$ ..D$.0x0020 05 4d 01 00 00 66 89 44 24 24 0f b6 44 24 16 83  .M...f.D$$..D$..0x0030 c0 59 88 44 24 26 c3                             .Y.D$&.

1.18 编译结果如下:

# command-line-arguments
"".demo STEXT nosplit size=20 args=0x10 locals=0x0 funcid=0x0 align=0x00x0000 00000 (E:\add.go:3)      TEXT    "".demo(SB), NOSPLIT|ABIInternal, $0-160x0000 00000 (E:\add.go:3)      FUNCDATA        $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (E:\add.go:3)      FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (E:\add.go:3)      FUNCDATA        $5, "".demo.arginfo1(SB)0x0000 00000 (E:\add.go:3)      FUNCDATA        $6, "".demo.argliveinfo(SB)0x0000 00000 (E:\add.go:3)      PCDATA  $3, $10x0000 00000 (E:\add.go:4)      ADDQ    $111, AX0x0004 00004 (E:\add.go:5)      ADDL    $222, BX0x000a 00010 (E:\add.go:6)      ADDL    $333, CX0x0010 00016 (E:\add.go:7)      ADDL    $89, DI0x0013 00019 (E:\add.go:8)      RET0x0000 48 83 c0 6f 81 c3 de 00 00 00 81 c1 4d 01 00 00  H..o........M...0x0010 83 c7 59 c3   

结果一目了然吧,两个都开了编译优化 -N 1.14 用的完全是栈, 1.18 用了四个寄存器: AX BX CX DI,那最多会用多少个寄存器呢?

# command-line-arguments
"".demo STEXT nosplit size=66 args=0x48 locals=0x0 funcid=0x0 align=0x00x0000 00000 (E:\add.go:3)      TEXT    "".demo(SB), NOSPLIT|ABIInternal, $0-720x0000 00000 (E:\add.go:3)      FUNCDATA        $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (E:\add.go:3)      FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)0x0000 00000 (E:\add.go:3)      FUNCDATA        $5, "".demo.arginfo1(SB)0x0000 00000 (E:\add.go:3)      FUNCDATA        $6, "".demo.argliveinfo(SB)0x0000 00000 (E:\add.go:3)      PCDATA  $3, $10x0000 00000 (E:\add.go:14)     MOVQ    "".j+8(SP), DX0x0005 00005 (E:\add.go:14)     ADDQ    $787, DX0x000c 00012 (E:\add.go:16)     MOVQ    DX, "".~r9+16(SP)0x0011 00017 (E:\add.go:5)      ADDQ    $111, AX0x0015 00021 (E:\add.go:6)      ADDL    $222, BX0x001b 00027 (E:\add.go:7)      ADDL    $333, CX0x0021 00033 (E:\add.go:8)      ADDL    $89, DI0x0024 00036 (E:\add.go:9)      ADDQ    $99, SI0x0028 00040 (E:\add.go:10)     ADDQ    $88, R80x002c 00044 (E:\add.go:11)     ADDQ    $999, R90x0033 00051 (E:\add.go:12)     ADDQ    $898, R100x003a 00058 (E:\add.go:13)     ADDQ    $989, R110x0041 00065 (E:\add.go:16)     RET0x0000 48 8b 54 24 08 48 81 c2 13 03 00 00 48 89 54 24  H.T$.H......H.T$0x0010 10 48 83 c0 6f 81 c3 de 00 00 00 81 c1 4d 01 00  .H..o........M..0x0020 00 83 c7 59 48 83 c6 63 49 83 c0 58 49 81 c1 e7  ...YH..cI..XI...0x0030 03 00 00 49 81 c2 82 03 00 00 49 81 c3 dd 03 00  ...I......I.....0x0040 00 c3     

答案是 9 个 超出的部分会按顺序放在栈上

go version

这个指令最基本的用法是查看 go 版本

E:\1.18-beta\as>go version
go version go1.18beta1 windows/amd64

但其实它还可以看 go 编译产物的构建版本信息,这次增加了一个 -m 参数:

E:\1.18-beta\as>go version -m add.exe
add.exe: go1.18beta1path    command-line-argumentsbuild   -compiler=gcbuild   -gcflags=-l -Sbuild   CGO_ENABLED=1build   CGO_CFLAGS=build   CGO_CPPFLAGS=build   CGO_CXXFLAGS=build   CGO_LDFLAGS=build   GOARCH=amd64build   GOOS=windowsbuild   GOAMD64=v1

参考

Go 1.18 Beta 1 is available, with generics

Tutorial: Getting started with generics

pkg.go.dev#Fuzzing

Proposal: Multi-Module Workspaces in cmd/go

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457390.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos7部署两个mysql_一文掌握mysql实用工具--pt-online-schema-change、innotop部署

概述因为OSC和innotop这两个需要的依赖包比较接近,所以这次就写一起了,下面介绍下完整的部署教程,以下基于centos7操作系统。官网文档:http://dev.mysql.com/doc/refman/5.7/en/innodb-create-index-overview.htmlOSC:…

python面试题目

问题一:以下的代码的输出将是什么? 说出你的答案并解释。 1234567891011121314class Parent(object):x 1class Child1(Parent):passclass Child2(Parent):passprint Parent.x, Child1.x, Child2.xChild1.x 2print Parent.x, Child1.x, Child2.xParent.x 3print …

修改页面后获得flag_互动征集丨是时候为2021立flag了

2020马上就要过去了今年的flag各位小伙伴实现了多少?翻出了生灰的flag擦擦说不定2021还能接着用哦2020年就要过去了还记得你在年初立下的那些Flag吗?减肥“明天我就开始减肥!”是大部分人在大部分时候都挂在嘴边的一句话疫情宅家不仅没减成还…

Python3.10 结构化模式匹配 PEP 634

Python3.10 结构化模式匹配 PEP 634 眼看 2021 马上结束,python 发布了它的 3.10 版本,优化了错误消息,上下文管理器等内容,但更吸引我的还是结构化模式匹配。 众所周之 switch 一直是 python 社区呼声比较高的一个功能&#xff…

为ESXI 添加ISCSI存储设备 Linux服务器系统

为ESXI 添加ISCSI存储设备 Linux系统本文使用的LINUX 6系统上一块硬盘制作的ISCSI存储设备其IP地址为:192.168.26.218:在系统上直接输入:yum -y install scsi-target-utils 命令 安装 iscsi分区设置我们将SDD这块硬盘的SDD1作为iscsi存储设备编辑ISCSI配…

出栈顺序 与 卡特兰数(Catalan)的关系

一,问题描述 给定一个以字符串形式表示的入栈序列,请求出一共有多少种可能的出栈顺序?如何输出所有可能的出栈序列? 比如入栈序列为:1 2 3 ,则出栈序列一共有五种,分别如下:1 2 3、…

[译] Bounds Check Elimination 边界检查消除

[译] Bounds Check Elimination 边界检查消除 Go 是一种内存安全的语言,在针对数组 (array) 或 Slice 做索引和切片操作时,Go 的运行时(runtime)会检查所涉及的索引是否超出范围。如果索引超出范围,将产生一个 Panic&…

cad多段线画圆弧方向_CAD箭头怎么画

CAD箭头怎么画问:CAD箭头怎么画?答:想要回答CAD箭头怎么画这个问题,得先从CAD多段线命令说起,画箭只是多段线的一种应用。执行CAD多段线命令的三种方式1.单击菜单栏上的"绘图">>"多段线"。2…

HDU 5410 CRB and His Birthday ——(完全背包变形)

对于每个物品&#xff0c;如果购买&#xff0c;价值为A[i]*xB[i]的背包问题。 先写了一发是WA的 。代码如下&#xff1a; 1 #include <stdio.h>2 #include <algorithm>3 #include <string.h>4 #include <set>5 using namespace std;6 typedef pair<…

一篇讲Java指令重排和内存可见性的好文

在这里&#xff1a; http://tech.meituan.com/java-memory-reordering.html 指令重排和内存可见性&#xff08;缓存不一致&#xff09;是两个不同的问题。 volatile关键字太强&#xff0c;即阻挡指令重排&#xff0c;又保证内存一致性。 unsafe.putOrderedXXX()只阻挡指令重排&…

php 获取delete蚕丝_php结合Redis实现100万用户投票项目,并实时查看到投票情况的案例...

场景&#xff1a;某网站需要对其项目做一个投票系统&#xff0c;投票项目上线后一小时之内预计有100万用户进行投票&#xff0c;希望用户投票完就能看到实时的投票情况这个场景可以使用redismysql冷热数据交换来解决。何为冷热数据交换&#xff1f;冷数据&#xff1a;之前使用的…

硬件内存模型 Hardware Memory Models

硬件内存模型 Hardware Memory Models (Memory Models, Part 1) Posted on Tuesday, June 29, 2021. 简介&#xff1a;童话的终结 很久以前&#xff0c;当人们还在写单线程程序的时候&#xff0c;让程序跑的更快的一个最有效的办法就是什么也不做&#xff0c;因为下一代硬件…

碰到日期题就怕的我来写一道水题吧

HDOJ-2005&#xff0c; http://acm.hdu.edu.cn/showproblem.php?pid2005 20XX系列的水题哈哈&#xff0c;写了二十分钟&#xff0c;就为找到一种比较正常不傻逼的写法。。。 嗯&#xff0c;学习了一下&#xff0c;闰年的判断可以写成一个接受参数的宏。 #define lev(n) (n%40&…

判断是否为gif/png图片的正确姿势

判断是否为gif/png图片的正确姿势 1.在能取到图片后缀的前提下 123456789//假设这是一个网络获取的URLNSString *path "http://pic3.nipic.com/20090709/2893198_075124038_2.gif";// 判断是否为gifNSString *extensionName path.pathExtension;if ([extensionName…

【Go】Map 的空间利用率统计

Go 中 map 利用率 今天刷 B 站看见有 Up 主在讲布隆过滤器&#xff0c;提到了利用率的问题&#xff0c;假设有一组数据&#xff0c;范围分布非常广&#xff0c;使用布隆过滤器时如何尽量少的减少内存使用&#xff0c;感觉除了针对特定数据的定向优化外没什么特别好的办法&…

ap模式和sta模式共存_AP+AC组网下的本地转发及集中转发

现在越来越多的企业都有自己的无线网络&#xff0c;而无线网络的组网方式一般都是使用ACAP模式进行组网&#xff0c;使用无线网络能够提供经济、高效的网络接入方式。相比有线网络&#xff0c;无线网络下只要能接入无线网的地方都可以使用网络&#xff0c;用户可以自由移动。而…

《JS权威指南学习总结--6.7属性的特性》

内容要点&#xff1a; 一.ES5中查询和设置属性的API 1.可以通过这些API给原型对象添加方法&#xff0c;并将它们设置成不可枚举的&#xff0c;这让它们看起来更像内置方法。 2.可以通过这些API给对象定义不能修改或删除的属性&#xff0c;借此 "锁定" 这个对象。 3.数…

【干货分享】流程DEMO-事务呈批表

流程名&#xff1a; 事务呈批表 业务描述&#xff1a; 办公采购、会议费用等事务的申请。流程发起时&#xff0c;会检查预算&#xff0c;如果预算不够&#xff0c;将不允许发起费用申请&#xff0c;如果预算够用&#xff0c;将发起流程&#xff0c;同时占用相应金额的预算&…

【译】TcMalloc: Thread-Caching Malloc

TcMalloc 的核心是分层缓存&#xff0c;前端没有锁竞争&#xff0c;可以快速分配和释放较小的内存对象&#xff08;一般是 256 KB&#xff09;前端有两种实现&#xff0c;分别是 pre-CPU 和 pre-Thread 模式&#xff0c;前者申请一块大的连续内存&#xff0c;每一个逻辑 CPU 将…

kotlin编译失败_Kotlin使用GraalVM开发原生命令行应用

背景之前用kotlin开发过一款根据建表DDL语句生成plantuml ER图的应用。被问如何使用&#xff0c;答曰"给你一个jar包&#xff0c;然后执行java -jar ddl2plantuml.jar ./ddl.sql ./er.puml 就可以了。是不是so easy?"结果被吐槽了一番&#xff0c;为什么不能像命令行…