自定义scanner的分割函数
原理
splitFunc有go内置的4中,当然也支持自定义:
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
splitFUnc的功能就是:根据两个参数返回下一次Scan需要前进几个字节(advance),分割出来的数据(token),以及错误(err)。
参数:
-- data(字节切片): 缓冲区的有效数据
-- atEOF(bool): 是否已经输入完成(scanner是否扫描到源的结尾了),若没有则duplicate扩容!
返回值:
-- advance(int): Scan需要前进几个字节(advance)
-- token(字节切片): 分割出来的数据
-- err(error): 错误
返回值可以在go内置4个splitFunc的基础上获取:
例如scanWord:func bufio.ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)
扫描数字组(初始buffer小于数据量)
func scanIntGroup1() {
ir := strings.NewReader("10000000000 11111111111 12222222222 13333333333")
bs := bufio.NewScanner(ir)
// 再scanWords()基础上实现scanTelephoneNum()
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
fmt.Printf("scanner是否扫描到EOF:%t, 缓冲区有效数据的数量:%d, 有效数据的内容:%s\n", atEOF, len(data), data)
advance, token, err = bufio.ScanWords(data, atEOF)
// 没有错误且内容不为空的时候进行处理
if err == nil && token != nil {
_, err = strconv.ParseInt(string(token), 10, 64) // 将token中10进制的字符串转换为int64
if err != nil {
panic(err)
}
}
return
}
// 将scanner初始缓冲区长度设置为2字节,max to 65536
buf := make([]byte, 2)
bs.Buffer(buf, bufio.MaxScanTokenSize)
bs.Split(split)
// 读取
i := 1
for bs.Scan() {
fmt.Printf("扫描到的第%d个匹配项:%v\n", i, bs.Text())
i++
}
}
扫描数字组(初始buffer大于数据量)
func scanIntGroup2() {
ir := strings.NewReader("10000000000 11111111111 12222222222 13333333333")
bs := bufio.NewScanner(ir)
// 再scanWords()基础上实现scanTelephoneNum()
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
fmt.Printf("scanner是否扫描到EOF:%t, scanner扫描的数据长度:%d, scanner扫描数据的内容:%s\n", atEOF, len(data), data)
advance, token, err = bufio.ScanWords(data, atEOF)
// 没有错误且内容不为空的时候进行处理
if err == nil && token != nil {
_, err = strconv.ParseInt(string(token), 10, 64) // 将token中10进制的字符串转换为int64
if err != nil {
panic(err)
}
}
return
}
// 将scanner初始缓冲区长度设置为2字节,max to 65536
// buf := make([]byte, 2)
// bs.Buffer(buf, bufio.MaxScanTokenSize)
bs.Split(split)
// 读取
i := 1
for bs.Scan() {
fmt.Printf("扫描到的第%d个匹配项:%v\n", i, bs.Text())
i++
}
}
执行结果
func main() {
scanIntGroup1()
fmt.Println()
fmt.Println("---------------------------------gorgeous separator---------------------------------")
fmt.Println()
scanIntGroup2()
}
图片: