Go true或false应该终止回调迭代吗?
在某些语言中,通过提供一个回调函数来进行迭代是必要的,或者更简洁,该函数接收项目并返回一个布尔值,指示是继续还是停止迭代 哪一个是表示希望停止/继续的首选值?为什么?有哪些先例 围棋的例子:Go true或false应该终止回调迭代吗?,go,foreach,callback,iteration,termination,Go,Foreach,Callback,Iteration,Termination,在某些语言中,通过提供一个回调函数来进行迭代是必要的,或者更简洁,该函数接收项目并返回一个布尔值,指示是继续还是停止迭代 哪一个是表示希望停止/继续的首选值?为什么?有哪些先例 围棋的例子: func IntSliceEach(sl []int, cb func(i int) (more bool)) (all bool) { for _, i := range sl { if !cb(i) { return false }
func IntSliceEach(sl []int, cb func(i int) (more bool)) (all bool) {
for _, i := range sl {
if !cb(i) {
return false
}
}
return true
}
哪一个是表示希望停止/继续的首选值
“继续”为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(确定)表示您应该继续。因此,我假设在您的示例中,这将是一种方式。前言:以下答案适用于回调函数,该函数根据当前项决定循环是否应提前终止-这就是您提出的问题 这不应与在有更多元素需要处理时进行处理和报告的函数混淆,其中
true
返回值通常被接受以表示有更多元素(这是一个很好的示例),其典型用途是:
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
将继续,因此如果您想提前终止,您必须明确地中断
,因此更常见的是干净的终止条件
但这是品味的问题。您可以选择任何您喜欢的方法,但重要的是以一种有意义的方式命名回调函数,它将清楚地说明其返回值的含义,因此查看代码(使用它的条件)将很容易理解
例如,以下名称是好的,返回值是明确的:
// 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
有错误
返回类型
回调不仅要测试,还要处理传递的项,这也是很常见的。在这些情况下,返回错误而不是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()
}
您的示例1不是回调函数(而是类型断言),您的示例2也不接受任何项,因此它不是测试函数,而是不断发展的功能。imho独立于具体实现是一个普遍的问题。顺便说一句,这种回调风格在大多数情况下并不惯用。实际上,这里真正重要的是函数的命名,它需要自我解释,以便读者理解返回值的含义。另一种方法是使用enum作为返回值,正如@icza在他的回答中所建议的那样。这些似乎是Go语言中支持true for continue的好例子。您描述的错误返回案例与我的要求最为接近。回调函数还处理该项。例如,请参见Javascript中iterable类型上使用的每个函数。