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.pswp.cn/news/457390.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/457390.shtml
英文地址,請注明出處:http://en.pswp.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;為什么不能像命令行…