爲何說strings.Reader類型的值能夠高效地讀取字符串ui
與strings.Builder類型偏偏相反,strings.Reader類型是爲了高效讀取字符串而存在的。後者的高效主要體如今它對字符串的讀取機制上,它封裝了不少用於在string值上讀取內容的最佳實踐。spa
strings.Reader類型的值(如下簡稱Reader值)可讓咱們很方便地讀取一個字符串中的內容。在讀取的過程當中,Reader值會保存已讀取的字節的計數(如下簡稱已讀計數)。code
已讀計數也表明着下一次讀取的起始索引位置。Reader值正是依靠這樣一個計數,以及針對字符串值的切片表達式,從而實現快速讀取。blog
此外,這個已讀計數也是讀取回退和位置設定時的重要依據。雖然它屬於Reader值的內部結構,但咱們仍是能夠經過該值的Len方法和Size把它計算出來的索引
Reader值擁有的大部分用於讀取的方法都會及時地更新已讀計數。好比,ReadByte方法會在讀取成功後將這個計數的值加1。ci
又好比,ReadRune方法在讀取成功以後,會把被讀取的字符所佔用的字節數做爲計數的增量。字符串
不過,ReadAt方法算是一個例外。它既不會依據已讀計數進行讀取,也不會在讀取後更新它。正由於如此,這個方法能夠自由地讀取其所屬的Reader值中的任何內容。string
// 示例1。 reader1 := strings.NewReader( "中文的的的SimpleNewReader returns a new Reader reading from s. " + "It is similar to bytes.NewBufferString but more efficient and read-only. ") %d\n",reader1.Size()-int64(reader1.Len())) fmt.Printf("len:%d\n",reader1.Len()) //原始字符串長度是141 by:= make([]byte,20) reader1.ReadAt(by,2) //這個方法不作計數也就是原值不變也就是len長度仍是原始長度 buf1 := make([]byte, 3) //原值偏移量+3 len長度要-3 reader1.Read(buf1) fmt.Printf("len:%d value:%s\n",reader1.Len(),string(buf1))
打印結果爲it
len:141
len:138 value:中 io
除此以外,Reader值的Seek方法也會更新該值的已讀計數。實際上,這個Seek方法的主要做用正是設定下一次讀取的起始索引位置
offset2 := int64(17) expectedIndex := reader1.Size() - int64(reader1.Len()) + offset2 fmt.Printf("Seek with offset %d and whence %d ...\n", offset2, io.SeekCurrent) readingIndex, _ := reader1.Seek(offset2, io.SeekCurrent) fmt.Printf("The reading index in reader: %d (returned by Seek)\n", readingIndex) fmt.Printf("The reading index in reader: %d (computed by me)\n", expectedIndex)