精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Go 泛型接口的正確打開方式,看看幾個例子!

開發 前端
自從 Go 引入泛型以來,大家在泛型上最常討論的點之一就是?如何設計/使用約束(constraints)。甚至連 Go 官方都出了多篇博文來頻頻介紹這個知識點。

自從 Go 引入泛型以來,大家在泛型上最常討論的點之一就是 如何設計/使用約束(constraints)。

甚至連 Go 官方都出了多篇博文來頻頻介紹這個知識點。今天就來源于:

圖片圖片

我們知道泛型的類型參數可以被限制在 cmp.Orderedcomparable 之類的集合:

圖片圖片


但有一個容易被忽視的事實是:接口本身也是類型,它們也能有類型參數

這意味著我們可以用 “泛型接口” 來更優雅地表達某些約束關系,尤其是涉及 元素自身比較組合約束指針接收者 這些場景。

下面我們就結合以下幾個例子,結合著來快速理解這個特性。

從一個樹開始:比較與約束

假設我們要寫一個泛型二叉搜索樹。

最簡單的做法是直接用 cmp.Ordered

type Tree[E cmp.Ordered] struct {
    root *node[E]
}

func (t *Tree[E]) Insert(element E) {
    t.root = t.root.insert(element)
}

type node[E cmp.Ordered] struct {
    value E
    left  *node[E]
    right *node[E]
}

func (n *node[E]) insert(element E) *node[E] {
    if n == nil {
        return &node[E]{value: element}
    }
    switch {
    case element < n.value:
        n.left = n.left.insert(element)
    case element > n.value:
        n.right = n.right.insert(element)
    }
    return n
}

這樣寫很直觀,但有個問題:它只適用于內置可比較的類型(intstring 等)。

如果我想存 time.Time 呢?就用不了了。

常見解法是要求用戶傳一個比較函數:

type FuncTree[E any] struct {
    root *funcNode[E]
    cmp  func(E, E) int
}

func NewFuncTree[E any](cmp func(E, E) int) *FuncTree[E] {
    return &FuncTree[E]{cmp: cmp}
}

func (t *FuncTree[E]) Insert(element E) {
    t.root = t.root.insert(t.cmp, element)
}

這當然能跑,但有兩個缺點:

  • 必須顯式初始化,不能用零值直接用。
  • 調用 cmp 是函數調用,編譯器不太好內聯,性能可能受影響。

能不能換個思路?答案就是:泛型接口。

用泛型接口表達 “自比較”

如果我們定義一個接口:

type Comparer interface {
    Compare(Comparer) int
}

看似不錯,但寫起來很尷尬:方法參數是 Comparer,每個類型都要強轉回來,非常不 Go。

改進后:

type Comparer[T any] interface {
    Compare(T) int
}

這樣就好多了。比如 time.Time 有個 Compare(Time) int 方法,自然就實現了 Comparer[time.Time]

進一步,我們就能寫一個支持自比較的樹:

type MethodTree[E Comparer[E]] struct {
    root *methodNode[E]
}

func (t *MethodTree[E]) Insert(element E) {
    t.root = t.root.insert(element)
}

type methodNode[E Comparer[E]] struct {
    value E
    left  *methodNode[E]
    right *methodNode[E]
}

func (n *methodNode[E]) insert(element E) *methodNode[E] {
    if n == nil {
        return &methodNode[E]{value: element}
    }
    sign := element.Compare(n.value)
    switch {
    case sign < 0:
        n.left = n.left.insert(element)
    case sign > 0:
        n.right = n.right.insert(element)
    }
    return n
}

好處是:

  • time.Time 這種自帶 Compare 方法的類型直接能用。
  • 容器仍然支持零值初始化。

再和 map 結合:需要 comparable

如果我們想基于樹實現一個 OrderedSet,里面加個 map 來做 O(1) 查詢:

type OrderedSet[E Comparer[E]] struct {
    tree     MethodTree[E]
    elements map[E]bool
}

func (s *OrderedSet[E]) Has(e E) bool {
    return s.elements[e]
}

結果編譯報錯:

invalid map key type E (missing comparable constraint)

因為 Go 要求 map key 必須是 comparable

這時有三種寫法:

  1. 在 Comparer 接口里直接嵌入 comparable
  2. 定義一個新的 ComparableComparer 接口。
  3. 在 OrderedSet 類型參數約束里 inline:
type OrderedSet[E interface {
    comparable
    Comparer[E]
}] struct { ... }

哪種方式用,看團隊習慣,但推薦避免不必要的全局約束,盡量在具體類型上加。

泛型接口不必過度約束

再看一個常見場景。

定義一個通用集合接口:

type Set[E any] interface {
    Insert(E)
    Delete(E)
    Has(E) bool
    All() iter.Seq[E]
}

這里的泛型參數最好只約束成 any,而不是強加 comparable 或 Comparer,因為不同實現有不同需求。

例如基于 map 的實現必須要求 comparable,而基于 Tree 的則不需要。

指針接收者的坑

如果我們用 Set 來實現一個去重函數 Unique,會遇到一個尷尬點:

  • 有些實現(比如 OrderedSet)的方法用指針接收者。
  • 如果我們在泛型函數里聲明 var seen S,當 S 是 *OrderedSet 時,它會被初始化成 nil,調用就 panic。

解決方案是:用一個額外的類型參數約束“必須是某個類型的指針”:

type PtrToSet[S, E any] interface {
    *S
    Set[E]
}

func Unique[E, S any, PS PtrToSet[S, E]](...) { ... }

這樣寫雖然麻煩,但至少能表達出“S 的指針實現了 Set”這個語義。Go 編譯器還能幫我們推斷最后一個參數,使用時還算順手。

是否要約束指針接收者?

這類寫法會讓函數簽名變得很 “嚇人”。很多時候,我們其實不需要這么復雜的約束,可以換個角度:

例如,我們本來寫 Unique 想返回一個 iter.Seq[E],但其實它內部要構建一個集合,結果已經全存下來了,那干脆讓調用方自己傳 Set 進來就好:

func InsertAll[E any](set Set[E], seq iter.Seq[E]) {
    for v := range seq {
        set.Insert(v)
    }
}

這樣簡單明了,還能讓不同實現的 Set 都能復用。

例如,最簡單的 map 版:

type HashSet[E comparable] map[E]bool

func (s HashSet[E]) Insert(v E)       { s[v] = true }
func (s HashSet[E]) Delete(v E)       { delete(s, v) }
func (s HashSet[E]) Has(v E) bool     { return s[v] }
func (s HashSet[E]) All() iter.Seq[E] { return maps.Keys(s) }

用接口值,而不是復雜約束,往往更容易讀懂,也更靈活。

總結

泛型接口是個很有意思的工具,能幫我們更自然地表達一些約束關系。

以下是幾個要點:

  1. 可以用泛型接口來約束元素必須支持“和自己比較”。
  2. 組合 Comparer 和 comparable,能寫出更強大的容器類型。
  3. 接口定義最好保持寬松,把具體約束交給實現。
  4. 如果因為指針接收者搞出很復雜的泛型函數簽名,不妨退一步,改用接口值。

泛型給了 Go 更大的表達能力,但也帶來了復雜性。

當然,我還是建議能用簡單方案解決的,就別上太花哨的寫法。真的容易累人

責任編輯:武曉燕 來源: 腦子進煎魚了
相關推薦

2022-03-22 07:37:04

FeignSpringRibbon

2016-03-01 14:51:18

云計算DevOps

2016-01-08 11:00:14

OpenStack云計算

2019-02-20 14:35:57

區塊鏈數字貨幣比特幣

2021-11-25 07:43:56

CIOIT董事會

2023-07-10 09:38:06

兼容性測試方案

2017-08-02 10:43:39

深度學習TensorFlowRNN

2025-04-30 08:20:58

2021-11-10 16:03:42

Pyecharts Python可視化

2021-10-09 15:49:00

5G網絡技術

2018-10-29 15:20:03

2021-06-07 10:05:56

性能優化Kafka

2020-07-05 09:17:20

云桌面

2020-06-04 15:16:46

云計算

2022-06-22 09:06:54

CSS垂直居中代碼

2019-03-17 16:48:51

物聯網云計算數據信息

2021-01-11 10:47:09

IT部門網絡管理

2022-08-16 08:33:06

DevOps實踐

2018-07-03 09:41:23

數據庫系統 計算機

2020-05-09 10:35:06

遞歸面試算法
點贊
收藏

51CTO技術棧公眾號

91视频婷婷| 欧美成在线观看| 性欧美videossex精品| 成人亚洲综合天堂| 久久精品国产一区二区| 欧美成人免费观看| 无码人妻aⅴ一区二区三区| 国产亚洲一区二区手机在线观看| 一区免费观看视频| 久久riav| 99久久久久久久| 久久av最新网址| 美女福利精品视频| 日本精品在线观看视频| jizz性欧美23| 欧美日韩国产经典色站一区二区三区 | 51xx午夜影福利| 国产一级免费在线观看| 成人小视频在线| 成人免费午夜电影| 日日夜夜操视频| 狠狠噜噜久久| 久久福利视频网| 中文字幕第二区| 日韩动漫一区| 精品av久久707| www.com污| 韩国成人在线| 精品久久香蕉国产线看观看gif| 中文精品视频一区二区在线观看| 日本成人一区二区三区| 国产91精品欧美| 91午夜理伦私人影院| av手机天堂网| 亚洲一区二区毛片| 午夜精品久久久久久久白皮肤 | 午夜视黄欧洲亚洲| 看一级黄色录像| 日本中文字幕在线观看| 国产日韩欧美制服另类| 久久久人人爽| 天堂中文资源在线观看| 成人在线综合网站| 99久久国产免费免费| 国产老妇伦国产熟女老妇视频| 青青草国产成人av片免费| 日本久久久久久| 五月天综合激情网| 一区在线视频| 久久久中精品2020中文| 国产大片免费看| 午夜欧美理论片| 欧美大肥婆大肥bbbbb| 老湿机69福利| 欧美久色视频| 久精品免费视频| 美女视频黄免费| 亚洲午夜av| 97视频免费在线观看| 日韩在线视频免费播放| 国产日韩亚洲| 日韩美女免费观看| 在线免费观看av片| 国产一区二区三区国产| 亚洲在线视频福利| 秋霞网一区二区| 91色在线porny| 热舞福利精品大尺度视频| 成人18在线| 亚洲色图20p| 菠萝蜜视频在线观看入口| 黄页网站在线观看免费| 欧美日韩综合视频| 亚洲高清在线免费观看| 日日夜夜亚洲精品| 欧美mv和日韩mv国产网站| 小毛片在线观看| 精品久久久亚洲| 久久精视频免费在线久久完整在线看| 九九视频在线免费观看| 99热精品在线观看| 国产精品美乳一区二区免费 | 国产成人av福利| 精品乱色一区二区中文字幕| 毛片在线能看| 亚洲人成影院在线观看| 国产天堂视频在线观看| 欧美人与性动交xxⅹxx| 8v天堂国产在线一区二区| 亚洲成年人av| 欧美美女一区| 久久久久久久久网站| www.色国产| 国产精品一区二区久久不卡 | 在线一区免费| 97成人在线视频| 11024精品一区二区三区日韩| 国产成人99久久亚洲综合精品| 农村寡妇一区二区三区| 久草免费在线观看| 欧美性猛交xxxx乱大交极品| 日韩在线不卡一区| 天天做夜夜做人人爱精品| www.国产一区| 亚洲永久精品在线观看| 日本中文字幕一区二区有限公司| 9a蜜桃久久久久久免费| 92国产在线视频| 婷婷成人激情在线网| 污污动漫在线观看| 麻豆精品少妇| 久久亚洲综合国产精品99麻豆精品福利 | 91影院成人| 日韩av第一页| 日韩一级在线播放| 亚洲欧美激情小说另类| 波多野结衣作品集| 老牛影视av一区二区在线观看| 日韩中文字幕欧美| 精品人妻一区二区三区潮喷在线| 粉嫩一区二区三区性色av| 亚洲视频电影| 色天使综合视频| 日韩成人在线视频网站| 国产一级片视频| 国产在线一区二区综合免费视频| 日韩高清三级| 欧美xx视频| 精品无人国产偷自产在线| 青青草偷拍视频| 国产综合久久久久久鬼色 | 日本精品视频一区二区| 国产性生活毛片| 黄色成人在线网站| 91免费高清视频| 免费在线观看黄色| 欧美色图免费看| 亚洲精品国产精品国自产网站| 国产午夜久久| 久久99久久99精品蜜柚传媒| eeuss鲁一区二区三区| 欧美va亚洲va香蕉在线| 精品国产乱码久久久久久鸭王1| 久久99这里只有精品| 亚洲无玛一区| 999精品视频在线观看| 日韩中文字幕在线视频| 亚洲中文字幕一区二区| 国产精品久久久久久久裸模| 一区二区三区 日韩| 日韩成人激情| 成人做爽爽免费视频| 久草免费在线| 日韩精品一区二区三区中文精品| 国产精品久久久久久久精| 国产精品影视在线观看| 久操手机在线视频| 男人的天堂久久| 欧美又大又粗又长| 国产精品视频二区三区| 色94色欧美sute亚洲线路二| 天天舔天天操天天干| 老司机免费视频一区二区| 中文字幕在线亚洲精品| 精品国产一区二| 欧美激情亚洲综合一区| 无码国产精品一区二区免费16| 精品美女久久久久久免费| 国产精品jizz| 青青草国产成人av片免费 | 国产欧美日韩综合一区在线播放 | 国产精品免费久久久| 午夜视频在线看| 欧美一二区视频| 国产手机在线视频| 久久精品人人做人人综合| 日本在线播放一区二区| 一区在线视频观看| 日本在线高清视频一区| 精品视频一二| 26uuu亚洲伊人春色| 日韩免费网站| 亚洲精品在线网站| 制服丝袜在线一区| 亚洲免费伊人电影| aa一级黄色片| 激情文学综合插| 青青青免费在线| 欧美激情777| 国产一区二区在线网站| 日韩色淫视频| 韩日精品中文字幕| 在线观看国产原创自拍视频| 欧美精品一区二区三| 中文字幕 亚洲视频| 亚洲一区二区三区在线| 国产精品美女高潮无套| 国产成人av电影在线| 午夜免费福利在线| 在线成人黄色| 二级片在线观看| 少妇精品久久久| 99精品国产一区二区| 99精品在免费线偷拍| 国外成人性视频| 成人在线网址| 中文字幕亚洲一区| 四虎在线视频| 精品日韩一区二区三区| 国产精品成人久久久| 亚洲高清一区二区三区| 天海翼在线视频| 久久久www成人免费无遮挡大片 | 久久精品一区八戒影视| 日本在线视频播放| 蜜臀a∨国产成人精品| 毛片在线视频播放| 午夜日本精品| 蜜臀av.com| 欧美超碰在线| 日韩免费电影一区二区| 日韩理论电影中文字幕| 成人xxxxx色| 欧美高清hd| 91久久国产婷婷一区二区| 成人软件在线观看| 欧美一级高清免费播放| av中文字幕在线观看第一页| 欧美成人午夜免费视在线看片| 2021av在线| 亚洲视频在线观看| 男人的天堂在线| 精品爽片免费看久久| 在线观看xxx| 亚洲精品福利在线观看| 天天操天天干天天干| 欧美精品一区二区三| 人妻无码中文字幕| 精品国产91乱码一区二区三区| 精品人妻伦一二三区久久 | 午夜在线电影亚洲一区| 欧美日韩大片在线观看| 亚洲美女区一区| 成人免费视频网站在线观看| 国产精品一卡二| 日本精品久久久久久久久久| 日韩精品亚洲aⅴ在线影院| 成人激情视频网| 国产日本久久| 成人网欧美在线视频| 欧美亚洲黄色| 成人av番号网| 91麻豆精品一二三区在线| 国产精品你懂得| 亚洲成人激情社区| 国产精品成人v| abab456成人免费网址| 国产福利成人在线| 不卡亚洲精品| 国产日韩欧美在线| 91精品视频一区二区| 91超碰rencao97精品| 综合激情五月婷婷| 久久久久久高清| 欧美日韩xxxx| 自拍视频一区二区三区| 一级毛片免费高清中文字幕久久网| 看全色黄大色大片| 亚洲精选久久| 1024精品视频| 青娱乐精品视频在线| 在线观看中文av| 成人a区在线观看| 18禁裸乳无遮挡啪啪无码免费| 国产三级欧美三级日产三级99 | 在线日韩国产精品| 中文天堂在线播放| 日韩一区国产二区欧美三区| 成人免费公开视频| 亚洲男人的天堂在线播放| 91精品国产综合久久久久久豆腐| 久久精品成人一区二区三区| 黄色在线观看视频网站| 日本午夜人人精品| 亚洲成人1区| 国产美女精品在线观看| 欧美理论电影大全| 欧美高清中文字幕| 日韩高清一级片| 国产精品99久久久精品无码| 久久久久久久av麻豆果冻| 日韩精品123区| 岛国精品视频在线播放| 国产尤物在线观看| 亚洲激情电影中文字幕| 男人和女人做事情在线视频网站免费观看| 久久69精品久久久久久久电影好| 美女福利一区二区| 91大片在线观看| 欧美天天综合| 2018国产在线| 久久 天天综合| 90岁老太婆乱淫| 亚洲一区二区不卡免费| 日韩黄色片网站| 亚洲国产小视频在线观看| 麻豆传媒在线完整视频| 国产精品99一区| 2023国产精华国产精品| 亚洲一区二区三区乱码| 亚洲一区二区三区免费在线观看| 成人免费播放视频| 国产欧美日韩麻豆91| 日本视频免费在线| 日韩午夜精品电影| 免费在线观看av| 国产国语videosex另类| 成人福利一区| 特大黑人娇小亚洲女mp4| 肉色丝袜一区二区| 欧美激情 亚洲| 亚洲另类在线制服丝袜| 中文字幕乱码中文字幕| 亚洲另类欧美自拍| 极品美鲍一区| 国产精品香蕉视屏| 欧美午夜国产| 中文字幕55页| 综合久久综合久久| 亚洲天堂网视频| 在线看欧美日韩| 国产第一精品| 日韩欧美99| 奇米一区二区三区| av男人的天堂av| 色诱视频网站一区| 黄网在线观看| 国产精品爱久久久久久久| 一区二区三区韩国免费中文网站| 你懂的av在线| 99热国产精品| 国产www在线| 国产视频亚洲精品| xxx欧美xxx| 日本午夜精品一区二区| 手机精品视频在线观看| 久久久久亚洲av成人无码电影| 高潮白浆女日韩av免费看| 亚洲三级中文字幕| 日本亚洲欧洲色α| 国产一区二区在线| 国产 porn| 国产精品国产精品国产专区不蜜 | www深夜成人a√在线| 欧美日韩国产一区| 国产激情小视频在线| 91精品综合视频| 国产精品草草| 精品人妻一区二区三区香蕉| 一本到不卡精品视频在线观看| 国产一二三区在线| 国产日本欧美一区| 亚洲老妇激情| 屁屁影院国产第一页| 欧美午夜无遮挡| av电影在线观看一区二区三区| 成人在线视频福利| 欧美精品啪啪| 懂色av粉嫩av蜜乳av| 欧亚洲嫩模精品一区三区| 在线观看精品一区二区三区| 91久久精品久久国产性色也91| 欧美fxxxxxx另类| 一本加勒比波多野结衣| 在线免费一区三区| av毛片在线看| 精品在线一区| 毛片av一区二区| 久久黄色免费网站| 亚洲天堂成人在线| 玖玖玖电影综合影院| 131美女爱做视频| 亚洲国产岛国毛片在线| 亚洲高清视频网站| 国产99视频在线观看| 国产精品久久久乱弄 | 久久人91精品久久久久久不卡| 在线日本制服中文欧美| 国产农村妇女精品久久| 欧美日韩亚洲系列| 成人欧美在线| 欧洲精品国产| 国产高清不卡一区| 欧美特级黄色片| 国产综合在线视频| 99欧美视频| 国产ts丝袜人妖系列视频| 91精品国模一区二区三区| 日本免费一区二区三区四区| 免费日韩在线观看|