我正在学习 go 语言并尝试使用golang重写我的一些Python代码。 我写了一个生成器函数,它逐行读取文本文件并发送(使用 yield 关键字)只有“有效”行(忽略空白行,重新构造未完成的行)。
示例文件(myfile.txt):
#123= FOOBAR(1.,'text');
#126= BARBAZ('poeazpfodsp',
234,56);
parse.py:
#!/usr/bin/python
def validlines(filename):
with open(filename) as fdin:
buff = ''
for line in fdin.readlines():
line = line.strip()
if line == '':
continue
buff += line
if line[-1] != ';':
continue
yield buff
buff = ''
fdin.close()
for line in validlines('myfile.txt'):
print(line)
显示:
#123= FOOBAR(1.,'text');
#126= BARBAZ('poeazpfodsp',234,56);
现在,我尝试使用golang中的闭包来完成相同的操作:
parse.go:
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func validLines(filename string) (func() (string, bool)) {
file, _ := os.Open(filename)
scanner := bufio.NewScanner(file)
return func() (string, bool) {
buff := ""
for scanner.Scan() {
line := scanner.Text()
line = strings.TrimSpace(line)
if line == "" {
continue
}
buff += line
if line[len(line)-1] != ';' {
continue
}
return buff, true
}
file.Close()
return "", false
}
}
func main() {
vline := validLines("myfile.txt")
for line, ok := vline(); ok; {
fmt.Println(line)
}
}
显示:
#123= FOOBAR(1.,'text');
#123= FOOBAR(1.,'text');
#123= FOOBAR(1.,'text');
#123= FOOBAR(1.,'text');
#123= FOOBAR(1.,'text');
#123= FOOBAR(1.,'text');
#123= FOOBAR(1.,'text');
...
在golang中正确的做法是什么?
答案 0 :(得分:6)
在Go中你可以使用频道而不是收益,这非常方便。
package main
curl -v orion:1026/v2/entities/Bcn-Welt/attrs/humidity/value --header "Accept: text/plain" --header "Accept: application/json"
* Hostname was NOT found in DNS cache
* Trying 172.17.0.13...
* Connected to orion (172.17.0.13) port 1026 (#0)
> GET /v2/entities/Bcn-Welt/attrs/humidity/value HTTP/1.1
> User-Agent: curl/7.35.0
> Host: orion:1026
> Accept: text/plain
> Accept: application/json
>
< HTTP/1.1 406 Not Acceptable
< Connection: Keep-Alive
< Content-Length: 73
< Content-Type: application/json
< Fiware-Correlator: 375fb1a8-232c-11e6-a21e-0242ac11000d
< Date: Thu, 26 May 2016 10:25:49 GMT
<
* Connection #0 to host orion left intact
{"error":"NotAcceptable","description":"accepted MIME types: text/plain"}
答案 1 :(得分:2)
只需添加pav5000's answer,您就应该对频道进行缓冲:
c:= make(chan string,1)
否则,它会将整个文件读入一个频道,没有必要使用它。
答案 2 :(得分:1)
这是你的主要的for
循环,这是问题所在。使用这种语法,它的作用如下:
line
ok
和vline()
ok
为真,则运行一次循环因此,您的问题是您永远不会更新line
和ok
。这是正确的版本:
for line, ok := vline(); ok; line, ok = vline() { ... }
答案 3 :(得分:1)
小变化:
func main() {
vline := validLines("myfile.txt")
line, ok := vline()
for ok {
fmt.Println(line)
line, ok = vline()
}
}