3 回答
TA贡献1875条经验 获得超3个赞
在 Go 中,我们努力提高效率。不要做不必要的事情。
例如,
package main
import (
"bufio"
"bytes"
"fmt"
"os"
)
func main() {
lines, requestA := 0, 0
f, err := os.Open("request.log")
if err != nil {
fmt.Print("There has been an error!: ", err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
lines++
// filter request a
line := scanner.Bytes()
if len(line) <= 30 || line[30] != 'A' {
continue
}
if !bytes.Equal(line[22:], []byte("REQUEST-A")) {
continue
}
requestA++
request := string(line)
// handle request a
fmt.Println(request)
}
if err := scanner.Err(); err != nil {
fmt.Println(err)
}
fmt.Println(lines, requestA)
}
输出:
$ go run request.go
2019-09-30T04:17:02 - REQUEST-A
2019-09-30T04:20:02 - REQUEST-A
2019-09-30T04:21:02 - REQUEST-A
6 3
$ cat request.log
2019-09-30T04:17:02 - REQUEST-A
2019-09-30T04:18:02 - REQUEST-C
2019-09-30T04:19:02 - REQUEST-B
2019-09-30T04:20:02 - REQUEST-A
2019-09-30T04:21:02 - REQUEST-A
2019-09-30T04:22:02 - REQUEST-B
为了强调效率的重要性(日志可能非常大),让我们针对Markus W Mahlberg的解决方案运行一个基准测试:https://play.golang.org/p/R2D_BeiJvx9。
$ go test log_test.go -bench=. -benchmem
BenchmarkPeterSO-4 21285 56953 ns/op 4128 B/op 2 allocs/op
BenchmarkMarkusM-4 649 1817868 ns/op 84747 B/op 2390 allocs/op
log_test.go:
package main
import (
"bufio"
"bytes"
"regexp"
"strings"
"testing"
)
var requestLog = `
2019-09-30T04:17:02 - REQUEST-A
2019-09-30T04:18:02 - REQUEST-C
2019-09-30T04:19:02 - REQUEST-B
2019-09-30T04:20:02 - REQUEST-A
2019-09-30T04:21:02 - REQUEST-A
2019-09-30T04:22:02 - REQUEST-B
`
var benchLog = strings.Repeat(requestLog[1:], 256)
func BenchmarkPeterSO(b *testing.B) {
for N := 0; N < b.N; N++ {
scanner := bufio.NewScanner(strings.NewReader(benchLog))
for scanner.Scan() {
// filter request a
line := scanner.Bytes()
if len(line) <= 30 || line[30] != 'A' {
continue
}
if !bytes.Equal(line[22:], []byte("REQUEST-A")) {
continue
}
request := string(line)
// handle request a
_ = request
}
if err := scanner.Err(); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkMarkusM(b *testing.B) {
for N := 0; N < b.N; N++ {
var re *regexp.Regexp = regexp.MustCompile(`^(\S*) - REQUEST-A$`)
scanner := bufio.NewScanner(strings.NewReader(benchLog))
var res []string
for scanner.Scan() {
if res = re.FindStringSubmatch(scanner.Text()); len(res) > 0 {
_ = res[1]
}
}
if err := scanner.Err(); err != nil {
b.Fatal(err)
}
}
}
TA贡献1860条经验 获得超9个赞
使用以下代码打印值为“REQUEST-A”的日志条目的时间字段。
for scanner.Scan() {
line := scanner.Text()
if len(line) < 19 {
continue
}
if line[19:] == " - REQUEST-A" {
fmt.Println(line[:19])
}
}
要写入文件,请将 stdout 重定向到文件。
上面的代码假设时间戳之后的所有内容都是“-REQUEST-A”。如果“-REQUEST-A”是其他数据的前缀,请使用以下内容:
const lenTimestamp = 19
for scanner.Scan() {
line := scanner.Text()
if len(line) < lenTimestamp {
continue
}
if strings.HasPrefix(line[lenTimestamp:], " - REQUEST-A") {
fmt.Println(line[:lenTimestamp])
}
}
TA贡献1807条经验 获得超9个赞
如果您使用的是 Linux 或 Mac,则不需要 Go 程序:
$ echo "2019-09-30T04:17:02 - REQUEST-A
2019-09-30T04:18:02 - REQUEST-C
2019-09-30T04:19:02 - REQUEST-B
2019-09-30T04:20:02 - REQUEST-A
2019-09-30T04:21:02 - REQUEST-A
2019-09-30T04:22:02 - REQUEST-B" | awk '/REQUEST-A/{print $1}' | tee request.log
2019-09-30T04:17:02
2019-09-30T04:20:02
2019-09-30T04:21:02
然而,如果你真的想在 Go 中实现这个:
package main
import (
"bufio"
"fmt"
"regexp"
"strings"
)
const input = `
2019-09-30T04:17:02 - REQUEST-A
2019-09-30T04:18:02 - REQUEST-C
2019-09-30T04:19:02 - REQUEST-B
2019-09-30T04:20:02 - REQUEST-A
2019-09-30T04:21:02 - REQUEST-A
2019-09-30T04:22:02 - REQUEST-B
`
var scanner = bufio.NewScanner(strings.NewReader(input))
// Here comes the magic: We create an anonymous group containing all
// non-whitespace characters up to the first blank. Since it is
// a group, we can easily extract it later down the road.
var re *regexp.Regexp = regexp.MustCompile(`^(\S*) - REQUEST-A$`)
func main() {
var res []string
for scanner.Scan() {
// We use re.FindStringSubmatch here, as it actually kills two
// birds with one stone: We check wether it is REQUEST-A
// and the anonymous group of the regexp contains what we are looking for.
if res = re.FindStringSubmatch(scanner.Text()); len(res) > 0 {
fmt.Println(res[1])
}
}
}
- 3 回答
- 0 关注
- 130 浏览
添加回答
举报