<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go 1.22 的新增功能系列之二:reflect.TypeFor

          共 2494字,需瀏覽 5分鐘

           ·

          2024-04-28 09:48

          Go 1.22 的第一個候選版本已經(jīng)發(fā)布,這意味著最終版本即將發(fā)布,現(xiàn)在是我在博客中介紹我在這個周期中所做工作的時候了。像往常一樣,我的貢獻(xiàn)很小,但它們是我的,所以我將從幕后的角度來談?wù)勊鼈儭J紫仁莚eflect.TypeFor。

          這是整個函數(shù):

          // TypeFor returns the [Type] that represents the type argument T.func TypeFor[T any]() Type {  return TypeOf((*T)(nil)).Elem()}

          很簡單!測試代碼比實際函數(shù)本身長大約十倍。

          當(dāng)您想要為某種類型創(chuàng)建 reflect.Type 對象時,例如 var intType = reflect.TypeFor[int]() 或 var errorType = reflect.TypeFor[error]() ,請使用此函數(shù)。

          將其添加到反射包中的提案由 Josh Bleecher Snyder 提出。它標(biāo)志著泛型通過標(biāo)準(zhǔn)庫的不斷進(jìn)步又邁出了一步。

          該提案最困難的部分可能是為該函數(shù)找到正確的名稱。 reflect.TypeOf 將是該函數(shù)最自然的名稱,但它已被現(xiàn)有函數(shù)用于創(chuàng)建 reflect.Type 對象。考慮的替代方案包括:

          • StaticTypeOf

          • MakeType

          • TypeOfT

          • TypeFrom

          • GetType

          • AsType

          • ToType

          • NewType

          • TheType

          • Types

          • ConstantType

          • T

          命名事物仍然是計算機(jī)科學(xué)中的兩個難題之一。

          我扔掉了獲勝的名字,但那時我們只是瀏覽所有可能的形容詞和介詞的列表,所以最終有人會選擇 TypeFor 。

          總的來說,我反對“無用地使用泛型”,即使用泛型函數(shù),即使它沒有添加任何類型安全性并且沒有或只有最小的長度節(jié)省。例如,制作 json.Marshal 的泛型版本對泛型來說是無用的,因為它實際上并沒有添加任何類型安全性。然而,在這種情況下,為接口構(gòu)建 reflect.Type 的正確方法相當(dāng)模糊,所以我認(rèn)為值得添加。

          這個問題可以追溯到 Go 中的反射第一定律:“反射從接口值到反射對象。”當(dāng)您調(diào)用 reflect.TypeOf(0) 時,您會得到您所期望的:類型 int 的 reflect.Type 對象。但如果您致電 reflect.TypeOf(err) ,您可能會對所得到的結(jié)果感到驚訝。您不會獲取包含類型 error 的對象,而是獲取具有底層具體類型 err 的對象。這是因為 error 是一個接口值,而 Go 中調(diào)用函數(shù)時,函數(shù)的接口參數(shù)會根據(jù)需要進(jìn)行轉(zhuǎn)換,所以錯誤接口丟失,只有具體值對 reflect.TypeOf 。更糟糕的是,如果 err 為零,您會從 reflect.TypeOf 返回零。

          Chris Siebenmann 對正在發(fā)生的事情以及如何解決它做了很好的解釋:

          因為 reflect.TypeOf() 傳遞了一個“ interface{} ”(現(xiàn)在也稱為“ any ”),所以它不能直接給你一個reflect.Type接口,因為該接口類型在轉(zhuǎn)換為“ interface{} ”時將會丟失。相反, reflect.TypeOf() 返回底層非接口類型(或 nil)。正如我們在“ nil ”只是某種類型的上下文中所看到的,要解決這個問題,您必須傳遞一個指向接口的指針(好吧,接口的值),返回類型“指向”的指針,然后再次通過反射取消引用原始類型......

          在 Go 1.22 之前,如果要為接口創(chuàng)建 reflect.Type ,解決方案是調(diào)用 reflect.TypeOf((*TheInterface)(nil)).Elem() 。這可行,但不是很直觀。我知道我很難在我自己的使用反射包的代碼中弄清楚它。

          當(dāng) reflect.TypeFor 被提出時,還有一個替代提案,它也添加了reflect.ValueOf函數(shù)的通用版本。我在問題評論中認(rèn)為這是一個錯誤:

          粗略地看一下標(biāo)準(zhǔn)庫,就會發(fā)現(xiàn)有許多地方可以用 reflect.T[whatever]() 來替換,以便更加清晰。reflect.GenericValueOf 更難限定,因為在某些地方接口類型顯然是我們想要的,但在很多情況下,底層的具體類型才是目標(biāo)。添加 reflect.GenericValueOf 會在閱讀代碼時增加一定程度的歧義:作者是否真的想要這里的接口類型,還是他們只是看到泛型并假設(shè)該函數(shù)更新,因此更好?它添加了第二種做事方式,但并沒有 100% 清楚其意圖。所以我傾向于在 reflect.T 上+1,但在 reflect.GenericValueOf 上+0。

          有時,Go 標(biāo)準(zhǔn)庫最好的東西就是所有被遺漏的東西。在我看來, reflect.GenericValueOf 會越過模糊線,變成“無用的泛型使用”。

          這就是 reflect.TypeFor 的故事。標(biāo)準(zhǔn)庫中的每個函數(shù)背后都有一個故事。

          瀏覽 264
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色国产在线 | 中国猛少妇xxxx猛交 | 日本黄色一级电影 | 天天干,天天射免费视频 | 土豪胖哥酒店微信高价的御范气质身材苗条匀称 |