日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Go 1.18.1 Beta 尝鲜 泛型 FuzzTest workspace mode

發(fā)布時(shí)間:2023/12/20 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go 1.18.1 Beta 尝鲜 泛型 FuzzTest workspace mode 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Go 1.18.1 Beta 嘗鮮

昨天,go 終于發(fā)布了 1.18 的 beta 版本, 帶來(lái)了大家期待已久的泛型,抓緊時(shí)間康康能不能趕上熱乎的。

下載地址

根據(jù)社區(qū)昨天發(fā)的 Go 1.18 Beta 1 is available, with generics 這次版本更新主要帶來(lái)的新功能有:

  • 泛型
  • 模糊測(cè)試( fuzzing-based tests)
  • workspace mode
  • arm64 和 PPC64 也增加了基于寄存器的調(diào)用規(guī)約
  • 增加了一個(gè) go version -m 可以記錄構(gòu)建細(xì)節(jié)
  • 其他,參見(jiàn) draft release notes for Go 1.18

泛型

在沒(méi)有泛型之前,假設(shè)我們需要求兩個(gè)數(shù)的和,根據(jù)運(yùn)算數(shù)的類型,可能需要寫(xiě)很多個(gè)函數(shù),如:

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

有了泛型之后就可以這樣寫(xiě)了:

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

上面的代碼在 [] 中聲明了一個(gè)泛型 V 它支持 int, int64, int32, float32, float64 五種類型,函數(shù)有兩個(gè) V 類型的參數(shù) a 和 b 此外函數(shù)返回值也是 V 類型

我還是挺好奇如果傳入的參數(shù)不是這五種會(huì)報(bào)什么錯(cuò):

//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)) }

編譯時(shí)報(bào)錯(cuò):

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

注意,在調(diào)用 Sum2 時(shí),我們使用 [] 顯示地制定了 V 是 int 類型,在編譯器可以推斷類型時(shí),這個(gè)是可以省略的,也就是可以寫(xiě)作

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

但這并不是一直有用的,比如你要調(diào)用一個(gè)沒(méi)有參數(shù)的泛型函數(shù)時(shí),如:

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 新增了一個(gè)關(guān)鍵字 comparable 表明泛型是一個(gè)可比較類型, 當(dāng)泛型參數(shù)作為 map 的 key 時(shí),它必須是可比較的。

//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})) }

是不是覺(jué)得每次 int | int64 | float64 | int32 | float32 寫(xiě)太麻煩了,確實(shí),為此 go1.18 提供了泛型接口,你可以像定義接口一樣定義一個(gè)泛型類型,就像:

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

在這之后,你就可以使用 Number 來(lái)代替這一長(zhǎng)串了

模糊測(cè)試

模糊測(cè)試 (fuzz testing, fuzzing)是一種軟件測(cè)試技術(shù)。其核心思想是將自動(dòng)或半自動(dòng)生成的隨機(jī)數(shù)據(jù)輸入到一個(gè)程序中,并監(jiān)視程序異常,如崩潰,斷言(assertion)失敗,以發(fā)現(xiàn)可能的程序錯(cuò)誤,比如內(nèi)存泄漏。模糊測(cè)試常常用于檢測(cè)軟件或計(jì)算機(jī)系統(tǒng)的安全漏洞。

—— wikipedia 模糊測(cè)試

可以看看官網(wǎng)的這個(gè)例子

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)}}) }

運(yùn)行 go test -fuzz=Fuzz 即可進(jìn)行模糊測(cè)試,用法和普通測(cè)試差不多,如果有需要請(qǐng)移步官方文檔

workspace mode

這是非常爽的一個(gè)功能,想想這樣一個(gè)場(chǎng)景,為了方便測(cè)試,你需要要改某一個(gè)功能(有時(shí)可能只是一個(gè)數(shù)值),但這個(gè)功能是一個(gè)單獨(dú)的模塊,通過(guò) mod 引入,所以你下載了這個(gè)包,并用 replace 將其替換成了本地的路徑,就像:

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

然后你就可以開(kāi)心的改本地的模塊了,但問(wèn)題在于你每次提交代碼時(shí)都需要回滾改過(guò)的 go.mod 否則大家就都用不了了……

workspace mode 就是解決了這樣的問(wèn)題,它引入了一個(gè) go.work 文件,你可以在項(xiàng)目目錄下執(zhí)行 go work init . 來(lái)生成它,需要注意的是 workspace mode 只能用在 goMod 中,所以目錄下必須有 go.mod 才能生成 go.work, 剛生成的文件內(nèi)容類似:

go 1.18use ./.

在 go.work 中我們可以使用 replace:

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

go 會(huì)優(yōu)先選擇 go.work 中的模塊,這樣你把 go.work 加入 .gitignore 就可以舒服地改代碼了

再看看上面的文件,事實(shí)上,在提案上,只有三個(gè)元素:

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

在 beta 版中, directory 被改成了 use, 這三個(gè)元素的作用是:

  • go: 指明一個(gè) go 版本
  • use: 將包含go.mod文件的目錄的絕對(duì)或相對(duì)路徑作為參數(shù)。路徑的語(yǔ)法與replace指令中的目錄替換相同。路徑必須是包含go.mod文件的模塊目錄。go.work文件必須至少包含一個(gè)use指令。
use (./tools // golang.org/x/tools./mod // golang.org/x/mod )
  • replace: 與 go mod 中的一樣

可以簡(jiǎn)單的理解為 go.work 聲明了一個(gè)工作目錄,這個(gè)目錄下的成員由 use 聲明,在工作目錄下執(zhí)行構(gòu)建時(shí),會(huì)優(yōu)先使用工作目錄下的組件。

看這個(gè)例子

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

當(dāng) work 引用 a b 時(shí),由于這兩個(gè)項(xiàng)目在 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 中可以只寫(xiě):

module workgo 1.18

因?yàn)樗麄冊(cè)谕粋€(gè)工作目錄下

基于寄存器的調(diào)用規(guī)約

在 go 1.17 時(shí)就針對(duì) X86-64 的處理器增加了這個(gè),據(jù)說(shuō)函數(shù)調(diào)用性能能提斯 20%,現(xiàn)在拓展到了 arm64 和 PPC64 但我沒(méi)有這種處理器的電腦,不過(guò)可以對(duì)比一下舊版的函數(shù)調(diào)用方式:

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 的環(huán)境下,將上面的代碼編譯并輸出匯編代碼如下:

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 編譯結(jié)果如下:

# 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

結(jié)果一目了然吧,兩個(gè)都開(kāi)了編譯優(yōu)化 -N 1.14 用的完全是棧, 1.18 用了四個(gè)寄存器: AX BX CX DI,那最多會(huì)用多少個(gè)寄存器呢?

# 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 個(gè) 超出的部分會(huì)按順序放在棧上

go version

這個(gè)指令最基本的用法是查看 go 版本

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

但其實(shí)它還可以看 go 編譯產(chǎn)物的構(gòu)建版本信息,這次增加了一個(gè) -m 參數(shù):

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

總結(jié)

以上是生活随笔為你收集整理的Go 1.18.1 Beta 尝鲜 泛型 FuzzTest workspace mode的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。