您好,登錄后才能下訂單哦!
這篇文章主要介紹“GOLang IO接口與工具如何使用”,在日常操作中,相信很多人在GOLang IO接口與工具如何使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”GOLang IO接口與工具如何使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
io.Copy(dst Writer, src Reader)
io.CopyBuffer(dst Writer, src Reader, buf []byte)
io.CopyN(dst Writer, src Reader, buf []byte)
src := strings.NewReader( "CopyN copies n bytes (or unil an error) from src to dst." + "It returns the number of bytes copied and " + "the earliest error encountered while copying") dst := new(strings.Builder) written, err := io.CopyN(dst, src, 58) if err != nil { fmt.Printf("err: %v\n", err) } else { // Written(58): "CopyN copies n bytes (or unil an error) from src to dst.It" fmt.Printf("Written(%d): %q\n", written, dst.String()) }
io.ReadWriter
這個接口即是io.Reader
的擴展接口,也是io.Writer
的擴展接口;
該接口定義了一組行為,包含且僅包含了基本的字節(jié)序列讀取方法Read,和字節(jié)寫入方法Write。
io.ReadCloser
: 該接口除了包含基本的字節(jié)序列讀取方法以外,還擁有一個基本的關閉方法Close。
Close方法一般用于關閉數(shù)據(jù)讀寫的通道。這個接口其實是io.Reader
接口和io.Closer
接口的組合。
io.ReadWriteCloser
:這個接口是io.Reader
、io.Writer
、io.Closer
三個接口的組合。
io.ReadSeeker
:該接口擁有一個尋找讀寫位置的基本方法Seek。
該方法可以根據(jù)給定的偏移量,基于數(shù)據(jù)的起始位置、末尾位置、或者當前讀寫位置去尋找新的讀寫位置。這個新的讀寫位置用于表明下一次讀或寫時的起始索引。
Seek是io.Seeker
接口唯一擁有的方法。
io.ReadWriteSeeker
:這個接口是io.Reader
、io.Writer
、io.Seeker
三個接口的組合。
*io.LimitedReader
:此類型的基本類型會包裝io.Reader
類型的值,并提供一個額外的受限讀取的功能。
該類型的讀取方法Read返回的總數(shù)據(jù)量會受到限制。無論該方法被調(diào)用多少次。這個限制由該類型的字段N指明,單位是字節(jié)。
*io.SectionReader
:此類型的基本類型可以包裝io.ReaderAt
類型的值,并且會限制它的Read方法,只能讀取原始數(shù)據(jù)的一部分(或者說某一段)。
這個數(shù)據(jù)段段起始位置和末尾位置,需要在它被初始化的時候就指明,并且之后無法變更。該類型的值的行為與切片有些類型,只會對外暴露在其窗口之中的那些數(shù)據(jù)。
*io.teeReader
:該類型是一個包級私有的數(shù)據(jù)類型,也是io.TeeReader
函數(shù)結果值的實際類型。
TeeReader(r Reader, w Writer)
函數(shù)的結果值的Read方法,會把r中的數(shù)據(jù)經(jīng)過作為方法參數(shù)的字節(jié)切片p寫入w中。也就是說,p是r和w的數(shù)據(jù)搬運工。
teeReader1 := io.TeeReader(src, dst) p := make([]byte, 7) teeReader1.Read(p)
*io.multiReader
:該類型也是包級私有的數(shù)據(jù)類型。類似地,io包中有一個名為MultiReader的函數(shù),它可以接受若干個io.Reader類型的參數(shù)值,并返回一個實際類型為io.multiReader
的結果值。
當這個結果值當Read方法被調(diào)用,它會順序地從前面那些io.Reader類型的參數(shù)值中讀取數(shù)據(jù)。因此,我們也稱之為多對象讀取器。
*io.pipe
:此類型是一個包級私有的數(shù)據(jù)類型。它不但實現(xiàn)了io.Reader
接口,而且還實現(xiàn)了io.Writer
接口。
實際上,io.PipeReader
類型和io.PipeWriter
類型擁有的所有指針方法都是以它為基礎的。這些方法都是代理了io.pipe
類型值所擁有的某一個方法而已。
Pipe() (*PipeReader, *PipeWriter)
返回兩個類型的指針值,并分別把它們作為其生成的同步內(nèi)存管道的兩端。所以可以說,*io.pipe
類型就是io包提供的同步內(nèi)存管道的核心實現(xiàn)。
*ip.PipeReader
該類型可以被視為*io.pipe
類型的代理類型。它代理了后者的一部分功能,并基于后者實現(xiàn)了io.ReadClosed
接口。同時,它還定義了同步內(nèi)存管道的讀取端。
在實際的面試中,只要應聘者能夠從某一個方面出發(fā),說出io.Reader的擴展接口及其存在意義,或者說清楚該接口的三五個實現(xiàn)類型,那么就可以算是基本回答正確了。
package main import ( "fmt" "io" "strings" "sync" "time" ) func executeIfNoErr(err error, f func()) { if err != nil { fmt.Printf("error: %v\n", err) return } f() } func example1(comment string) { // 創(chuàng)建一個字符串 // 創(chuàng)建一個字符串讀取器,它的名字是 reader1。 fmt.Println("創(chuàng)建一個字符串讀取器,它的名字是 reader1。") reader1 := strings.NewReader(comment) buf1 := make([]byte, 7) n, err := reader1.Read(buf1) var index1, offset1 int64 executeIfNoErr(err, func() { // Read(7): "Package" fmt.Printf("Read(%d): %q\n", n, buf1[:n]) offset1 = int64(54) index1, err = reader1.Seek(offset1, io.SeekCurrent) }) executeIfNoErr(err, func() { fmt.Printf("基于當前的所以,移動%d的偏移量后,新的索引值為: %d \n", offset1, index1) n, err = reader1.Read(buf1) }) executeIfNoErr(err, func() { fmt.Printf("Read(%d):%q\n", n, buf1[:n]) }) fmt.Println() } func example2(comment string) { reader1 := strings.NewReader(comment) reader1.Reset(comment) num := int64(7) fmt.Printf("創(chuàng)建一個新的限制Reader,限制讀的數(shù)量為:%d\n", num) reader2 := io.LimitReader(reader1, num) buf2 := make([]byte, 10) for i := 0; i < 3; i++ { n, err := reader2.Read(buf2) executeIfNoErr(err, func() { fmt.Printf("Read(%d):%q\n", n, buf2[:n]) }) } fmt.Println() } func example3(comment string) { reader1 := strings.NewReader(comment) writer1 := new(strings.Builder) fmt.Println("創(chuàng)建一個新的teeReader, 帶有一個reader和一個writer") reader3 := io.TeeReader(reader1, writer1) buf4 := make([]byte, 40) for i := 0; i < 8; i++ { n, err := reader3.Read(buf4) executeIfNoErr(err, func() { fmt.Printf("Read(%d):%q\n", n, buf4[:n]) }) } fmt.Println() } func example4(comment string) { reader1 := strings.NewReader(comment) offset1 := int64(56) num2 := int64(72) fmt.Printf("創(chuàng)建一個section Reader 帶有一個Reader, 偏移量為%d, 數(shù)量為 %d...\n", offset1, num2) reader2 := io.NewSectionReader(reader1, offset1, num2) buf1 := make([]byte, 20) for i := 0; i < 5; i++ { n, err := reader2.Read(buf1) executeIfNoErr(err, func() { fmt.Printf("Read(%d): %q\n", n, buf1[:n]) }) } fmt.Println() } func example5() { reader01 := strings.NewReader("MultiReader returns a Reader that's the logical concatenation of " + "the provided input readers.") reader02 := strings.NewReader("They're read sequentially.") reader03 := strings.NewReader("Once all inputs have returned EOF, " + "Read will return EOF.") reader04 := strings.NewReader("If any of the readers return a non-nil, " + "non-EOF error, Read will return that error.") fmt.Println("創(chuàng)建一個multi-reader, 帶有4個reader") reader1 := io.MultiReader(reader01, reader02, reader03, reader04) buf2 := make([]byte, 50) for i := 0; i < 8; i++ { n, err := reader1.Read(buf2) executeIfNoErr(err, func() { fmt.Printf("Read(%d): %q\n", n, buf2[:n]) }) } fmt.Println() } func example6() { fmt.Println("創(chuàng)建一個新的內(nèi)存同步管道....") pipeReader, pipWriter := io.Pipe() _ = interface{}(pipeReader).(io.ReadCloser) _ = interface{}(pipWriter).(io.WriteCloser) comments := [][]byte{ []byte("Pipe creates a synchronous in-memory pipe."), []byte("It can be used to connect code expecting an io.Reader "), []byte("with code expecting an io.Writer."), } // 這里的同步工具,純屬為了保證下面示例中的打印語句能夠執(zhí)行完成 // 在實際中沒必要這樣做 var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() for _, d := range comments { time.Sleep(time.Millisecond * 500) n, err := pipWriter.Write(d) if err != nil { fmt.Printf("read error : %v\n", err) break } fmt.Printf("Writen(%d): %q\n", n, d) } pipWriter.Close() }() go func() { defer wg.Done() wBuf := make([]byte, 55) for { n, err := pipeReader.Read(wBuf) if err != nil { fmt.Printf("read error: %v\n", err) break } fmt.Printf("Read(%d): %q\n", n, wBuf[:n]) } }() wg.Wait() } func main() { comment := "Package io provides basic interfaces to I/O primitives. " + "Its primary job is to wrap existing implementations of such primitives, " + "such as those in package os, " + "into shared public interfaces that abstract the functionality, " + "plus some other related primitives." // 示例1:: Seek example1(comment) // 示例2: LimitReader example2(comment) // 示例3: TeeReader example3(comment) // 示例4: NewSectionReader example4(comment) // 示例5: MultiReader example5() // 示例6 example6() }
沒有嵌入其它接口并且只定義了一個方法的接口,總共有11個。其中有3個接口有著眾多的擴展接口和實現(xiàn)類型,它們是:io.Reader
、io.Writer
、io.Closer
。
可以把這些接口分為四類:讀取、寫入、關閉、讀寫位置設定。前三個操作屬于基本的I/O操作。
上面已經(jīng)討論,核心接口io.Reader
有5個擴展接口,6個實現(xiàn)類型。更多的讀操作接口還有:
io.ByteReader
和io.RuneReader
。它們分別定義了一個讀取方法:ReadByte
和ReadRune
。用于讀取下一個單一的字節(jié)和Unicode字符。
var b *bytes.Buffer b = bytes.NewBufferString("ab") _ = interface{}(b).(io.ByteReader) _ = interface{}(b).(io.RuneReader) _ = interface{}(b).(io.ByteScanner) _ = interface{}(b).(io.RuneScanner) // io.ByteReader var reader01 *strings.Reader reader01 = strings.NewReader("aa") _ = interface{}(reader01).(io.ByteReader) _ = interface{}(reader01).(io.RuneReader) _ = interface{}(reader01).(io.ByteScanner) _ = interface{}(reader01).(io.RuneScanner)
strings.Reader
和bytes.Buffer
都是io.ByteReader
和io.RuneReader
的實現(xiàn)類型。同時,這兩個接口,還都實現(xiàn)了io.ByteScanner
和 io.RuneScanner
。
type ByteScanner interface { ByteReader UnreadByte() error }
io.ByteScanner
接口內(nèi)嵌了簡單接口io.ByteReader
、并額外定義了UnreadByte
方法,這樣,它就抽象出一個能夠讀取和讀回退單字節(jié)的功能集。
type RuneScanner interface { RuneReader UnreadRune() error }
io.RuneScanner
接口內(nèi)嵌了簡單接口io.RunneReader
,并額外定義了UnreadRune
方法。這樣,它就抽象出一個能夠讀取和讀回退單個Unicode字符的功能集。
io.ReaderAt
接口只定義了一個方法ReadAt。ReadAt是一個純粹的只讀方法。
它只讀其所屬值中包含的字節(jié),而不對這個值進行真正的修改。比如,它絕對不能修改已讀計數(shù)的值。
io.WriterTo
接口,定義了一個名為WriteTo
的方法。它只會接受一個io.Writer
類型的參數(shù)值,并從該參數(shù)值中讀出數(shù)據(jù),并寫入其所屬值中。
與之對應的接口是io.ReaderFrom
io.CopyN
函數(shù),在復制數(shù)據(jù)的時候,會檢查其參數(shù)src,是否實現(xiàn)了io.WriterTo
接口。如果是,那么它就直接利用該值的WriteTo
方法,把其中的數(shù)據(jù)拷貝給參數(shù)dst參數(shù)的值。
類似地,這個函數(shù)還會檢查dst的值是否實現(xiàn)了io.ReaderFrom接口。如果是,那么它就會利用這個值的ReadFrom方法,直接從src那里把數(shù)據(jù)拷貝到該值。
io.Copy
和io.CopyBuffer
,和io.CopyN
一樣。因為它們內(nèi)部復制到時候,使用同一套代碼。
io.ReaderFrom
接口,它定義了一個名叫ReadFrom
的寫入方法。該方法接受一個io.Reader
類型的參數(shù)值。并會從該參數(shù)值中讀取數(shù)據(jù),并寫入到所屬值中。
基于io.Writer
擴展的接口
io.ReadWriter
*io.pipe
就是io.ReadWriter
接口的實現(xiàn)類型。
io.ReadWriteClose
io.ReadWriteSeeker
io.WriteCloser
io.WriteSeeker
io.ByteWriter
io.WriterAt
*io.File
不但是io.WriterAt
的實現(xiàn)類型,同時還實現(xiàn)了io.ReadWriterCloser
、io.ReadWriteSeeker
接口。
io.Seeker
接口作為一個讀寫位置設定相關的接口,僅定義了一個方法,叫Seek
。
基于io.Seeker
擴展的接口:
io.ReadSeeker
io.ReadWriteSeeker
io.WriteSeeker
io.WriteSeeker
是基于io.Writer
和io.Seeker
的擴展接口
*strings.Reader
和*io.SectionReader
都實現(xiàn)了io.Seeker
接口,這兩個類型也都是io.ReaderAt
接口的實現(xiàn)類型。
var reader02 *strings.Reader reader02 = strings.NewReader("aa") _ = interface{}(reader02).(io.Seeker) _ = interface{}(reader02).(io.ReaderAt) var sectionReader01 *io.SectionReader sectionReader01 = io.NewSectionReader(reader02, 0, 1) _ = interface{}(sectionReader01).(io.Seeker) _ = interface{}(sectionReader01).(io.ReaderAt)
io.Closer
它的實現(xiàn)類型,在io包里只有io.PipeReader
和io.PipeWriter
。
io.Reader
io.ByteReader
io.RuneReader
io.ReaderAt
io.WriterTo
io.Writer
io.ByteWriter
io.WriterAt
io.ReaderFrom
io.Closer
io.Seeker
io.ReadWriter
io.ReadCloser
io.ReadSeeker
io.ByteScanner
io.RuneScanner
io.ReadWriteCloser
io.ReadWriteSeeker
io.WriteCloser
io.WriteSeeker
到此,關于“GOLang IO接口與工具如何使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。