我有一个在轮询时返回值的函数,但是在某些时候它将停止返回明智的值,如下所示。

有没有比每次检查if !ok更为惯用的方式对其进行轮询。我在想类似于使用range轮询 channel 的方法。

package main

import "fmt"

func iter() func() (int, bool) {
    i := 0
        return func() (int, bool) {
        if i < 10 {
            i++
            return i, true
        }
        return i, false
    }
}

func main() {
    f := iter()
    for {
        v, ok := f()
        if !ok {
            break
        }
        fmt.Println(v)
    }
}

最佳答案

我认为没有办法避免检查正常,但是您可以对其进行重组,以免出现难看的中断:

for v,ok := f(); ok; v,ok = f() {
    fmt.Println(v)
}

应当指出,这仅在以下情况下有效:
  • 您有一个具有多个返回值要检查的函数,或者
  • 您有一个或多个函数,只有一个返回值来检查

  • 不幸的是Go不会让您做类似的事情
    f := iter()
    g := iter()
    v,ok,v2,ok2 := f(), g(); ok && ok2; v,ok,v2,ok2 := f(), g() {
       // code
    }
    

    因此,如果您的案例包含多个函数,那么除非它们仅返回一个值,否则它们会陷入ifs和break的困境。

    也就是说,(在反射时),在Go中编写迭代器的更惯用的方法是遍及整个 channel 。考虑等效程序:
    func Iterator(iterCh chan<- int) {
        for i := 0; i < 10; i++ {
           iterCh <- i
        }
        close(iterCh)
    }
    
    func main() {
        iter := make(chan int)
        go Iterator(iter)
        for v := range iter {
           fmt.Println(v)
        }
    }
    

    在这种情况下,不要返回 bool 值,而只要发送完值就关闭 channel 。此方法的缺点是,如果要返回多个值,则必须制作某种结构以通过 channel 发送。

    最后,如果您想对其进行包装,以在每次运行迭代器时隐藏 channel 样板:
    func Iter() <-chan int {
       iterChan := make(chan int)
       go iter(iterChan)
       return iterChan
    }
    func iter(iterCh chan<- int) {
        for i := 0; i < 10; i++ {
           iterCh <- i
        }
        close(iterCh)
    }
    
    func main() {
        for v := range Iter() {
           fmt.Println(v)
        }
    }
    

    这是用于初始实现的更多代码,但是省去了每次要使用迭代器时都必须手动声明 channel 的麻烦。

    关于go - 轮询功能的惯用方式,直到确定!= true,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17867305/

    10-16 12:26