欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言for-range函數(shù)使用技巧實(shí)例探究

 更新時(shí)間:2024年01月21日 10:16:36   作者:晁岳攀(鳥(niǎo)窩) 鳥(niǎo)窩聊技術(shù)  
這篇文章主要為大家介紹了Go語(yǔ)言for-range函數(shù)使用技巧實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Go range函數(shù)

Go 1.22 中可以 range 一個(gè)整數(shù),比如下面的代碼:

for i := range 10 {
    fmt.Println(i)
}

這個(gè)大家都已經(jīng)知道了,其實(shí)對(duì)應(yīng)的提案中還有一個(gè)隱藏的功能,就是可以 range 一個(gè)函數(shù),比如下面的代碼(摘自官方代碼庫(kù)internal/trace/v2/event.go[1]):

// Frames is an iterator over the frames in a Stack.
func (s Stack) Frames(yield func(f StackFrame) bool) bool {
 if s.id == 0 {
  return true
 }
 stk := s.table.stacks.mustGet(s.id)
 for _, f := range stk.frames {
  sf := StackFrame{
   PC:   f.pc,
   Func: s.table.strings.mustGet(f.funcID),
   File: s.table.strings.mustGet(f.fileID),
   Line: f.line,
  }
  if !yield(sf) {
   return false
  }
 }
 return true
}

就少有介紹了。

本文嘗試介紹它,讓讀者先了解一下,它在 Go 1.22 中是一個(gè)實(shí)驗(yàn)性的功能,還不確定未來(lái)在哪個(gè)版本中會(huì)被正式支持。

官方 wiki 中也有一篇介紹: Rangefunc Experiment[2],類(lèi)似問(wèn)答的形式,也是必讀的知識(shí)庫(kù)。

這個(gè)功能去年 Russ Cox 發(fā)起討論(#56413[3]), 并建立一個(gè)提案(#61405[4]),大家討論都很激烈啊,幾百次的討論,所以我也不準(zhǔn)備介紹前因后果了,直接了當(dāng)?shù)恼f(shuō)結(jié)論。 先前, for-range所能遍歷(迭代)的類(lèi)型很有限,只能是 slice、數(shù)組、map、字符串、channel 等。 現(xiàn)在,除了上面的五種類(lèi)型,還可以是整數(shù)和三種三種函數(shù)。

當(dāng)然for x := range n { ... }等價(jià)于for x := T(0); x < n; x++ { ... }, 其中 T 是 n 的類(lèi)型。這個(gè)大家都知道了。

range 的類(lèi)型

三個(gè)函數(shù)可能大家不是很了解,很正常,目前這只是一個(gè)實(shí)驗(yàn)性的功能。當(dāng)然 range 的類(lèi)型如下:

Range 表達(dá)式第一個(gè)值第二個(gè)值
array or slice a [n]E, *[n]E, or []Eindex i inta[i] E
string s string typeindex i intsee below rune
map m map[K]Vkey k Km[k] V
channel c chan E, <-chan Eelement e E
integer n integer typeindex i int
function, 0 values f func(func()bool) bool
function, 1 value f func(func(V)bool) boolvalue v V
function, 2 values f func(func(K, V)bool) boolkey k Kv V

本文介紹的就是后三種形式

三種可遍歷的函數(shù)

假設(shè)f是一個(gè)這樣的函數(shù):func(func()bool) bool, 那么for x := range f { ... }類(lèi)似于f(func(x T1, y T2) bool { ... }),其中 for 循環(huán)移動(dòng)到方法體中了。yield的 bool 返回值指示是否還要繼續(xù)遍歷。

對(duì)于這樣一個(gè)f,下面的格式都可以:

for x, y := range f { ... }
for x, _ := range f { ... }
for _, y := range f { ... }
for x := range f { ... }
for range f { ... }

下面是一個(gè)例子:

 var fn = func(yield func(k int, v byte) bool) {
  for i := 0; i < 26; i++ {
   if !yield(i, byte('a'+i)) {
    return
   }
  }
 }

 for k, v := range fn {
  fmt.Printf("%d: %c\n", k, v)
 }

運(yùn)行可以看到結(jié)果符合預(yù)期,我們遍歷了 26 個(gè)小寫(xiě)字母,注意 range 的數(shù)據(jù)類(lèi)型是我們的函數(shù):

這里,fn 這個(gè)函數(shù)沒(méi)有返回值,其實(shí)也可以有 bool 返回值,有 bool 返回值就可以組合多個(gè) range 函數(shù),可以容易寫(xiě)出復(fù)雜且難以維護(hù)的代碼,減少自己失業(yè)的可能。 這里的yield函數(shù)接收兩個(gè)參數(shù),第一個(gè)是int類(lèi)型,第二個(gè)是byte類(lèi)型,返回值是bool類(lèi)型,這個(gè)yield函數(shù)的返回值決定了是否繼續(xù)遍歷。當(dāng)然這里我們可以寫(xiě)泛型的程序,這里為了簡(jiǎn)單,就不寫(xiě)了。

下面是一個(gè)ffunc(func(V)bool) bool的例子:

    var fn = func(yield func(v byte) bool) {
        for i := 0; i < 26; i++ {
            if !yield(byte('a' + i)) {
                return
            }
        }
    }

    for v := range fn {
        fmt.Printf("%c\n", v)
    }

當(dāng)然 yield 函數(shù)也可以沒(méi)有參數(shù),比如func(func()bool) bool,下面這個(gè)例子就是無(wú)參數(shù)的形式,輸出結(jié)果是 26。

package main

import "fmt"

func main() {
 var fn = func(yield func() bool) {
  for i := 0; i < 26; i++ {
   if !yield() {
    return
   }
  }
 }

 var count int
 for range fn {
  count++
 }
 fmt.Println(count)
}

如果不使用 for-range 函數(shù)的形式,我們可以進(jìn)行改寫(xiě),比如兩個(gè)參數(shù)的列子:

 var fn = func(yield func(k int, v byte) bool) {
  for i := 0; i < 26; i++ {
   if !yield(i, byte('a'+i)) {
    return
   }
  }
 }

 fn(func(k int, v byte) bool {
  fmt.Printf("%d: %c\n", k, v)
  return true
 })

注意yield參數(shù)名稱(chēng)不是一個(gè)關(guān)鍵字,它只是一個(gè)普通的參數(shù)名稱(chēng),可以隨便取名字,但是為了模仿和其它語(yǔ)言中的generator,使用了yield這樣一個(gè)名稱(chēng),以至于代碼更加易讀。

看起來(lái)這個(gè)功能就是一個(gè)語(yǔ)法糖, 代碼rangefunc/rewrite[5]將 range-over-func 代碼寫(xiě)成非 range-over-func 代碼的形式。

為什么要這樣做?

標(biāo)準(zhǔn)庫(kù)中就有archive/tar.Reader.Nextbufio.Reader.ReadBytebufio.Scanner.Scancontainer/ring.Ring.Dodatabase/sql.Rowsexpvar.Doflag.Visitgo/token.FileSet.Iteratepath/filepath.Walkgo/token.FileSet.Iterateruntime.Frames.Next 和sync.Map.Range等各種遍歷的函數(shù),所以如果有一種統(tǒng)一的格式更好。

第三方庫(kù)中有更多的類(lèi)似代碼。

雖然這個(gè)功能還沒(méi)有正式支持,但是我看到有些庫(kù)摩拳擦掌準(zhǔn)備使用了,而sqlrange[6]更進(jìn)一步,已經(jīng)支持了。

當(dāng)然你使用它必須下載 Go 1.22 或者 gotip, 并且設(shè)置export GOEXPERIMENT=rangefunc。

它提供了QueryExec可遍歷函數(shù)。比如Query從一個(gè)表中查詢(xún)Point數(shù)據(jù):

type Point struct {
    X float64 `sql:"x"`
    Y float64 `sql:"y"`
}

for p, err := range sqlrange.Query[Point](db, `select x, y from points` "Point") {
    if err != nil {
        ...
    }
    ...
}

遍歷查詢(xún)和 ORM 一氣呵成。這里的資源管理是自動(dòng)的,底層的*sql.Rows遍歷完會(huì)自動(dòng)關(guān)閉。

參考文檔

[1]internal/trace/v2/event.go: https://github.com/golang/go/blob/97daa6e94296980b4aa2dac93a938a5edd95ce93/src/internal/trace/v2/event.go#L262 

[2]Rangefunc Experiment: https://go.dev/wiki/RangefuncExperiment 

[3]#56413: https://github.com/golang/go/discussions/56413 

[4]#61405: https://github.com/golang/go/issues/61405 

[5]rangefunc/rewrite: https://go.googlesource.com/go/+/refs/changes/41/510541/7/src/cmd/compile/internal/rangefunc/rewrite.go 

[6]sqlrange: https://github.com/achille-roussel/sqlrange 

以上就是Go語(yǔ)言for-range函數(shù)使用技巧實(shí)例探究的詳細(xì)內(nèi)容,更多關(guān)于go for-range函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文帶你掌握Golang中panic與recover的使用方法

    一文帶你掌握Golang中panic與recover的使用方法

    這篇文章主要介紹了Golang中panic與recover的作用和使用方法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的小伙伴可以參考一下
    2023-04-04
  • Go并發(fā)編程實(shí)現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng)

    Go并發(fā)編程實(shí)現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng)

    本文主要介紹了Go并發(fā)編程實(shí)現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 在Golang中讀寫(xiě)CSV文件的操作指南

    在Golang中讀寫(xiě)CSV文件的操作指南

    CSV(逗號(hào)分隔值)文件是一種常見(jiàn)的數(shù)據(jù)存儲(chǔ)格式,廣泛應(yīng)用于數(shù)據(jù)導(dǎo)入、導(dǎo)出、分析和交換等場(chǎng)景,在Golang中,有許多庫(kù)和工具可以幫助我們讀取和寫(xiě)入CSV文件,使數(shù)據(jù)處理變得簡(jiǎn)單而高效,本文將深入探討如何在Golang中使用標(biāo)準(zhǔn)庫(kù)以及第三方庫(kù)來(lái)讀寫(xiě)CSV文件
    2023-11-11
  • Go正則表達(dá)式匹配字符串,替換字符串方式

    Go正則表達(dá)式匹配字符串,替換字符串方式

    介紹了Go語(yǔ)言中使用正則表達(dá)式進(jìn)行字符串匹配和替換的方法,包括匹配單個(gè)子字符串和所有子字符串,個(gè)人經(jīng)驗(yàn)分享,旨在為讀者提供實(shí)用的編程技巧,并鼓勵(lì)大家支持腳本之家
    2025-02-02
  • GoLang?channel底層代碼分析詳解

    GoLang?channel底層代碼分析詳解

    Channel和goroutine的結(jié)合是Go并發(fā)編程的大殺器。而Channel的實(shí)際應(yīng)用也經(jīng)常讓人眼前一亮,通過(guò)與select,cancel,timer等結(jié)合,它能實(shí)現(xiàn)各種各樣的功能。接下來(lái),我們就要梳理一下GoLang?channel底層代碼實(shí)現(xiàn)
    2022-10-10
  • go語(yǔ)言制作端口掃描器

    go語(yǔ)言制作端口掃描器

    本文給大家分享的是使用go語(yǔ)言編寫(xiě)的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線(xiàn)程,有需要的小伙伴可以參考下。
    2015-03-03
  • Windows系統(tǒng)中搭建Go語(yǔ)言開(kāi)發(fā)環(huán)境圖文詳解

    Windows系統(tǒng)中搭建Go語(yǔ)言開(kāi)發(fā)環(huán)境圖文詳解

    GoLand?是?JetBrains?公司推出的商業(yè)?Go?語(yǔ)言集成開(kāi)發(fā)環(huán)境(IDE),這篇文章主要介紹了Windows系統(tǒng)中搭建Go語(yǔ)言開(kāi)發(fā)環(huán)境詳解,需要的朋友可以參考下
    2022-10-10
  • Golang并發(fā)編程之調(diào)度器初始化詳解

    Golang并發(fā)編程之調(diào)度器初始化詳解

    這篇文章主要為大家詳細(xì)介紹了Golang并發(fā)編程中關(guān)于調(diào)度器初始化的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-03-03
  • golang package time的用法具體詳解

    golang package time的用法具體詳解

    本篇文章主要介紹了golang package time的用法具體詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • 解決Golang time.Parse和time.Format的時(shí)區(qū)問(wèn)題

    解決Golang time.Parse和time.Format的時(shí)區(qū)問(wèn)題

    這篇文章主要介紹了解決Golang time.Parse和time.Format的時(shí)區(qū)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04

最新評(píng)論