Golang學(xué)習(xí) - bufio 包


// bufio 包實現(xiàn)了帶緩存的 I/O 操作


type Reader struct { ... }

// NewReaderSize 將 rd 封裝成一個帶緩存的 bufio.Reader 對象嗅辣,
// 緩存大小由 size 指定(如果小于 16 則會被設(shè)置為 16)流码。
// 如果 rd 的基類型就是有足夠緩存的 bufio.Reader 類型,則直接將
// rd 轉(zhuǎn)換為基類型返回瘦锹。
func NewReaderSize(rd io.Reader, size int) *Reader

// NewReader 相當(dāng)于 NewReaderSize(rd, 4096)
func NewReader(rd io.Reader) *Reader

// bufio.Reader 實現(xiàn)了如下接口:
// io.Reader
// io.WriterTo
// io.ByteScanner
// io.RuneScanner

// Peek 返回緩存的一個切片仔夺,該切片引用緩存中前 n 個字節(jié)的數(shù)據(jù)季眷,
// 該操作不會將數(shù)據(jù)讀出激蹲,只是引用扫沼,引用的數(shù)據(jù)在下一次讀取操作之
// 前是有效的。如果切片長度小于 n缤剧,則返回一個錯誤信息說明原因。
// 如果 n 大于緩存的總大小域慷,則返回 ErrBufferFull荒辕。
func (b *Reader) Peek(n int) ([]byte, error)

// Read 從 b 中讀出數(shù)據(jù)到 p 中,返回讀出的字節(jié)數(shù)和遇到的錯誤犹褒。
// 如果緩存不為空抵窒,則只能讀出緩存中的數(shù)據(jù),不會從底層 io.Reader
// 中提取數(shù)據(jù)叠骑,如果緩存為空李皇,則:
// 1、len(p) >= 緩存大小宙枷,則跳過緩存掉房,直接從底層 io.Reader 中讀
// 出到 p 中。
// 2慰丛、len(p) < 緩存大小卓囚,則先將數(shù)據(jù)從底層 io.Reader 中讀取到緩存
// 中,再從緩存讀取到 p 中诅病。
func (b *Reader) Read(p []byte) (n int, err error)

// Buffered 返回緩存中未讀取的數(shù)據(jù)的長度哪亿。
func (b *Reader) Buffered() int

// Discard 跳過后續(xù)的 n 個字節(jié)的數(shù)據(jù)粥烁,返回跳過的字節(jié)數(shù)。
// 如果結(jié)果小于 n蝇棉,將返回錯誤信息讨阻。
// 如果 n 小于緩存中的數(shù)據(jù)長度,則不會從底層提取數(shù)據(jù)篡殷。
func (b *Reader) Discard(n int) (discarded int, err error)

// ReadSlice 在 b 中查找 delim 并返回 delim 及其之前的所有數(shù)據(jù)钝吮。
// 該操作會讀出數(shù)據(jù),返回的切片是已讀出的數(shù)據(jù)的引用贴唇,切片中的數(shù)據(jù)
// 在下一次讀取操作之前是有效的搀绣。
//
// 如果找到 delim,則返回查找結(jié)果戳气,err 返回 nil链患。
// 如果未找到 delim,則:
// 1瓶您、緩存不滿麻捻,則將緩存填滿后再次查找。
// 2呀袱、緩存是滿的贸毕,則返回整個緩存,err 返回 ErrBufferFull夜赵。
//
// 如果未找到 delim 且遇到錯誤(通常是 io.EOF)明棍,則返回緩存中的所
// 有數(shù)據(jù)和遇到的錯誤。
//
// 因為返回的數(shù)據(jù)有可能被下一次的讀寫操作修改寇僧,所以大多數(shù)操作應(yīng)該
// 使用 ReadBytes 或 ReadString摊腋,它們返回的是數(shù)據(jù)的拷貝。
func (b *Reader) ReadSlice(delim byte) (line []byte, err error)

// ReadLine 是一個低水平的行讀取原語嘁傀,大多數(shù)情況下兴蒸,應(yīng)該使用
// ReadBytes('\n') 或 ReadString('\n'),或者使用一個 Scanner细办。
//
// ReadLine 通過調(diào)用 ReadSlice 方法實現(xiàn)橙凳,返回的也是緩存的切片。用于
// 讀取一行數(shù)據(jù)笑撞,不包括行尾標(biāo)記(\n 或 \r\n)岛啸。
//
// 只要能讀出數(shù)據(jù),err 就為 nil娃殖。如果沒有數(shù)據(jù)可讀值戳,則 isPrefix 返回
// false,err 返回 io.EOF炉爆。
//
// 如果找到行尾標(biāo)記堕虹,則返回查找結(jié)果卧晓,isPrefix 返回 false。
// 如果未找到行尾標(biāo)記赴捞,則:
// 1逼裆、緩存不滿,則將緩存填滿后再次查找赦政。
// 2胜宇、緩存是滿的,則返回整個緩存恢着,isPrefix 返回 true桐愉。
//
// 整個數(shù)據(jù)尾部“有一個換行標(biāo)記”和“沒有換行標(biāo)記”的讀取結(jié)果是一樣。
//
// 如果 ReadLine 讀取到換行標(biāo)記掰派,則調(diào)用 UnreadByte 撤銷的是換行標(biāo)記从诲,
// 而不是返回的數(shù)據(jù)。
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)

// ReadBytes 功能同 ReadSlice靡羡,只不過返回的是緩存的拷貝系洛。
func (b *Reader) ReadBytes(delim byte) (line []byte, err error)

// ReadString 功能同 ReadBytes,只不過返回的是字符串略步。
func (b *Reader) ReadString(delim byte) (line string, err error)

// Reset 將 b 的底層 Reader 重新指定為 r描扯,同時丟棄緩存中的所有數(shù)據(jù),復(fù)位
// 所有標(biāo)記和錯誤信息趟薄。 bufio.Reader绽诚。
func (b *Reader) Reset(r io.Reader)


// 示例:Peek、Read杭煎、Discard憔购、Buffered
func main() {
    sr := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
    buf := bufio.NewReaderSize(sr, 0)
    b := make([]byte, 10)

    fmt.Println(buf.Buffered()) // 0
    s, _ := buf.Peek(5)
    s[0], s[1], s[2] = 'a', 'b', 'c'
    fmt.Printf("%d   %q\n", buf.Buffered(), s) // 16   "abcDE"

    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)
    }
    // 5   "bcDEFGHIJK"   <nil>
    // 0   "LMNOP"   <nil>
    // 6   "QRSTUVWXYZ"   <nil>
    // 0   "123456"   <nil>
    // 0   "7890"   <nil>
    // 0   ""   EOF
}

// 示例:ReadLine
func main() {
    sr := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n1234567890")
    buf := bufio.NewReaderSize(sr, 0)

    for line, isPrefix, err := []byte{0}, false, error(nil); len(line) > 0 && err == nil; {
        line, isPrefix, err = buf.ReadLine()
        fmt.Printf("%q   %t   %v\n", line, isPrefix, err)
    }
    // "ABCDEFGHIJKLMNOP"   true   <nil>
    // "QRSTUVWXYZ"   false   <nil>
    // "1234567890"   false   <nil>
    // ""   false   EOF

    fmt.Println("----------")

    // 尾部有一個換行標(biāo)記
    buf = bufio.NewReaderSize(strings.NewReader("ABCDEFG\n"), 0)

    for line, isPrefix, err := []byte{0}, false, error(nil); len(line) > 0 && err == nil; {
        line, isPrefix, err = buf.ReadLine()
        fmt.Printf("%q   %t   %v\n", line, isPrefix, err)
    }
    // "ABCDEFG"   false   <nil>
    // ""   false   EOF

    fmt.Println("----------")

    // 尾部沒有換行標(biāo)記
    buf = bufio.NewReaderSize(strings.NewReader("ABCDEFG"), 0)

    for line, isPrefix, err := []byte{0}, false, error(nil); len(line) > 0 && err == nil; {
        line, isPrefix, err = buf.ReadLine()
        fmt.Printf("%q   %t   %v\n", line, isPrefix, err)
    }
    // "ABCDEFG"   false   <nil>
    // ""   false   EOF
}

// 示例:ReadSlice
func main() {
    // 尾部有換行標(biāo)記
    buf := bufio.NewReaderSize(strings.NewReader("ABCDEFG\n"), 0)

    for line, err := []byte{0}, error(nil); len(line) > 0 && err == nil; {
        line, err = buf.ReadSlice('\n')
        fmt.Printf("%q   %v\n", line, err)
    }
    // "ABCDEFG\n"   <nil>
    // ""   EOF

    fmt.Println("----------")

    // 尾部沒有換行標(biāo)記
    buf = bufio.NewReaderSize(strings.NewReader("ABCDEFG"), 0)

    for line, err := []byte{0}, error(nil); len(line) > 0 && err == nil; {
        line, err = buf.ReadSlice('\n')
        fmt.Printf("%q   %v\n", line, err)
    }
    // "ABCDEFG"   EOF
}

type Writer struct { ... }

// NewWriterSize 將 wr 封裝成一個帶緩存的 bufio.Writer 對象,
// 緩存大小由 size 指定(如果小于 4096 則會被設(shè)置為 4096)岔帽。
// 如果 wr 的基類型就是有足夠緩存的 bufio.Writer 類型,則直接將
// wr 轉(zhuǎn)換為基類型返回导绷。
func NewWriterSize(wr io.Writer, size int) *Writer

// NewWriter 相當(dāng)于 NewWriterSize(wr, 4096)
func NewWriter(wr io.Writer) *Writer

// bufio.Writer 實現(xiàn)了如下接口:
// io.Writer
// io.ReaderFrom
// io.ByteWriter

// WriteString 功能同 Write犀勒,只不過寫入的是字符串
func (b *Writer) WriteString(s string) (int, error)

// WriteRune 向 b 寫入 r 的 UTF-8 編碼,返回 r 的編碼長度妥曲。
func (b *Writer) WriteRune(r rune) (size int, err error)

// Flush 將緩存中的數(shù)據(jù)提交到底層的 io.Writer 中
func (b *Writer) Flush() error

// Available 返回緩存中未使用的空間的長度
func (b *Writer) Available() int

// Buffered 返回緩存中未提交的數(shù)據(jù)的長度
func (b *Writer) Buffered() int

// Reset 將 b 的底層 Writer 重新指定為 w贾费,同時丟棄緩存中的所有數(shù)據(jù),復(fù)位
// 所有標(biāo)記和錯誤信息檐盟。相當(dāng)于創(chuàng)建了一個新的 bufio.Writer褂萧。
func (b *Writer) Reset(w io.Writer)


// 示例:Available、Buffered葵萎、WriteString导犹、Flush
func main() {
    buf := bufio.NewWriterSize(os.Stdout, 0)
    fmt.Println(buf.Available(), buf.Buffered()) // 4096 0

    buf.WriteString("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
    fmt.Println(buf.Available(), buf.Buffered()) // 4070 26

    // 緩存后統(tǒng)一輸出唱凯,避免終端頻繁刷新,影響速度
    buf.Flush() // ABCDEFGHIJKLMNOPQRSTUVWXYZ
}

// ReadWriter 集成了 bufio.Reader 和 bufio.Writer
type ReadWriter struct {
*Reader
*Writer
}

// NewReadWriter 將 r 和 w 封裝成一個 bufio.ReadWriter 對象
func NewReadWriter(r *Reader, w *Writer) *ReadWriter


// Scanner 提供了一個方便的接口來讀取數(shù)據(jù)谎痢,例如遍歷多行文本中的行磕昼。Scan 方法會通過
// 一個“匹配函數(shù)”讀取數(shù)據(jù)中符合要求的部分,跳過不符合要求的部分节猿∑贝樱“匹配函數(shù)”由調(diào)
// 用者指定。本包中提供的匹配函數(shù)有“行匹配函數(shù)”滨嘱、“字節(jié)匹配函數(shù)”峰鄙、“字符匹配函數(shù)”
// 和“單詞匹配函數(shù)”,用戶也可以自定義“匹配函數(shù)”太雨。默認(rèn)的“匹配函數(shù)”為“行匹配函
// 數(shù)”吟榴,用于獲取數(shù)據(jù)中的一行內(nèi)容(不包括行尾標(biāo)記)
//
// Scanner 使用了緩存,所以匹配部分的長度不能超出緩存的容量躺彬。默認(rèn)緩存容量為 4096 -
// bufio.MaxScanTokenSize煤墙,用戶可以通過 Buffer 方法指定自定義緩存及其最大容量。
//
// Scan 在遇到下面的情況時會終止掃描并返回 false(掃描一旦終止宪拥,將無法再繼續(xù)):
// 1仿野、遇到 io.EOF
// 2、遇到讀寫錯誤
// 3她君、“匹配部分”的長度超過了緩存的長度
//
// 如果需要對錯誤進(jìn)行更多的控制脚作,或“匹配部分”超出緩存容量,或需要連續(xù)掃描缔刹,則應(yīng)該
// 使用 bufio.Reader
type Scanner struct { ... }

// NewScanner 創(chuàng)建一個 Scanner 來掃描 r球涛,默認(rèn)匹配函數(shù)為 ScanLines。
func NewScanner(r io.Reader) *Scanner

// Buffer 用于設(shè)置自定義緩存及其可擴(kuò)展范圍校镐,如果 max 小于 len(buf)亿扁,則 buf 的尺寸將
// 固定不可調(diào)。Buffer 必須在第一次 Scan 之前設(shè)置鸟廓,否則會引發(fā) panic从祝。
// 默認(rèn)情況下,Scanner 會使用一個 4096 - bufio.MaxScanTokenSize 大小的內(nèi)部緩存引谜。
func (s *Scanner) Buffer(buf []byte, max int)

// Split 用于設(shè)置“匹配函數(shù)”牍陌,這個函數(shù)必須在調(diào)用 Scan 前執(zhí)行。
func (s *Scanner) Split(split SplitFunc)

// SplitFunc 用來定義“匹配函數(shù)”员咽,data 是緩存中的數(shù)據(jù)毒涧。atEOF 標(biāo)記數(shù)據(jù)是否讀完。
// advance 返回 data 中已處理的數(shù)據(jù)的長度贝室。token 返回找到的“匹配部分”契讲,“匹配
// 部分”可以是緩存的切片仿吞,也可以是自己新建的數(shù)據(jù)(比如 bufio.errorRune)』巢矗“匹
// 配部分”將在 Scan 之后通過 Bytes 和 Text 反饋給用戶茫藏。err 返回錯誤信息。
//
// 如果在 data 中無法找到一個完整的“匹配部分”則應(yīng)返回 (0, nil, nil)霹琼,以便告訴
// Scanner 向緩存中填充更多數(shù)據(jù)务傲,然后再次掃描(Scan 會自動重新掃描)。如果緩存已
// 經(jīng)達(dá)到最大容量還沒有找到枣申,則 Scan 會終止并返回 false售葡。
// 如果 data 為空,則“匹配函數(shù)”將不會被調(diào)用忠藤,意思是在“匹配函數(shù)”中不必考慮
// data 為空的情況挟伙。
//
// 如果 err != nil,掃描將終止模孩,如果 err == ErrFinalToken尖阔,則 Scan 將返回 true,
// 表示掃描正常結(jié)束榨咐,如果 err 是其它錯誤介却,則 Scan 將返回 false,表示掃描出錯块茁。錯誤
// 信息可以在 Scan 之后通過 Err 方法獲取齿坷。
//
// SplitFunc 的作用很簡單,從 data 中找出你感興趣的數(shù)據(jù)数焊,然后返回永淌,同時返回已經(jīng)處理
// 的數(shù)據(jù)的長度。
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

// Scan 開始一次掃描過程佩耳,如果匹配成功遂蛀,可以通過 Bytes() 或 Text() 方法取出結(jié)果,
// 如果遇到錯誤干厚,則終止掃描答恶,并返回 false。
func (s *Scanner) Scan() bool

// Bytes 將最后一次掃描出的“匹配部分”作為一個切片引用返回萍诱,下一次的 Scan 操作會覆
// 蓋本次引用的內(nèi)容。
func (s *Scanner) Bytes() []byte

// Text 將最后一次掃描出的“匹配部分”作為字符串返回(返回副本)污呼。
func (s *Scanner) Text() string

// Err 返回掃描過程中遇到的非 EOF 錯誤裕坊,供用戶調(diào)用,以便獲取錯誤信息燕酷。
func (s *Scanner) Err() error

// ScanBytes 是一個“匹配函數(shù)”用來找出 data 中的單個字節(jié)并返回籍凝。
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)

// ScanRunes 是一個“匹配函數(shù)”周瞎,用來找出 data 中單個 UTF8 字符的編碼。如果 UTF8 編
// 碼錯誤饵蒂,則 token 會返回 "\xef\xbf\xbd"(即:U+FFFD)声诸,但只消耗 data 中的一個字節(jié)。
// 這使得調(diào)用者無法區(qū)分“真正的U+FFFD字符”和“解碼錯誤的返回值”退盯。
func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)

// ScanLines 是一個“匹配函數(shù)”彼乌,用來找出 data 中的單行數(shù)據(jù)并返回(包括空行)。
// 行尾標(biāo)記可以是 \n 或 \r\n(返回值不包含行尾標(biāo)記)
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)

// ScanWords 是一個“匹配函數(shù)”渊迁,用來找出 data 中以空白字符分隔的單詞慰照。
// 空白字符由 unicode.IsSpace 定義。
func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)


// 示例:掃描
func main() {
    // 逗號分隔的字符串琉朽,最后一項為空
    const input = "1,2,3,4,"
    scanner := bufio.NewScanner(strings.NewReader(input))
    // 定義匹配函數(shù)(查找逗號分隔的字符串)
    onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
        for i := 0; i < len(data); i++ {
            if data[i] == ',' {
                return i + 1, data[:i], nil
            }
        }
        if atEOF {
            // 告訴 Scanner 掃描結(jié)束毒租。
            return 0, data, bufio.ErrFinalToken
        } else {
            // 告訴 Scanner 沒找到匹配項,讓 Scan 填充緩存后再次掃描箱叁。
            return 0, nil, nil
        }
    }
    // 指定匹配函數(shù)
    scanner.Split(onComma)
    // 開始掃描
    for scanner.Scan() {
        fmt.Printf("%q ", scanner.Text())
    }
    // 檢查是否因為遇到錯誤而結(jié)束
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "reading input:", err)
    }
}

// 示例:帶檢查掃描
func main() {
    const input = "1234 5678 1234567901234567890 90"
    scanner := bufio.NewScanner(strings.NewReader(input))
    // 自定義匹配函數(shù)
    split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
        // 獲取一個單詞
        advance, token, err = bufio.ScanWords(data, atEOF)
        // 判斷其能否轉(zhuǎn)換為整數(shù)墅垮,如果不能則返回錯誤
        if err == nil && token != nil {
            _, err = strconv.ParseInt(string(token), 10, 32)
        }
        // 這里包含了 return 0, nil, nil 的情況
        return
    }
    // 設(shè)置匹配函數(shù)
    scanner.Split(split)
    // 開始掃描
    for scanner.Scan() {
        fmt.Printf("%s\n", scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        fmt.Printf("Invalid input: %s", err)
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市耕漱,隨后出現(xiàn)的幾起案子算色,更是在濱河造成了極大的恐慌,老刑警劉巖孤个,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剃允,死亡現(xiàn)場離奇詭異,居然都是意外死亡齐鲤,警方通過查閱死者的電腦和手機(jī)斥废,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來给郊,“玉大人牡肉,你說我怎么就攤上這事∠牛” “怎么了统锤?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長炭庙。 經(jīng)常有香客問我饲窿,道長,這世上最難降的妖魔是什么焕蹄? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任逾雄,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鸦泳。我一直安慰自己银锻,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布做鹰。 她就那樣靜靜地躺著击纬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钾麸。 梳的紋絲不亂的頭發(fā)上更振,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機(jī)與錄音喂走,去河邊找鬼殃饿。 笑死,一個胖子當(dāng)著我的面吹牛芋肠,可吹牛的內(nèi)容都是我干的乎芳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼帖池,長吁一口氣:“原來是場噩夢啊……” “哼奈惑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起睡汹,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤肴甸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后囚巴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體原在,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年彤叉,在試婚紗的時候發(fā)現(xiàn)自己被綠了庶柿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡秽浇,死狀恐怖浮庐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情柬焕,我是刑警寧澤审残,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站斑举,受9級特大地震影響搅轿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜富玷,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一璧坟、第九天 我趴在偏房一處隱蔽的房頂上張望没宾。 院中可真熱鬧,春花似錦沸柔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至伐蒋,卻和暖如春工三,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背先鱼。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工俭正, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人焙畔。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓掸读,卻偏偏與公主長得像,于是被迫代替她去往敵國和親宏多。 傳聞我的和親對象是個殘疾皇子儿惫,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 對于傳入 []byte 的函數(shù),都不會修改傳入的參數(shù)伸但,返回值要么是參數(shù)的副本肾请,要么是參數(shù)的切片。 // 轉(zhuǎn)換 //...
    佛心看世界閱讀 729評論 0 0
  • io包中最重要的是兩個接口:Reader和Writer Reader接口##### type Writer int...
    勿以浮沙筑高臺閱讀 16,260評論 0 5
  • // Print 將參數(shù)列表 a 中的各個參數(shù)轉(zhuǎn)換為字符串并寫入到標(biāo)準(zhǔn)輸出中更胖。// 非字符串參數(shù)之間會添加空格铛铁,返...
    佛心看世界閱讀 881評論 0 0
  • Golang 錯誤處理最讓人頭疼的問題就是代碼里充斥著「if err != nil」,它們破壞了代碼的可讀性却妨,本文...
    QFdongdong閱讀 470評論 0 1
  • fmt格式化字符串 格式:%[旗標(biāo)][寬度][.精度][arg索引]動詞旗標(biāo)有以下幾種:+: 對于數(shù)值類型總是輸出...
    皮皮v閱讀 1,089評論 0 3