亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

GOLang?IO接口與工具如何使用

發布時間:2023-03-17 10:36:54 來源:億速云 閱讀:113 作者:iii 欄目:開發技術

這篇文章主要介紹“GOLang IO接口與工具如何使用”,在日常操作中,相信很多人在GOLang IO接口與工具如何使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”GOLang IO接口與工具如何使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

一、io包中接口的好處和優勢

1.1拷貝數據的函數

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包中io.Reader的擴展接口和實現類型

2.1 io.Reader的擴展接口

io.ReadWriter 這個接口即是io.Reader的擴展接口,也是io.Writer的擴展接口;

該接口定義了一組行為,包含且僅包含了基本的字節序列讀取方法Read,和字節寫入方法Write。

io.ReadCloser: 該接口除了包含基本的字節序列讀取方法以外,還擁有一個基本的關閉方法Close。

Close方法一般用于關閉數據讀寫的通道。這個接口其實是io.Reader接口和io.Closer接口的組合。

io.ReadWriteCloser:這個接口是io.Readerio.Writerio.Closer三個接口的組合。

io.ReadSeeker :該接口擁有一個尋找讀寫位置的基本方法Seek。

該方法可以根據給定的偏移量,基于數據的起始位置、末尾位置、或者當前讀寫位置去尋找新的讀寫位置。這個新的讀寫位置用于表明下一次讀或寫時的起始索引。

Seek是io.Seeker接口唯一擁有的方法。

io.ReadWriteSeeker:這個接口是io.Readerio.Writerio.Seeker三個接口的組合。

2.2 io.Reader接口的實現類型

*io.LimitedReader:此類型的基本類型會包裝io.Reader類型的值,并提供一個額外的受限讀取的功能。

該類型的讀取方法Read返回的總數據量會受到限制。無論該方法被調用多少次。這個限制由該類型的字段N指明,單位是字節。

*io.SectionReader :此類型的基本類型可以包裝io.ReaderAt類型的值,并且會限制它的Read方法,只能讀取原始數據的一部分(或者說某一段)。

這個數據段段起始位置和末尾位置,需要在它被初始化的時候就指明,并且之后無法變更。該類型的值的行為與切片有些類型,只會對外暴露在其窗口之中的那些數據。

*io.teeReader:該類型是一個包級私有的數據類型,也是io.TeeReader函數結果值的實際類型。

TeeReader(r Reader, w Writer)函數的結果值的Read方法,會把r中的數據經過作為方法參數的字節切片p寫入w中。也就是說,p是r和w的數據搬運工。

	teeReader1 := io.TeeReader(src, dst)
	p := make([]byte, 7)
	teeReader1.Read(p)

*io.multiReader:該類型也是包級私有的數據類型。類似地,io包中有一個名為MultiReader的函數,它可以接受若干個io.Reader類型的參數值,并返回一個實際類型為io.multiReader的結果值。

當這個結果值當Read方法被調用,它會順序地從前面那些io.Reader類型的參數值中讀取數據。因此,我們也稱之為多對象讀取器。

*io.pipe:此類型是一個包級私有的數據類型。它不但實現了io.Reader接口,而且還實現了io.Writer接口。

實際上,io.PipeReader類型和io.PipeWriter類型擁有的所有指針方法都是以它為基礎的。這些方法都是代理了io.pipe類型值所擁有的某一個方法而已。

Pipe() (*PipeReader, *PipeWriter) 返回兩個類型的指針值,并分別把它們作為其生成的同步內存管道的兩端。所以可以說,*io.pipe類型就是io包提供的同步內存管道的核心實現。

*ip.PipeReader該類型可以被視為*io.pipe類型的代理類型。它代理了后者的一部分功能,并基于后者實現了io.ReadClosed接口。同時,它還定義了同步內存管道的讀取端。

在實際的面試中,只要應聘者能夠從某一個方面出發,說出io.Reader的擴展接口及其存在意義,或者說清楚該接口的三五個實現類型,那么就可以算是基本回答正確了。

2.3 示例

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) {
	// 創建一個字符串
	// 創建一個字符串讀取器,它的名字是 reader1。
	fmt.Println("創建一個字符串讀取器,它的名字是 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("創建一個新的限制Reader,限制讀的數量為:%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("創建一個新的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("創建一個section Reader 帶有一個Reader, 偏移量為%d, 數量為 %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("創建一個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("創建一個新的內存同步管道....")
	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."),
	}
	// 這里的同步工具,純屬為了保證下面示例中的打印語句能夠執行完成
	// 在實際中沒必要這樣做
	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()
}

三、io包的接口以及它們之間的關系

沒有嵌入其它接口并且只定義了一個方法的接口,總共有11個。其中有3個接口有著眾多的擴展接口和實現類型,它們是:io.Readerio.Writerio.Closer

可以把這些接口分為四類:讀取、寫入、關閉、讀寫位置設定。前三個操作屬于基本的I/O操作。

3.1 讀操作接口

上面已經討論,核心接口io.Reader有5個擴展接口,6個實現類型。更多的讀操作接口還有:

io.ByteReaderio.RuneReader。它們分別定義了一個讀取方法:ReadByteReadRune。用于讀取下一個單一的字節和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.Readerbytes.Buffer都是io.ByteReaderio.RuneReader的實現類型。同時,這兩個接口,還都實現了io.ByteScannerio.RuneScanner

type ByteScanner interface {
	ByteReader
	UnreadByte() error
}

io.ByteScanner接口內嵌了簡單接口io.ByteReader、并額外定義了UnreadByte方法,這樣,它就抽象出一個能夠讀取和讀回退單字節的功能集。

type RuneScanner interface {
	RuneReader
	UnreadRune() error
}

io.RuneScanner接口內嵌了簡單接口io.RunneReader,并額外定義了UnreadRune方法。這樣,它就抽象出一個能夠讀取和讀回退單個Unicode字符的功能集。

io.ReaderAt接口只定義了一個方法ReadAt。ReadAt是一個純粹的只讀方法。

它只讀其所屬值中包含的字節,而不對這個值進行真正的修改。比如,它絕對不能修改已讀計數的值。

io.WriterTo接口,定義了一個名為WriteTo的方法。它只會接受一個io.Writer類型的參數值,并從該參數值中讀出數據,并寫入其所屬值中。

與之對應的接口是io.ReaderFrom

io.CopyN函數,在復制數據的時候,會檢查其參數src,是否實現了io.WriterTo接口。如果是,那么它就直接利用該值的WriteTo方法,把其中的數據拷貝給參數dst參數的值。

類似地,這個函數還會檢查dst的值是否實現了io.ReaderFrom接口。如果是,那么它就會利用這個值的ReadFrom方法,直接從src那里把數據拷貝到該值。

io.Copyio.CopyBuffer,和io.CopyN一樣。因為它們內部復制到時候,使用同一套代碼。

3.2 寫操作接口

io.ReaderFrom接口,它定義了一個名叫ReadFrom的寫入方法。該方法接受一個io.Reader類型的參數值。并會從該參數值中讀取數據,并寫入到所屬值中。

基于io.Writer 擴展的接口

io.ReadWriter

*io.pipe就是io.ReadWriter 接口的實現類型。

io.ReadWriteClose

io.ReadWriteSeeker

io.WriteCloser

io.WriteSeeker

io.ByteWriter

io.WriterAt

*io.File不但是io.WriterAt的實現類型,同時還實現了io.ReadWriterCloserio.ReadWriteSeeker接口。

3.3 讀寫位置設定接口

io.Seeker接口作為一個讀寫位置設定相關的接口,僅定義了一個方法,叫Seek

基于io.Seeker擴展的接口:

io.ReadSeeker

io.ReadWriteSeeker

io.WriteSeeker

io.WriteSeeker是基于io.Writerio.Seeker的擴展接口

*strings.Reader*io.SectionReader都實現了io.Seeker接口,這兩個類型也都是io.ReaderAt接口的實現類型。

	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)

3.4 關閉操作

io.Closer

它的實現類型,在io包里只有io.PipeReaderio.PipeWriter

四、總結11個簡單接口和9個擴展接口

4.1 讀取操作接口有5個

io.Reader

io.ByteReader

io.RuneReader

io.ReaderAt

io.WriterTo

4.2 寫入操作接口有4個

io.Writer

io.ByteWriter

io.WriterAt

io.ReaderFrom

4.3 關閉操作接口有1個

io.Closer

4.4 讀寫位置設定的接口有1個

io.Seeker

4.5 基于11簡單接口的擴展接口有9個

io.ReadWriter

io.ReadCloser

io.ReadSeeker

io.ByteScanner

io.RuneScanner

io.ReadWriteCloser

io.ReadWriteSeeker

io.WriteCloser

io.WriteSeeker

到此,關于“GOLang IO接口與工具如何使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

go io
AI

星子县| 宁乡县| 清水县| 镇沅| 车致| 洪泽县| 郎溪县| 邳州市| 新巴尔虎左旗| 凤阳县| 奉贤区| 中超| 福安市| 图木舒克市| 冷水江市| 通化县| 合江县| 巨鹿县| 樟树市| 平昌县| 民乐县| 综艺| 兴安盟| 仁寿县| 定结县| 嘉义市| 清河县| 开原市| 开鲁县| 庄河市| 万荣县| 玉树县| 灵台县| 南乐县| 赣州市| 阿拉善右旗| 武强县| 房山区| 南华县| 涟水县| 石景山区|