我劝天公重抖擞,不拘一格降人才
今天是假期归来上班的第一天,不出所料,右边的同事果然没有按时来上班,虽然心里早已经有了结论,但是右边突然少了一个熟悉的人还是有点不适应。不到一年左右两边都已选择离开,只剩下我这个刚来不到一年的新人还在坚挺。左边同事的离开或多或少的跟组里的某些同事有关,而右边同事的离开一则与组里某些同事有关,最重要的问题还是因为待遇相关的问题,要不然右边的同事是不可能轻易的就离开已经呆了5年的公司。结合这两位同事的经历而言,一家公司如果想要留住优秀的人才,一方面既要做好团队文化的建设,另一方面也要提高相应的薪资待遇。否则人才早晚都会留不住。
go语言的bufio包
go语言的bufio包主要提供了一些操作io缓存流的函数和方法,下面将针对这些函数和方法展开讲解。
package main
/*********************************************************************/
/**************** golang中bufio包相关API讲解 ***********************/
/********************************************************************/
/*
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)
func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)
func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)
type ReadWriter
func NewReadWriter(r *Reader, w *Writer) *ReadWriter
type Reader
func NewReader(rd io.Reader) *Reader
func NewReaderSize(rd io.Reader, size int) *Reader
func (b *Reader) Buffered() int
func (b *Reader) Discard(n int) (discarded int, err error)
func (b *Reader) Peek(n int) ([]byte, error)
func (b *Reader) Read(p []byte) (n int, err error)
func (b *Reader) ReadByte() (byte, error)
func (b *Reader) ReadBytes(delim byte) ([]byte, error)
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
func (b *Reader) ReadRune() (r rune, size int, err error)
func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
func (b *Reader) ReadString(delim byte) (string, error)
func (b *Reader) Reset(r io.Reader)
func (b *Reader) Size() int
func (b *Reader) UnreadByte() error
func (b *Reader) UnreadRune() error
func (b *Reader) WriteTo(w io.Writer) (n int64, err error)
type Scanner
func NewScanner(r io.Reader) *Scanner
func (s *Scanner) Buffer(buf []byte, max int)
func (s *Scanner) Bytes() []byte
func (s *Scanner) Err() error
func (s *Scanner) Scan() bool
func (s *Scanner) Split(split SplitFunc)
func (s *Scanner) Text() string
type SplitFunc
type Writer
func NewWriter(w io.Writer) *Writer
func NewWriterSize(w io.Writer, size int) *Writer
func (b *Writer) Available() int
func (b *Writer) Buffered() int
func (b *Writer) Flush() error
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
func (b *Writer) Reset(w io.Writer)
func (b *Writer) Size() int
func (b *Writer) Write(p []byte) (nn int, err error)
func (b *Writer) WriteByte(c byte) error
func (b *Writer) WriteRune(r rune) (size int, err error)
func (b *Writer) WriteString(s string) (int, error)
*/
func main() {
/*********************************************************************/
/************************ Scanner的相关讲解 ************************/
/*******************************************************************/
//Scanner为读取数据提供了一些方便的数据接口,通过切割的方法可以逐
//字节、逐行、逐字、逐词组读取
/**
* ScanBytes()函数的作用是逐字节读取数据
*func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)
**/
/*
s := strings.NewReader("Hello world")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanBytes)
for bs.Scan(){
fmt.Printf("%s\n", bs.Text())
}
*/
/**
* 逐行读取数据
*func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)
**/
/*
s := strings.NewReader("Hello 世界\nhaha")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanLines)
for bs.Scan() {
fmt.Printf("%s\n", bs.Text())
}
*/
/**
× 逐字读取数据
*func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)
**/
/*
s := strings.NewReader("hello 世界")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanRunes)
for bs.Scan() {
fmt.Printf("%s\n", bs.Text())
}
*/
/**
* 逐词组读取数据
*func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)
**/
/*
s := strings.NewReader("hello world!")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanWords)
for bs.Scan() {
fmt.Printf("%s\n", bs.Text())
}
*/
/*********************************************************************/
/************************ ReadWriter的相关讲解 *********************/
/*******************************************************************/
/**
× 封装NewReaderWriter既可读也可写
*func NewReadWriter(r *Reader, w *Writer) *ReadWriter
**/
//NewReadWriter()封装r和w为一个bufio.ReadWriter对象
/*
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
s := strings.NewReader("123")
br := bufio.NewReader(s)
rw := bufio.NewReadWriter(br, bw)
p, _ := rw.ReadString('\n')
fmt.Printf("%s\n", string(p))
rw.WriteString("hello world")
rw.Flush()
fmt.Println(b)
*/
/*********************************************************************/
/************************ Reader的相关讲解 *************************/
/*******************************************************************/
//bufio包中定义的Reader结构
/*
type Reader struct {
buf []byte
rd io.Reader // reader provided by the client
r, w int // buf read and write positions
err error
lastByte int // last byte read for UnreadByte; -1 means invalid
lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}
*/
/*
fileName := "sdk/test.txt"
file, err := os.Open(fileName)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
*/
/**
* 读取数据存放于包装Reader中
*func NewReader(rd io.Reader) *Reader
**/
/*
//案例一
b := bufio.NewReader(file)
p := make([]byte, 1024)
n, err := b.Read(p)
fmt.Println(n)
fmt.Println(p[:n])
//案例二
b2 := bufio.NewReader(os.Stdin)
s, _ := b2.ReadString('\n')
fmt.Println(s)
*/
/**
* 将Reader封装成一个带指定大小的缓冲bufio.Reader对象,默认大小为16
*func NewReaderSize(rd io.Reader, size int) *Reader
**/
/*
reader := bufio.NewReaderSize(strings.NewReader("http://studygolang.com"), 16)
line, err := reader.ReadString('\n')
fmt.Printf("%s, %s\n", line, err)
*/
/**
* Buffered()方法的功能是返回可从缓冲区中读出数据的字节数
*func (b *Reader) Buffered() int
**/
/**
* Discard()方法的作用是跳过后续的n个字节的数据,返回跳过的字节数
*如果结果小于n则返回错误信息,如果n小鱼缓存中的数据长度,则不会从底层中提取数据
*func (b *Reader) Discard(n int) (discarded int, err error)
**/
/*
sr := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
buf := bufio.NewReaderSize(sr, 0)
b := make([]byte, 10)
fmt.Println(buf.Buffered())
s, _ := buf.Peek(5)
s[0], s[1], s[2] = 'a', 'b', 'c'
fmt.Printf("%d %q\n", buf.Buffered(), s)
buf.Discard(1)
for n, err := 0, error(nil); err == nil; {
n, err = buf.Read(b)
fmt.Printf("%d %q %v\n", buf.Buffered(), b[:n], err)
}
*/
/**
* Peek()方法返回缓存的一个切片,该切片应用缓存中前n个字节的数据,该操作不会讲数据读出,
*只是引用,引用的数据在下一次读取操作之前是有效的,如果切片长度小于n,
*则返回一个错误信息说明原因,如果
*n大于缓存的总大小,则返回ErrBufferFull。
*func (b *Reader) Peek(n int) ([]byte, error)
**/
/*
s := strings.NewReader("你好,世界!")
br := bufio.NewReader(s)
p, _ := br.Peek(3)
fmt.Println(p)
fmt.Println(string(p))
*/
/**
* Read()方法的作用是从b中读出数据存放到p中,返回读出的字节数和遇到的错误,
*如果缓存不为空,则只能读出缓存中存在的数据,不会从底层的io.Reader中读取,
*如果缓存中为空,则:
*1、如果len(p)>=缓存大小,则跳过缓存,直接从底层io.Reader中读出到p中
*2、如果len(p)<缓存大小,则现将数据从底层io.Reader中读取到缓存中,再从缓存中读取到p中
*func (b *Reader) Read(p []byte) (n int, err error)
**/
/*
s := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
br := bufio.NewReader(s)
p := make([]byte, 10)
n, _ := br.Read(p)
fmt.Println(n)
*/
/**
* ReadByte()方法的作用是从b中读取一个字节并返回,如果b中没有可读数据,则返回一个错误
*func (b *Reader) ReadByte() (byte, error)
**/
/*
s := strings.NewReader("ABCDEFG")
br := bufio.NewReader(s)
c, _ := br.ReadByte()
fmt.Println(c)
fmt.Println(string(c))
*/
/**
* ReadBytes()方法的作用是在b中查找delim并读出delim及其之前的所有的数据,
*如果ReadBytes在找到delim之前遇到错误,则返回遇到错误之前的所有数据,
*同时返回遇到的错误(一般为io.EOF),
*只有当ReadBytes找不到delim时, err才不会为nil
*func (b *Reader) ReadBytes(delim byte) ([]byte, error)
**/
/*
s := strings.NewReader("ABC DEF GHI JKL")
br := bufio.NewReader(s)
w, _ := br.ReadBytes(' ')
fmt.Println(w)
fmt.Println(string(w))
fmt.Printf("%q\n", w)
*/
/**
*ReadLine()方法是一个底层的按行读取原始操作.大多数用户应该使用ReadBytes('\n)或者
*ReadString('\n')或者使用Scanner.
*ReadLine尝试返回简单一行数据,不包括末尾字节.如果输入行对缓冲区来说太长,那么
*isPrefix会被设置为true,然后返回输入行的开头部分.
*输入行的剩下部分会在其它调用中返回.在返回输入行的最后一个片段时isPrefix会设置为false.
*函数是不可重入的,返回的缓冲区只在下次调用ReadLine
*前有效.ReadLine要不返回非空的行,要不返回一个错误,不会同时返回.
*ReadLine返回的文本不包括行末结束符("\r\n"或者"\n").如果输入流的末尾没有结束符,
*也不会有提示或者错误发生.在ReadLine之后调用UnreadByte
*也会标记最后一个字节未读(这个字节可能是属于行末结束符的一个字节),
*即使这个字节不是ReadLine返回的数据中的一部分.
*func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
**/
/*
s := strings.NewReader("123\n456")
r := bufio.NewReader(s)
line, flag , err := r.ReadLine()
fmt.Println(line, flag, err)
fmt.Println(string(line))
*/
/**
* ReadRune()方法的作用是读取单个 UTF-8 编码的 Unicode 字符,
*并以字节为单位返回符文及其大小。如果编码的符文无效,
*它将消耗一个字节并返回大小为1的 unicode.ReplacementChar (U+FFFD)。
*func (b *Reader) ReadRune() (r rune, size int, err error)
**/
/*
s := strings.NewReader("ABCD")
br := bufio.NewReader(s)
r, n, err := br.ReadRune()
fmt.Println(string(r))
fmt.Println(r, n, err)
*/
/**
* ReadSlice()方法的作用是
ReadSlice 读取直到输入中第一次出现 delim,返回指向缓冲区中字节的片段。
*字节在下次读取时停止有效。如果ReadSlice在查找分隔符之前遇到错误,
*它将返回缓冲区中的所有数据和错误本身(通常为 io.EOF)。如果缓冲区没有分隔符,
*则ReadSlice将失败并返回错误 ErrBufferFull 。因为从ReadSlice
返回的数据将被下一个I/O操作覆盖,所以大多数客户端应该使用ReadBytes
*或ReadString。ReadSlice 返回 err != nil 当且仅当该行不以 delim结束时。
*func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
*/
/*
s := strings.NewReader("asffghg\nsddfgf")
b := bufio.NewReader(s)
p, err := b.ReadSlice('\n')
fmt.Println(string(p))
fmt.Println(p, err)
*/
/**
* ReadString()方法的作用是ReadString 进行读取,直到输入中第一次出现 delim,
*返回一个包含数据的字符串直到并包含分隔符。
*func (b *Reader) ReadString(delim byte) (string, error)
**/
/*
s := strings.NewReader("ABC DEF GHI JKL")
b := bufio.NewReader(s)
str, _ := b.ReadString(' ')
fmt.Println(str)
fmt.Println(string(str))
fmt.Printf("%q\n", str)
*/
/**
* Reset()方法的作用是丢弃所有的缓存数据,重置所有的状态并且将缓存读切换到r
*func (b *Reader) Reset(r io.Reader)
**/
/*
s := strings.NewReader("ABCDEF")
str := strings.NewReader("123456")
br := bufio.NewReader(s)
b, _ := br.ReadString('\n')
fmt.Println(b)
br.Reset(str)
b, _ = br.ReadString('\n')
fmt.Println(b)
*/
/**
* Size()函数的作用是返回缓存区的大小(以字节为单位)
*func (b *Reader) Size() int
**/
/*
s := strings.NewReader("ABCDEF")
b := bufio.NewReader(s)
n := b.Size()
fmt.Println(n)
*/
/**
* UnreadByte()方法的作用是撤销最近一次读出的字节,只要有内容读出,
*就可以使用该方法撤销一个字节
*func (b *Reader) UnreadByte() error
**/
/*
s := strings.NewReader("ABCDEF")
b := bufio.NewReader(s)
c, _ := b.ReadByte()
fmt.Printf("%c\n", c)
c, _ = b.ReadByte()
fmt.Printf("%c\n", c)
b.UnreadByte()
fmt.Printf("%c\n", c)
*/
/**
* UnreadRune()方法的作用是返回最近一次调用的unicode码值,
*如果最经一次读取的不是调用的ReadRune,会返回错误
*func (b *Reader) UnreadRune() error
**/
/*
s := strings.NewReader("你好,世界")
b := bufio.NewReader(s)
c, size, _ := b.ReadRune()
fmt.Printf("%c %v\n", c, size)
c, size, _ = b.ReadRune()
fmt.Printf("%c %v\n", c, size)
b.UnreadRune()
c, size, _ = b.ReadRune()
fmt.Printf("%c %v\n", c, size)
*/
/**
* WriteTo()方法的作用是实现io.WriteTo,可能会多次调用底层Reader的Read方法
*func (b *Reader) WriteTo(w io.Writer) (n int64, err error)
**/
/*
s := strings.NewReader("ABCEFG")
br := bufio.NewReader(s)
b := bytes.NewBuffer(make([]byte, 0))
br.WriteTo(b)
fmt.Printf("%s\n", b)
*/
/*********************************************************************/
/*************************** Scanner的相关讲解 *********************/
/*******************************************************************/
/**
* NewScanner()函数的作用是创建并返回一个从r读取数据的Scanner,
*默认的分割函数是ScanLines.
* func NewScanner(r io.Reader) *Scanner
**/
/*
s := strings.NewReader("123446")
b := bufio.NewScanner(s)
for b.Scan() {
fmt.Printf("%s %v\n", b.Bytes(), b.Text())
}
*/
/*
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
fmt.Println(s.Text())
}
*/
/**
* Buffer()方法的作用是缓冲区设置扫描时要使用的初始缓冲区以及扫描期间
*可能分配的最大缓冲区大小。最大令牌大小是 max 和 cap(buf) 中较大的一个。
*如果 max <= cap(buf),扫描将仅使用此缓冲区并且不进行分配。
*func (s *Scanner) Buffer(buf []byte, max int)
**/
/*
input := "abcdefghijkl"
scanner := bufio.NewScanner(strings.NewReader(input))
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
fmt.Printf("%t\t%d\t%s\n", atEOF, len(data), data)
if atEOF {
return 0, nil, errors.New("bad luck")
}
return 0, nil, nil
}
scanner.Split(split)
buf := make([]byte, 12)
scanner.Buffer(buf, bufio.MaxScanTokenSize)
for scanner.Scan() {
fmt.Printf("%s\n", scanner.Text())
}
if scanner.Err() != nil {
fmt.Printf("error: %s\n", scanner.Err())
}
*/
/**
* Bytes()方法的作用是将最后一次扫描出的制定部分作为一个切片返回
*func (s *Scanner) Bytes() []byte
**/
/*
s := strings.NewReader("adsdfghghjhj")
scanner := bufio.NewScanner(s)
for scanner.Scan() {
fmt.Printf("%s %v\n", scanner.Bytes(), scanner.Text())
}
*/
/**
* Err方法的作用是返回扫描仪遇到的第一个非EOF错误
*func (s *Scanner) Err() error
*/
/*
s := strings.NewReader("asdffgfgh")
scanner := bufio.NewScanner(s)
for scanner.Scan() {
fmt.Printf("%s\n", scanner.Err())
if scanner.Err() != io.EOF {
fmt.Println("NOT io.EoF ERROR")
}
}
*/
/**
* Scan方法的作用是获取当前位置的token(该token可以通过Bytes或者Text方法进行获取),
*并让Scanner的扫描位置移动到下一个token,当扫抵达输入流结尾或者遇到错误而停止时,
*本方法会返回false,
*在Scan方法返回false后,Err方法将返回扫描时遇到的任何的错误,除非是io.EOF,此时返回nil
*func (s *Scanner) Scan() bool
*/
/*
s := strings.NewReader("asffgghjhjhjk")
scanner := bufio.NewScanner(s)
flag := scanner.Scan()
fmt.Println(flag)
*/
/**
* split方法的作用是设置该Scanner()的分割函数,本方法必须在Scan之前调用
*func (s *Scanner) Split(split SplitFunc)
*/
/*
const input = "1234 5678 1234567901234567"
scanner := bufio.NewScanner(strings.NewReader(input))
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
advance, token, err = bufio.ScanWords(data, atEOF)
if err == nil && token != nil {
_, err = strconv.ParseInt(string(token), 10, 32)
}
return
}
scanner.Split(split)
for scanner.Scan() {
fmt.Printf("%s \n", scanner.Text())
}
*/
/**
* Text()方法的作用是返回最近一次scan调用生成的token,
*会创建一个字符串并返回
*func (s *Scanner) Text() string
*/
/*
s := strings.NewReader("asvgfgghgjh\nsddgffgfg")
scanner := bufio.NewScanner(s)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
*/
/*********************************************************************/
/*************************** Writer的相关讲解 ***********************/
/*******************************************************************/
/**
* NewWriter函数的作用是创建一个既有默认大小缓冲,写入w的×writer
*会创建一个字符串并返回
*func NewWriter(w io.Writer) *Writer
*/
/*
w := bufio.NewWriter(os.Stdout)
fmt.Fprint(w, "hello")
fmt.Fprint(w, "hello")
w.Flush()
*/
/**
* NewWriterSize函数的作用是NewWriterSize创建一个具有最少有size尺寸的缓冲、
*写入w的 *Writer。
*如果参数w已经是一个具有足够大缓冲的*Writer类型值,会返回w。
*func NewWriterSize(w io.Writer, size int) *Writer
*/
/**
* Available方法的作用是Available返回缓冲中还有多少字节未使用。
*如果参数w已经是一个具有足够大缓冲的*Writer类型值,会返回w。
*func (b *Writer) Available() int
*/
/*
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
fmt.Println(bw.Available(), bw.Buffered())
*/
/**
* Buffered方法的作用是返回缓冲中已使用的字节数。
*func (b *Writer) Buffered() int
*/
/*
s := strings.NewReader("123456789")
br := bufio.NewReader(s)
b := make([]byte, 3)
br.Read(b)
fmt.Println(br.Buffered())
br.Read(b)
fmt.Println(br.Buffered())
*/
/**
* flush方法的作用是将缓冲中的数据写入下层的io.Writer接口
*func (b *Writer) Flush() error
*/
/*
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
bw.WriteString("ABCDEFG")
bw.Flush()
fmt.Printf("%q\n", b)
*/
/**
* ReadFrom方法的作用是实现了io.ReaderFrom
*func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
*/
/*
b := bytes.NewBuffer(make([]byte, 0))
s := strings.NewReader("Hello 世界!")
bw := bufio.NewWriter(b)
n , err := bw.ReadFrom(s)
fmt.Println(b, n, err)
*/
/**
* Reset方法的作用是丢弃缓冲中的数据,清除任何错误,将b重设为其下层从r读取数据。
*func (b *Writer) Reset(w io.Writer)
*/
/*
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
bw.WriteString("123")
c := bytes.NewBuffer(make([]byte, 0))
bw.Reset(c)
bw.WriteString("456")
bw.Flush()
fmt.Println(b)
fmt.Println(c)
*/
/**
* Reset方法的作用是返回缓冲区的大小(以字节为单位)
* func (b *Writer) Size() int
*/
/*
w := bufio.NewWriter(os.Stdin)
fmt.Fprint(w , "hello")
fmt.Fprint(w, "world")
fmt.Println(w.Size())
*/
/**
* Reset方法的作用是将p的内容写入缓冲。返回写入的字节数。如果返回值nn < len(p),
*还会返回一个错误说明原因。
*func (b *Writer) Write(p []byte) (nn int, err error)
*/
/*
var writer bytes.Buffer
strings := []string{
"hello ",
"right now i am testing the usage of ",
"writer",
}
for _, s := range strings{
n, err :=writer.Write([]byte(s))
if err != nil{
log.Fatal(err)
}
if n != len(s){
log.Fatal("fail to write the right string")
}
}
fmt.Println(writer.String())
*/
/**
* WriteByte方法的作用是将一个byte类型的数据放到缓冲器的尾部
*func (b *Writer) WriteByte(c byte) error
*/
/*
var s byte = '?'
buf := bytes.NewBufferString("hello")
fmt.Println(buf.String())
buf.WriteByte(s)
fmt.Println(buf.String())
*/
/**
* WriteRune方法的作用是将一个rune类型的数据放到缓冲器的尾部
*func (b *Writer) WriteRune(r rune) (size int, err error)
*/
/*
var s rune = '好'
buf := bytes.NewBufferString("hello")
fmt.Println(buf.String())
buf.WriteRune(s)
fmt.Println(buf.String())
*/
/**
* WriteRune方法的作用是把一个字符串放到缓冲器的尾部
*func (b *Writer) WriteString(s string) (int, error)
*/
/*
s := " world"
buf := bytes.NewBufferString("hello")
fmt.Println(buf.String())
buf.WriteString(s)
fmt.Println(buf.String())
*/
}
总结
bufio包主要是运用于io缓冲流方面的,有的时候为了提高针对流操作的效率,不然不能缺少针对缓冲流的相关操作,因此bufio包中的函数和方法的运用也是十分重要的,建议一鼓作气坚持拿下来。