使用來自
ByteCounter
的思路,實現一個針對對單詞
和行數
的計數器golang
package main
import (
"bufio"
"bytes"
"fmt"
)
type Counter struct {
line int
word int
}
//implement the io.Writer interface
func (c *Counter) Write(p []byte) (int, error) {
line, err := counterLine(p)
if err != nil {
return 0, err
}
c.line += line
word, err := counterWord(p)
if err != nil {
return 0, nil
}
c.word += word
return len(p), nil
}
//implements the fmt.Stringer interface
func (c Counter) String() string {
return fmt.Sprintf("Counter has %d words and %d lines!\n", c.word, c.line)
}
func main() {
var str = "Spicy jalapeno pastrami ut ham turducken.\n " +
"Lorem sed ullamco, leberkas sint short loin strip steak ut shoulder shankle porchetta venison prosciutto turducken swine.\n " +
"Deserunt kevin frankfurter tongue aliqua incididunt tri-tip shank nostrud.\n"
var c Counter
fmt.Println(c)
fmt.Fprintf(&c, str)
fmt.Println(c)
}
//count the lines of the given strings
func counterLine(p []byte) (int, error) {
scan := bufio.NewScanner(bytes.NewReader(p))
scan.Split(bufio.ScanLines)
var line int
for scan.Scan() {
line++
}
if err := scan.Err(); err != nil {
return 0, err
}
return line, nil
}
//count the words of the given strings
func counterWord(p []byte) (int, error) {
scan := bufio.NewScanner(bytes.NewReader(p))
scan.Split(bufio.ScanWords)
var word int
for scan.Scan() {
word++
}
if err := scan.Err(); err != nil {
return 0, nil
}
return word, nil
}
//output:
//Counter has 0 words and 0 lines!
//Counter has 32 words and 3 lines!
複製代碼
寫一個帶有以下函數簽名的函數
CountingWriter
,傳入一個io.Writer
接口類型,返回一個新的Writer
類型把原來的Writer
封裝在裏面和一個表示寫入新的Writer
字節數的int64
類型指針
函數
package counter
import "io"
type byteWriter struct {
w io.Writer
written int64
}
func (b *byteWriter) Write(p []byte) (n int, err error) {
n, err = b.w.Write(p)
b.written += int64(n)
return
}
func CounterWriter(writer io.Writer) (io.Writer, *int64) {
c := &byteWriter{w: writer, written: 0}
return c, &c.written
}
複製代碼
package counter
import (
"bytes"
"testing"
)
func TestCounterWriter(t *testing.T) {
b := &bytes.Buffer{}
c, n := CounterWriter(b)
data := []byte("Hello golang!")
c.Write(data)
if l := len(data); *n != int64(l) {
t.Logf("%d != %d", *n, l)
t.Fail()
}
}
複製代碼