国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

簡(jiǎn)單易懂的 Go 泛型使用和實(shí)現(xiàn)原理介紹

開(kāi)發(fā)
本文是對(duì)泛型的基本思想及其在 Go 中的實(shí)現(xiàn)的一個(gè)比較容易理解的介紹,同時(shí)也是對(duì)圍繞泛型的各種性能討論的簡(jiǎn)單總結(jié)。

本文是對(duì)泛型的基本思想及其在 Go 中的實(shí)現(xiàn)的一個(gè)比較容易理解的介紹,同時(shí)也是對(duì)圍繞泛型的各種性能討論的簡(jiǎn)單總結(jié)。首先,我們來(lái)看看泛型所解決的核心問(wèn)題。

問(wèn)題

假設(shè)我們想實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 tree 數(shù)據(jù)結(jié)構(gòu)。每個(gè)節(jié)點(diǎn)持有一個(gè)值。在 Go 1.18 之前,實(shí)現(xiàn)這種結(jié)構(gòu)的典型方法如下:

type Node struct {
value interface{}
}

這在大多數(shù)情況下都很好用,但它也有一些缺點(diǎn)。

首先,interface{} 可以是任何東西。如果我們想限制 value 可能持有的類型,例如整數(shù)和浮點(diǎn)數(shù),我們只能在運(yùn)行時(shí)檢查這個(gè)限制。

func (n Node) IsValid() bool {
switch n.value.(type) {
case int, float32, float64:
return true
default:
return false
}
}

這樣并不可能在編譯時(shí)限制類型,像上面這樣的類型判斷在許多 Go 庫(kù)中都是很常見(jiàn)的做法。

第二,對(duì) Node 中的值進(jìn)行處理是非常繁瑣和容易出錯(cuò)的。對(duì)值做任何事情都會(huì)涉及到某種類型的斷言,即使你可以安全地假設(shè)值持有一個(gè) int 值。

number, ok := node.value.(int)
if !ok {
// ...
}

double := number * 2

這些只是使用 interface{} 的一些不便之處,它沒(méi)有提供類型安全,并有可能導(dǎo)致難以恢復(fù)的運(yùn)行時(shí)錯(cuò)誤。

解決方法

我們不打算接受任意數(shù)據(jù)類型或具體類型,而是定義一個(gè)叫做 T 的 占位符類型 作為值的類型。請(qǐng)注意,這段代碼還不會(huì)通過(guò)編譯。

type Node[T] struct {
value T
}

首先需要聲明泛型類型 T,這是在結(jié)構(gòu)或函數(shù)名稱后面方括號(hào)里面使用的。

T 可以是任何類型,只有在實(shí)例化一個(gè)具有明確類型的 Node 時(shí),T 才會(huì)被推導(dǎo)為該類型。

n := Node[int]{
value: 5,
}

泛型 Node 被實(shí)例化為 Node[int](整數(shù)節(jié)點(diǎn)),所以 T 是一個(gè) int。

類型約束

上面的實(shí)現(xiàn)里,T 的聲明缺少一個(gè)必要的信息:類型約束。

類型約束用于進(jìn)一步限制可以作為 T 的可能類型。Go 本身提供了一些預(yù)定義的類型約束,但也可以使用自定義的類型約束。

type Node[T any] struct {
value T
}

任意類型(any)約束允許 T 實(shí)際上是任何類型。如果節(jié)點(diǎn)值需要進(jìn)行比較,有一個(gè) comparable 類型約束,滿足這個(gè)預(yù)定義約束的類型可以使用 == 進(jìn)行比較。

type Node[T comparable] struct {
value T
}

任何類型都可以作為一個(gè)類型約束。Go 1.18 引入了一種新的 interface 語(yǔ)法,可以嵌入其他數(shù)據(jù)類型。

type Numeric interface {
int | float32 | float64
}

這意味著一個(gè)接口不僅可以定義一組方法,還可以定義一組類型。使用 Numeric 接口作為類型約束,意味著值可以是整數(shù)或浮點(diǎn)數(shù)。

type Node[T Numeric] struct {
value T
}

重獲類型安全

相對(duì)于使用 interface{},泛型類型參數(shù)的巨大優(yōu)勢(shì)在于,T 的最終類型在編譯時(shí)就會(huì)被推導(dǎo)出來(lái)。為 T 定義一個(gè)類型約束,完全消除了運(yùn)行時(shí)檢查。如果用作 T 的類型不滿足類型約束,代碼就不會(huì)編譯通過(guò)。

在編寫(xiě)泛型代碼時(shí),你可以像已經(jīng)知道 T 的最終類型一樣寫(xiě)代碼。

func (n Node[T]) Value() T {
return n.value
}

上面的函數(shù)返回 n.Value,它的類型是 T。因此,返回值是 T,如果 T 是一個(gè)整數(shù),那么返回類型就已知是 int。因此,返回值可以直接作為一個(gè)整數(shù)使用,不需要任何類型斷言。

n := Node[int]{
value: 5,
}

double := n.Value() * 2

在編譯時(shí)恢復(fù)類型安全使 Go 代碼更可靠,更不容易出錯(cuò)。

泛型使用場(chǎng)景

在 Ian Lance Taylor 的 When To Use Generics 中列出了泛型的典型使用場(chǎng)景,歸結(jié)為三種主要情況:

  • 使用內(nèi)置的容器類型,如 slices、maps 和 channels
  • 實(shí)現(xiàn)通用的數(shù)據(jù)結(jié)構(gòu),如 linked list 或 tree
  • 編寫(xiě)一個(gè)函數(shù),其實(shí)現(xiàn)對(duì)許多類型來(lái)說(shuō)都是一樣的,比如一個(gè)排序函數(shù)

一般來(lái)說(shuō),當(dāng)你不想對(duì)你所操作的值的內(nèi)容做出假設(shè)時(shí),可以考慮使用泛型。我們例子中的 Node 并不太關(guān)心它持有的值。

當(dāng)不同的類型有不同的實(shí)現(xiàn)時(shí),泛型就不是一個(gè)好的選擇。另外,不要把 Read(r io.Reader) 這樣的接口函數(shù)簽名改為 Read[T io.Reader](r T) 這樣的通用簽名。

性能

要了解泛型的性能及其在 Go 中的實(shí)現(xiàn),首先需要了解一般情況下實(shí)現(xiàn)泛型的兩種最常見(jiàn)方式。

這是對(duì)各種性能的深入研究和圍繞它們進(jìn)行的討論的簡(jiǎn)要介紹。你大概率不太需要關(guān)心 Go 中泛型的性能。

虛擬方法表

在編譯器中實(shí)現(xiàn)泛型的一種方法是使用 Virtual Method Table。泛型函數(shù)被修改成只接受指針作為參數(shù)的方式。然后,這些值被分配到堆上,這些值的指針被傳遞給泛型函數(shù)。這樣做是因?yàn)橹羔樋雌饋?lái)總是一樣的,不管它指向的是什么類型。

如果這些值是對(duì)象,而泛型函數(shù)需要調(diào)用這些對(duì)象的方法,它就不能再這樣做了。該函數(shù)只有一個(gè)指向?qū)ο蟮闹羔槪恢浪鼈兊姆椒ㄔ谀睦铩R虼耍枰粋€(gè)可以查詢方法的內(nèi)存地址的表格:Virtual Method Table。這種所謂的動(dòng)態(tài)調(diào)度已經(jīng)被 Go 和 Java 等語(yǔ)言中的接口所使用。

Virtual Method Table 不僅可以用來(lái)實(shí)現(xiàn)泛型,還可以用來(lái)實(shí)現(xiàn)其他類型的多態(tài)性。然而,推導(dǎo)這些指針和調(diào)用虛擬函數(shù)要比直接調(diào)用函數(shù)慢,而且使用 Virtual Method Table 會(huì)阻止編譯器進(jìn)行優(yōu)化。

單態(tài)化

一個(gè)更簡(jiǎn)單的方法是單態(tài)化(Monomorphization),編譯器為每個(gè)被調(diào)用的數(shù)據(jù)類型生成一個(gè)泛型函數(shù)的副本。

func max[T Numeric](a, b T) T {
// ...
}

larger := max(3, 5)

由于上面顯示的max函數(shù)是用兩個(gè)整數(shù)調(diào)用的,編譯器在對(duì)代碼進(jìn)行單態(tài)化時(shí)將為 int 生成一個(gè) max 的副本。

func maxInt(a, b int) int {
// ...
}

larger := maxInt(3, 5)

最大的優(yōu)勢(shì)是,Monomorphization 帶來(lái)的運(yùn)行時(shí)性能明顯好于使用 Virtual Method Table。直接方法調(diào)用不僅更有效率,而且還能適用整個(gè)編譯器的優(yōu)化鏈。不過(guò),這樣做的代價(jià)是編譯時(shí)長(zhǎng),為所有相關(guān)類型生成泛型函數(shù)的副本是非常耗時(shí)的。

Go 的實(shí)現(xiàn)

這兩種方法中哪一種最適合 Go?快速編譯很重要,但運(yùn)行時(shí)性能也很重要。為了滿足這些要求,Go 團(tuán)隊(duì)決定在實(shí)現(xiàn)泛型時(shí)混合兩種方法。

Go 使用 Monomorphization,但試圖減少需要生成的函數(shù)副本的數(shù)量。它不是為每個(gè)類型創(chuàng)建一個(gè)副本,而是為內(nèi)存中的每個(gè)布局生成一個(gè)副本:int、float64、Node 和其他所謂的 "值類型" 在內(nèi)存中看起來(lái)都不一樣,因此泛型函數(shù)將為所有這些類型復(fù)制副本。

與值類型相反,指針和接口在內(nèi)存中總是有相同的布局。編譯器將為指針和接口的調(diào)用生成一個(gè)泛型函數(shù)的副本。就像 Virtual Method Table 一樣,泛型函數(shù)接收指針,因此需要一個(gè)表來(lái)動(dòng)態(tài)地查找方法地址。在 Go 實(shí)現(xiàn)中的字典與虛擬方法表的性能特點(diǎn)相同。

結(jié)論

這種混合方法的好處是,你在使用值類型的調(diào)用中獲得了 Monomorphization 的性能優(yōu)勢(shì),而只在使用指針或接口的調(diào)用中付出了 Virtual Method Table 的成本。

在性能討論中經(jīng)常被忽略的是,所有這些好處和成本只涉及到函數(shù)的調(diào)用。通常情況下,大部分的執(zhí)行時(shí)間是在函數(shù)內(nèi)部使用的。調(diào)用方法的性能開(kāi)銷可能不會(huì)成為性能瓶頸,即使是這樣,也要考慮先優(yōu)化函數(shù)實(shí)現(xiàn),再考慮調(diào)用開(kāi)銷。

責(zé)任編輯:趙寧寧 來(lái)源: 開(kāi)源博客
相關(guān)推薦

2021-09-29 18:17:30

Go泛型語(yǔ)言

2022-04-15 09:55:59

Go 泛型Go 程序函數(shù)

2022-03-28 13:34:26

Go泛型部署泛型

2009-08-07 17:09:11

CLR泛型

2024-10-28 00:40:49

Go語(yǔ)法版本

2024-10-14 08:31:41

泛型策略模式

2011-07-12 16:00:39

java泛型

2009-09-02 18:03:19

C#實(shí)現(xiàn)泛型類

2011-07-10 13:45:35

JAVA泛型

2023-11-29 08:19:45

Go泛型缺陷

2022-10-24 00:48:58

Go語(yǔ)言errgroup

2021-10-18 10:53:26

Go 代碼技術(shù)

2019-02-11 08:32:22

編程語(yǔ)言Go

2021-11-27 22:20:13

SlicesGo泛型

2023-11-03 14:02:04

Go切片泛型庫(kù)

2021-08-09 10:36:20

GoSlices Maps

2025-08-07 01:22:00

Go泛型場(chǎng)景

2009-09-02 17:38:16

C#泛型支持

2017-03-06 16:51:52

Java泛型實(shí)現(xiàn)

2020-11-13 07:19:45

元編程模型Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲综合最新在线| 久久国产精品毛片| 波多野结衣中文字幕一区二区三区 | heyzo在线| xnxx国产精品| 91视频免费在线| 亚洲精品无播放器在线播放| 欧美日产在线观看| 韩国版免费三体| 丁香天五香天堂综合| 亚洲va欧美va国产综合剧情| 超碰97久久国产精品牛牛| 日韩精品免费综合视频在线播放| 久草视频在线播放| 久久久久综合网| 好色先生视频污| 狠狠综合久久| 国产精品免费一区豆花| 国产精品字幕| 亚洲精品xxx| av男人的天堂在线| 亚洲风情在线资源站| 中文字幕在线观看第三页| 狠狠色伊人亚洲综合成人| 国产欧美欧洲| 亚洲天天影视网| 中文字幕久久久av一区| 亚洲久久久久| 精品亚洲一区二区三区| 亚洲视频你懂的| 久久偷窥视频| 亚洲福利电影网| 99视频免费在线观看| 午夜久久99| 国产精品一区电影| 亚洲宅男一区| 日韩av免费在线看| 亚洲一区二区电影| 视频一区国产精品| 精精国产xxxx视频在线野外| 精品视频资源站| 一二三区在线观看| 亚洲自拍偷拍av| 在线观看av网站永久| 日韩亚洲欧美视频| 97国产成人高清在线观看| 国产精品9999| 久久在线电影| 成人动漫视频在线观看免费| 国产精品theporn| 久久久久se| 美腿丝袜亚洲综合| 青春草国产视频| 久久综合久久99| 美女久久久久久久久久久| 国产精品免费网站在线观看| h视频在线播放| 久久99精品久久久久久动态图| 欧美久久综合性欧美| 久久综合影音| 国产四区在线观看| 99久免费精品视频在线观看| 99在线看视频| 欧美视频完全免费看| 国产一区网站| 日韩三区在线观看| 欧美人与性动交α欧美精品济南到| 日韩免费在线观看| 欧美www.| 69久久夜色精品国产69乱青草| 国产精品午夜一区二区三区| 国产欧美在线看| 欧美在线网站| 国产精品日韩精品在线播放 | 国产成人影院| 国产一区欧美二区三区| 欧美日本一区| 亚洲精品一区二区三区四区五区| 国产精品 欧美精品| wwwwww99| 欧美日韩国产美| 免费视频观看成人| 国产精品一区二区电影| 国产欧美综合一区二区三区| 99在线精品免费视频| 亚洲国产成人va在线观看天堂| 成人高清免费在线| 美日韩精品视频免费看| 久久免费大视频| 中文字幕日韩精品一区二区| 自拍av一区二区三区| 91最新在线| 欧美床上激情在线观看| 欧美日韩91| 97国产精东麻豆人妻电影 | 一区二区日本伦理| 中文幕一区二区三区久久蜜桃| 大地资源中文在线观看免费版| 一区二区三区视频在线| 91亚洲人成网污www| 国产乱淫av片杨贵妃| 图片区小说区国产精品视频| 国产欧美一区二区三区精品酒店| 国产精品黄色影片导航在线观看| 久久国产精品色| 在线一区观看| 精品国产依人香蕉在线精品| 亚洲欧洲日本mm| 日韩一区二区三区久久| 亚洲国产一区二区三区在线观看| 欧美视频网址| 欧美 日本 亚洲| 欧美成人精品3d动漫h| 自拍亚洲一区| 欧美日韩中文字幕在线播放| 精品久久久精品| 欧美日本三级| 色阁综合av| 欧美日韩激情视频| 精品麻豆剧传媒av国产九九九| 欧美成人综合一区| 亚洲在线视频一区| 欧美.com| 99久久久精品视频| 日韩色在线观看| 欧美日韩亚洲国产精品| av网站在线不卡| 伊人男人综合视频网| 亚洲少妇自拍| 精品福利视频导航大全| 青青久久av北条麻妃海外网| 国产精品18久久久| 毛片大全在线观看| 国产欧美一区二区三区不卡高清| 黄色成人在线观看网站| 欧洲精品一区色| 欧美高清视频一二三区| 伊人色**天天综合婷婷| 超碰在线免费看| 97在线视频一区| 2024国产精品| 9999精品视频| 日本免费黄视频| 亚洲小视频在线观看| 韩国三级中文字幕hd久久精品| 91三级在线| 亚洲国产精品视频一区| 欧美一级一区二区| 久久成人免费| 青草在线视频| 青青草成人激情在线| 日韩午夜电影av| 免费观看30秒视频久久| 丁香花在线高清完整版视频| 性刺激综合网| 精品国产91久久久久久久妲己| 亚洲一区免费| 亚洲资源一区| 日本午夜精品一区二区三区| 3atv在线一区二区三区| 国产欧美精品久久| 四虎影院观看视频在线观看| 日韩av电影免费观看| 亚洲精品动漫久久久久| 久久精品99国产精品| 午夜欧美巨大性欧美巨大| 亚洲理论电影在线观看| 久久久久99精品久久久久| 国产午夜精品美女毛片视频| 欧美电影在线观看完整版| hbad中文字幕| 91精品国产综合久久久久久蜜臀 | 欧美三级日韩三级国产三级| 欧美 日韩 国产 一区| 1pondo在线播放免费| 日产精品久久久一区二区| 日韩麻豆第一页| 久久天天做天天爱综合色| 大奶在线精品| 亚洲字幕成人中文在线观看| 国产精品日韩一区二区| 精品欧美乱码久久久久久1区2区| 韩国女主播成人在线观看| 国产精品一区免费在线| 国产午夜电影| 99久久国产免费免费| 亚洲激情久久久| 久久久99久久| 99精品视频在线观看免费播放| huan性巨大欧美| 又大又硬又爽免费视频| 97色在线视频| 欧美视频精品在线| 国产精品99久久久久久有的能看 | 国产女大学生av| 国产97免费视| 日韩片之四级片| 久久久久久久久久美女| 欧美在线看片| 中韩乱幕日产无线码一区|