true或false应该终止回调迭代吗?

时间:2016-04-07 08:57:38

标签: go foreach callback iteration termination

在某些语言中,通过提供一个接收项的回调函数并返回一个指示是继续还是停止迭代的布尔值来进行迭代是必要的或更干净的。

表示希望停止/继续的首选值是多少?为什么?先例存在什么?

Go中的示例:

func IntSliceEach(sl []int, cb func(i int) (more bool)) (all bool) {
    for _, i := range sl {
        if !cb(i) {
            return false
        }
    }
    return true
}

2 个答案:

答案 0 :(得分:2)

  

表示希望停止/继续的首选值是什么?

如果继续

,则为true
  

为什么?

示例1:

func example(i interface{}) {
    if w, ok := i.(io.Writer); ok {
        // do something with your writer, ok indicates that you can continue
    }
}

示例2:

var sum int = 0
it := NewIntStatefulIterator(int_data)
for it.Next() {
    sum += it.Value()
}

在两种情况下,true(ok)表示您应该继续。所以我认为这是你的例子。

答案 1 :(得分:1)

前言:以下答案适用于回调函数,该回调函数根据当前项决定循环是否应该提前终止 - 这就是您所要求的。

这不要与进展的函数混淆,并报告是否有更多要处理的元素,其中通常接受true返回值来表示有更多元素(这是一个很好的例子, Scanner.Scan()),其典型用途是:

scanner := bufio.NewScanner(input)
for scanner.Scan() {
    // Process current item (line):
    line := scanner.Text()
    fmt.Println(line) // Do something with line
}

坚持bool返回类型

通常返回true以指示更容易阅读的代码中的终止结果。这是由于for的性质:如果你什么都不做,for会继续,所以如果你想提前终止,你必须明确地break,所以有一个干净的终止条件更多常见的。

但这是品味问题。您可以选择任何一种方式,但重要的是以有意义的方式命名您的回调函数,以明确说明其返回值的含义,从而查看代码(使用它的条件)将很容易理解。

例如,以下名称是好的,返回值是明确的:

// A return value of true means to terminate
func isLast(item Type) bool
func terminateAfter(item Type) bool
func abort(item Type) bool

// A return value of true means to continue (not to terminate)
func keepGoing(item Type) bool
func carryOn(item Type) bool
func processMore(item Type) bool

在易于理解的代码中使用这些结果:

for i, v := range vals {
    doSomeWork()
    if terminateAfter(v) {
        break // or return
    }
}

for i, v := range vals {
    doSomeWork()
    if !keepGoing(v) {
        break // or return
    }
}

// Or an alternative to the last one (subjective which is easier to read):

for i, v := range vals {
    doSomeWork()
    if keepGoing(v) {
        continue
    }
    break
}

作为反面例子,以下回调函数名称不好,因为你无法猜出它们的返回值是什么意思:

// Bad: you can't tell what return value of true means just by its name:
func test(item Type) bool
func check(item Type) bool

error返回类型

回调通常不仅仅是测试,而且还可以对传递的项目进行一些操作。在这些情况下,返回error而不是bool是有意义的。这样做,显然nil返回值表示成功(并继续),非nil值表示错误,处理应该停止。

func process(item Type) error

for i, v := range vals {
    if err := process(v); err != nil {
        // Handle error and terminate
        break
    }
}

具有类似枚举的返回值

此外,如果多个返回值有意义,您可以选择为返回值定义常量,您可以有意义地命名。

type Action int
const (
    ActionContinue Action = iota
    ActionTerminate
    ActionSkip
)

func actionToTake(item Type) Action

for i, v := range vals {
    switch actionToTake(v) {
    case ActionSkip:
        continue
    case ActionTerminate:
        return
    }
    doSomeWork()
}