2 回答
TA贡献1155条经验 获得超0个赞
我认为没有办法避免检查确定,但您可以对其进行重组以避免丑陋的中断:
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
}
因此,如果您有一个包含多个函数的案例,除非它们只返回一个值,否则您会被 if 和中断所困扰。
也就是说,(以及反思),在 Go 中编写迭代器的更惯用的方法是遍历通道。考虑等价的程序:
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)
}
}
在这种情况下,不要返回布尔值,只需在完成发送值时关闭通道即可。这种方法的缺点是如果你想返回多个值,你必须创建某种结构来通过通道发送。
最后,如果你想在每次运行迭代器时稍微包装一下以隐藏通道样板:
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)
}
}
这是初始实现的更多代码,但是每次要使用迭代器时都不必手动声明通道。
TA贡献1815条经验 获得超10个赞
我看不出你的例子与文件结束之前阅读的常见习语有何不同。例如,
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
func main() {
buf := bytes.NewBufferString("line1\nline2")
for {
line, err := buf.ReadString('\n')
if err != nil {
if err != io.EOF {
fmt.Println(err)
return
}
if len(line) == 0 {
break
}
}
line = strings.TrimSuffix(line, "\n")
fmt.Println(line)
}
}
输出:
line1
line2
你的例子对我来说看起来很惯用。
- 2 回答
- 0 关注
- 173 浏览
添加回答
举报