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 關注
- 179 瀏覽
添加回答
舉報