最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go 泛型中的 [0]func(T)的實(shí)現(xiàn)

 更新時(shí)間:2026年02月25日 09:18:32   作者:Kevin666  
本文主要介紹了Go 泛型中的 [0]func(T)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

很多 Go 泛型庫會(huì)在一個(gè)看似“空”的結(jié)構(gòu)體里塞一個(gè)很奇怪的字段:0 長度數(shù)組,元素類型是 函數(shù)且?guī)ь愋蛥?shù)。這不是炫技,而是在用編譯器幫你“堵住誤用”。

1. 先從一個(gè)真實(shí)需求出發(fā):可插拔的“比較策略”

假設(shè)你在寫一個(gè)泛型工具:對切片做去重、查找、或比較;你希望用戶可以自定義“怎么判斷兩個(gè)元素相等”。

package main

type Eq[T any] interface {
    Equal(a, b T) bool
}

type Finder[T any, E Eq[T]] struct {
    eq E
}

func (f Finder[T, E]) IndexOf(xs []T, target T) int {
    for i, v := range xs {
        if f.eq.Equal(v, target) {
            return i
        }
    }
    return -1
}

你還想給一個(gè)默認(rèn)實(shí)現(xiàn):當(dāng) T 可比較時(shí),直接用 ==。

type DefaultEq[T comparable] struct{}

func (DefaultEq[T]) Equal(a, b T) bool { return a == b }

到這里看起來很完美,對吧?但實(shí)際上它埋了兩個(gè)“類型安全”層面的坑。

2. 坑 A:不同T的默認(rèn)策略“長得一樣”,可能引發(fā)誤用

DefaultEq[int]DefaultEq[string] 在內(nèi)存布局上都是空結(jié)構(gòu)體struct{}。
空結(jié)構(gòu)體最大的特點(diǎn):沒有任何字段,于是很多時(shí)候“看起來完全相同”。

你在項(xiàng)目里做大規(guī)模泛型封裝時(shí),很可能出現(xiàn)這樣的情況:

  • 你把“默認(rèn)策略”作為參數(shù)、作為字段、作為返回值在很多地方傳遞
  • 有人(包括未來的你)做了一些泛型包裝/類型別名/反射/unsafe 或中間層抽象
  • 一旦某個(gè)環(huán)節(jié)把“策略類型”當(dāng)成“只是個(gè)空殼”,就容易出現(xiàn)“拿錯(cuò)策略也編譯過了”或“通過轉(zhuǎn)換繞過去”的情況

直觀理解:當(dāng)一個(gè)泛型類型實(shí)例化后仍然是空的,類型系統(tǒng)可約束的東西就少了,誤用空間就大。

我們想要的是:
DefaultEq[int]DefaultEq[string] 在“結(jié)構(gòu)上就不一樣”,從而盡量把錯(cuò)誤擋在編譯期。

3. 坑 B:策略對象被比較、被當(dāng)成 map key —— 這通常是 bug

策略對象(比如“比較器”“哈希器”“排序規(guī)則”)一般只承載行為,不承載數(shù)據(jù)。
如果它是一個(gè)可比較的空結(jié)構(gòu)體,那么下面這些“看起來合理但通常有坑”的寫法就能通過編譯:

// 例:把策略當(dāng)成 key 來緩存某些結(jié)果
// map[DefaultEq[int]]something  // 這在“空結(jié)構(gòu)體可比較”的情況下是可行的

更常見的是你寫了一個(gè)容器/緩存結(jié)構(gòu),未來某個(gè)改動(dòng)把策略對象塞進(jìn) struct,然后有人順手就 == 比較整個(gè) struct,結(jié)果“比較成功”但語義完全不對,bug 非常隱蔽。

我們希望:
策略對象最好不要支持 == 比較,這樣一旦有人試圖比較就立刻編譯失敗。

4. 解決方案:放一個(gè)“0 字節(jié)但類型強(qiáng)綁定”的字段

我們把默認(rèn)策略改成這樣:

type SaferDefaultEq[T comparable] struct {
    _ [0]func(T)
}

func (SaferDefaultEq[T]) Equal(a, b T) bool { return a == b }

這行字段同時(shí)完成兩件事:

4.1[0]...:0 長度數(shù)組,不占內(nèi)存(零運(yùn)行時(shí)成本)

[0]X 的大小永遠(yuǎn)是 0,不管 X 是什么。
所以這個(gè)字段不會(huì)讓 struct 變大,不會(huì)增加分配成本,也不會(huì)影響逃逸分析結(jié)果——它幾乎純粹是“給類型系統(tǒng)看的”。

4.2func(T):函數(shù)類型不可比較 → struct 也不可比較

在 Go 里:

  • 函數(shù)值(func(...))是不可比較類型
  • 如果一個(gè) struct 含有不可比較字段,那么這個(gè) struct 也不可比較

于是:

var a, b SaferDefaultEq[int]
// _ = (a == b) // 編譯錯(cuò)誤:該類型不可比較

這就把“策略對象被拿去比較/當(dāng) key”這種誤用直接扼殺在編譯期。

4.3func(T)里帶T:把類型參數(shù)“烙”進(jìn)結(jié)構(gòu)里

重點(diǎn)是 func(T) 這個(gè)字段類型包含了類型參數(shù) T。
當(dāng) T 不同,字段類型也不同:

  • SaferDefaultEq[int] 的字段是 [0]func(int)
  • SaferDefaultEq[string] 的字段是 [0]func(string)

它們在結(jié)構(gòu)層面不再“長得一樣”,從而更難在中間層被當(dāng)成可互換的東西(尤其是當(dāng)你有很多 wrapper、type alias、泛型適配器時(shí),這種“強(qiáng)區(qū)分”很值錢)。

5. 用一組“能看懂就懂”的對照實(shí)驗(yàn)

5.1 對照:空結(jié)構(gòu)體策略可以比較(常常不想要)

type PlainDefaultEq[T comparable] struct{}
func (PlainDefaultEq[T]) Equal(a, b T) bool { return a == b }

func compareStrategy() {
    var x, y PlainDefaultEq[int]
    _ = (x == y) // 可以編譯:但比較它通常沒有意義
}

5.2 加上_[0]func(T)后:比較直接被禁止

type StrictDefaultEq[T comparable] struct {
    _ [0]func(T)
}
func (StrictDefaultEq[T]) Equal(a, b T) bool { return a == b }

func compareStrategy2() {
    var x, y StrictDefaultEq[int]
    // _ = (x == y) // 編譯失?。翰豢杀容^(更安全)
}

5.3 依然 0 成本:對象大小不變(仍然等于 0)

空結(jié)構(gòu)體大小是 0;加了 [0]func(T) 仍然是 0。
(你可以用 unsafe.Sizeof 驗(yàn)證:兩者一般都為 0;放進(jìn)另一個(gè) struct 時(shí)也不會(huì)額外占空間——0 長度數(shù)組不會(huì)貢獻(xiàn)布局。)

6. 為什么不直接用其他“綁定 T 的辦法”?

你可能會(huì)問:我也可以寫這些?。?/p>

6.1_ T—— 不行,會(huì)占空間且需要值

type Tag[T any] struct { _ T } // 會(huì)占用 T 的大小,完全不零成本

6.2_ *T—— 會(huì)占一個(gè)指針大小

type Tag[T any] struct { _ *T } // 通常 8 字節(jié)(64 位)

6.3struct{}—— 0 成本,但綁定不夠“強(qiáng)”

type Tag[T any] struct { _ struct{} } // 0 成本,但沒把 T 烙進(jìn)字段類型

[0]func(T) 同時(shí)滿足:

  • 0 成本(0 字節(jié))
  • 強(qiáng)綁定 T(字段類型直接依賴 T)
  • 順手讓 struct 不可比較(因?yàn)?func 不可比較)

屬于“一個(gè)字段,三個(gè)收益”。

7. 什么時(shí)候你應(yīng)該用這種寫法?

適用場景(很典型):

  1. 策略/配置/適配器對象:比如 Equal/Hash/Compare/Encode/Decode 策略
  2. 你不希望它被 == 比較:比較往往無意義且易隱藏 bug
  3. 你希望不同類型參數(shù)的實(shí)例化在類型層面強(qiáng)區(qū)分:避免在多層封裝里被“當(dāng)成一樣的空殼”

不適用場景:

  • 你真的需要比較該類型的值(那就不要讓它不可比較)
  • 你需要該類型攜帶真實(shí)數(shù)據(jù)(那就直接加字段,不必玩標(biāo)簽)

8. 一個(gè)更完整的“使用姿勢”示例(仍然全新)

package main

type Eq[T any] interface {
    Equal(a, b T) bool
}

type StrictDefaultEq[T comparable] struct {
    _ [0]func(T)
}

func (StrictDefaultEq[T]) Equal(a, b T) bool { return a == b }

type Finder[T any, E Eq[T]] struct {
    eq E
}

func (f Finder[T, E]) Contains(xs []T, target T) bool {
    for _, v := range xs {
        if f.eq.Equal(v, target) {
            return true
        }
    }
    return false
}

func main() {
    f := Finder[int, StrictDefaultEq[int]]{eq: StrictDefaultEq[int]{}}
    _ = f.Contains([]int{1, 2, 3}, 2)
}

這個(gè)例子里:

  • 策略類型是 0 大?。◣缀趿愠杀荆?/li>
  • 策略對象不可比較(防誤用)
  • StrictDefaultEq[int]StrictDefaultEq[string] 是強(qiáng)區(qū)分的類型實(shí)體

9. 一句話總結(jié)

_ [0]func(T) 是一種 “零字節(jié)字段 + 強(qiáng)類型綁定 + 禁止比較” 的組合技巧。
它用極低的成本換來更強(qiáng)的編譯期約束,尤其適合做泛型庫里的“默認(rèn)策略/類型標(biāo)簽/行為適配器”。

到此這篇關(guān)于Go 泛型中的 [0]func(T)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go [0]func(T)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Go語言創(chuàng)建一個(gè)簡單的HTTP服務(wù)器的示例代碼

    使用Go語言創(chuàng)建一個(gè)簡單的HTTP服務(wù)器的示例代碼

    Go語言天生支持網(wǎng)絡(luò)編程,其標(biāo)準(zhǔn)庫 net/http 內(nèi)置了完整的 HTTP 協(xié)議處理能力,語法簡潔、性能優(yōu)越,本文我們將從零開始,用Go語言構(gòu)建一個(gè)基礎(chǔ)的 HTTP 服務(wù)器,掌握Go在服務(wù)端開發(fā)中的關(guān)鍵能力,需要的朋友可以參考下
    2025-07-07
  • Goland 關(guān)閉自動(dòng)移除未使用的包操作

    Goland 關(guān)閉自動(dòng)移除未使用的包操作

    這篇文章主要介紹了Goland 關(guān)閉自動(dòng)移除未使用的包操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go語言resty http包調(diào)用jenkins api實(shí)例

    Go語言resty http包調(diào)用jenkins api實(shí)例

    這篇文章主要為大家介紹了Go語言resty http包調(diào)用jenkins api實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Golang time.Sleep()用法及示例講解

    Golang time.Sleep()用法及示例講解

    Go語言中的Sleep()函數(shù)用于在至少規(guī)定的持續(xù)時(shí)間d內(nèi)停止最新的go-routine,這篇文章主要介紹了Golang time.Sleep()用法及示例講解,需要的朋友可以參考下
    2023-02-02
  • 淺談Golang中創(chuàng)建一個(gè)簡單的服務(wù)器的方法

    淺談Golang中創(chuàng)建一個(gè)簡單的服務(wù)器的方法

    這篇文章主要介紹了淺談Golang中創(chuàng)建一個(gè)簡單的服務(wù)器的方法,golang中的net/http包對網(wǎng)絡(luò)的支持非常好,這樣會(huì)讓我們比較容易的建立起一個(gè)相對簡單的服務(wù)器,有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • golang使用http client發(fā)起get和post請求示例

    golang使用http client發(fā)起get和post請求示例

    這篇文章主要介紹了golang使用http client發(fā)起get和post請求示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • GoLang string類型深入分析

    GoLang string類型深入分析

    string 作為 go 語言中的基礎(chǔ)類型,其實(shí)有一些需要反復(fù)揣摩的,可能是我們使用的場景太簡單,也可能是我們不需要那可憐的一點(diǎn)優(yōu)化來提高性能,對它也就沒那么上心了
    2023-01-01
  • go 代碼格式化和風(fēng)格開發(fā)者指南

    go 代碼格式化和風(fēng)格開發(fā)者指南

    這篇文章主要為大家介紹了go 代碼格式化和風(fēng)格開發(fā)者指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • golang調(diào)用藍(lán)兔支付實(shí)現(xiàn)網(wǎng)上支付功能

    golang調(diào)用藍(lán)兔支付實(shí)現(xiàn)網(wǎng)上支付功能

    支付寶、微信的網(wǎng)上支付需要營業(yè)執(zhí)照個(gè)人無法直接使用,如果個(gè)人需要實(shí)現(xiàn)網(wǎng)上支付功能,目前大部分應(yīng)該是都是依賴第三方聚合支付來實(shí)現(xiàn),本文就來介紹一下如何調(diào)用藍(lán)兔支付實(shí)現(xiàn)網(wǎng)上支付功能,有需要的可以參考下
    2023-09-09
  • Golang中的同步工具sync.Map示例詳解

    Golang中的同步工具sync.Map示例詳解

    sync.Map是Golang標(biāo)準(zhǔn)庫提供的并發(fā)安全的Map類型,可以在多個(gè)goroutine并發(fā)讀寫Map的場景下不需要加鎖,這篇文章主要介紹了Golang中的同步工具sync.Map詳解,需要的朋友可以參考下
    2023-05-05

最新評論

济阳县| 阿合奇县| 若尔盖县| 易门县| 常山县| 自治县| 尚志市| 静安区| 清涧县| 增城市| 高碑店市| 富源县| 祁阳县| 金坛市| 科技| 阳春市| 新安县| 曲阜市| 迁西县| 淳安县| 扶沟县| 丹棱县| 阜新市| 东安县| 镇康县| 沈阳市| 敦化市| 红原县| 泸水县| 塘沽区| 中宁县| 天柱县| 茌平县| 太湖县| 兰西县| 湖州市| 广东省| 上林县| 原阳县| 武义县| 隆德县|