日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

你沒看錯,這里講的就是 Go 中的泛型。只不過還沒有正式發布,是基于草案設計的,已經是實現了可運行的版本。所以,泛型到來真的不遠了!

Go 中的泛型已經接近成為現實。本文講述的是泛型的最新設計,以及如何自己嘗試泛型。

 

Go的泛型真的要來了—如何使用以及它們是怎么工作的

 

Generics in Go —— How They Work and How to Play With Them

Go 由于不支持泛型而臭名昭著,但最近,泛型已接近成為現實。Go 團隊實施了一個看起來比較穩定的設計草案,并且正以源到源翻譯器原型的形式獲得關注。本文講述的是泛型的最新設計,以及如何自己嘗試泛型。

例子

FIFO Stack

假設你要創建一個先進先出堆棧。沒有泛型,你可能會這樣實現:

type Stack []interface{}
func (s Stack) Peek() interface{} {
 return s[len(s)-1]
}
func (s *Stack) Pop() {
 *s = (*s)[:len(*s)-1]
}
func (s *Stack) Push(value interface{}) {
 *s = Append(*s, value)
}

但是,這里存在一個問題:每當你 Peek 項時,都必須使用類型斷言將其從 interface{} 轉換為你需要的類型。如果你的堆棧是 *MyObject 的堆棧,則意味著很多 s.Peek().(*MyObject)這樣的代碼。這不僅讓人眼花繚亂,而且還可能引發錯誤。比如忘記 * 怎么辦?或者如果您輸入錯誤的類型怎么辦?s.Push(MyObject{})` 可以順利編譯,而且你可能不會發現到自己的錯誤,直到它影響到你的整個服務為止。

通常,使用 interface{} 是相對危險的。使用更多受限制的類型總是更安全,因為可以在編譯時而不是運行時發現問題。

泛型通過允許類型具有類型參數來解決此問題:

type Stack(type T) []T
func (s Stack(T)) Peek() T {
 return s[len(s)-1]
}
func (s *Stack(T)) Pop() {
 *s = (*s)[:len(*s)-1]
}
func (s *Stack(T)) Push(value T) {
 *s = append(*s, value)
}

這會向 Stack 添加一個類型參數,從而完全不需要 interface{}。現在,當你使用 Peek() 時,返回的值已經是原始類型,并且沒有機會返回錯誤的值類型。這種方式更安全,更容易使用。(譯注:就是看起來更丑陋,^-^)

此外,泛型代碼通常更易于編譯器優化,從而獲得更好的性能(以二進制大小為代價)。如果我們對上面的非泛型代碼和泛型代碼進行基準測試,我們可以看到區別:

type MyObject struct {
    X int
}
var sink MyObject
func BenchmarkGo1(b *testing.B) {
 for i := 0; i < b.N; i++ {
  var s Stack
  s.Push(MyObject{})
  s.Push(MyObject{})
  s.Pop()
  sink = s.Peek().(MyObject)
 }
}
func BenchmarkGo2(b *testing.B) {
 for i := 0; i < b.N; i++ {
  var s Stack(MyObject)
  s.Push(MyObject{})
  s.Push(MyObject{})
  s.Pop()
  sink = s.Peek()
 }
}

結果:

BenchmarkGo1
BenchmarkGo1-16     12837528         87.0 ns/op       48 B/op        2 allocs/op
BenchmarkGo2
BenchmarkGo2-16     28406479         41.9 ns/op       24 B/op        2 allocs/op

在這種情況下,我們分配更少的內存,同時泛型的速度是非泛型的兩倍。

合約(Contracts)

上面的堆棧示例適用于任何類型。但是,在許多情況下,你需要編寫僅適用于具有某些特征的類型的代碼。例如,你可能希望堆棧要求類型實現 String() 函數。這就是 Contracts :

contract stringer(T) {
 T String() string
}
type Stack(type T stringer) []T
// Now we can use the String method of T:
func (s Stack(T)) String() string {
 ret := ""
 for _, v := range s {
  if ret != "" {
   ret += ", "
  }
  ret += v.String()
 }
 return ret
}

更多示例

以上示例僅涵蓋了泛型的基礎知識。你還可以在函數中添加類型參數,并在合約(Contracts)中添加特定類型。

有關更多示例,你可以從兩個地方獲得:

設計草案

設計草案包含更詳細的描述以及更多示例:

https://go.googlesource.com/proposal/+/4a54a00950b56dd0096482d0edae46969d7432a6/design/go2draft-contracts.md,如果訪問不了,可以看我備份的:https://github.com/polaris1119/go_dynamic_docs/blob/master/go2draft-contracts.md。

實現原型的 CL

原型 CL 也有幾個示例。查找以“ .go2”結尾的文件:

https://go-review.googlesource.com/c/go/+/187317

如何嘗試泛型?

使用 WebAssembly Playground

到目前為止,嘗試泛型的最快,最簡單的方法是通過 WebAssembly Playground[1]。它使用 WASM 構建的源代碼到源代碼翻譯器原型在你的瀏覽器中直接運行 Go 代碼。但這存在一些限制(請參見 https://github.com/ccbrown/wasm-go-playground)。

編譯 CL

上面引用的 CL[2] 包含一個源到源轉換器的實現,該轉換器可用于將泛型代碼編譯為可以由 Go 的當前版本編譯的代碼。它將泛型代碼(“多態”代碼)稱為Go 2代碼,將非多態代碼稱為 Go 1 代碼,但是根據實現的細節,泛型可能會成為 Go 1 版本而不是 Go 2 版本的一部分。

它還添加了一個 “go2go” 命令,可用于從 CLI 轉換代碼。

你可以按照 Go 的從源代碼安裝 Go 指令來編譯 CL。當你到達可選的 “Switch to the master branch” 步驟時,請 用 checkout CL 代替:

git fetch "https://go.googlesource.com/go" refs/changes/17/187317/14 && git checkout FETCH_HEAD

請注意,這將檢出補丁集 14,這是撰寫本文時的最新補丁集。轉到 CL[3] 并找到“下載”按鈕以獲取最新補丁集的簽出命令。

編譯 CL 之后,可以使用 go/* 包編寫用于使用泛型的自定義工具,或者可以僅使用 go2go 命令行工具:

go tool go2go translate mygenericcode.go2

原文鏈接:https://blog.tempus-ex.com/generics-in-go-how-they-work-and-how-to-play-with-them/

作者:Chris Brown[4]

日期:2020-04-08

翻譯:polaris

參考資料

[1]WebAssembly Playground: https://ccbrown.github.io/wasm-go-playground/experimental/generics/

[2]CL: https://go-review.googlesource.com/c/go/+/187317

[3]CL: https://go-review.googlesource.com/c/go/+/187317

[4]Chris Brown: https://blog.tempus-ex.com/author/chris/

 

推薦閱讀

  • 你期待泛型嗎?為什么Go語言沒有泛型?何時會有?
  • Go和Rust的優缺點;預測Go1.16-1.19會支持泛型

分享到:
標簽:泛型
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定