欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

GOLang?IO接口與工具使用方法講解

 更新時(shí)間:2023年03月17日 09:35:06   作者:鯤鵬飛九萬里  
這篇文章主要介紹了GOLang?IO接口與工具使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧

一、io包中接口的好處和優(yōu)勢

1.1拷貝數(shù)據(jù)的函數(shù)

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的擴(kuò)展接口和實(shí)現(xiàn)類型

2.1 io.Reader的擴(kuò)展接口

io.ReadWriter 這個(gè)接口即是io.Reader的擴(kuò)展接口,也是io.Writer的擴(kuò)展接口;

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

io.ReadCloser: 該接口除了包含基本的字節(jié)序列讀取方法以外,還擁有一個(gè)基本的關(guān)閉方法Close。

Close方法一般用于關(guān)閉數(shù)據(jù)讀寫的通道。這個(gè)接口其實(shí)是io.Reader接口和io.Closer接口的組合。

io.ReadWriteCloser:這個(gè)接口是io.Reader、io.Writerio.Closer三個(gè)接口的組合。

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

該方法可以根據(jù)給定的偏移量,基于數(shù)據(jù)的起始位置、末尾位置、或者當(dāng)前讀寫位置去尋找新的讀寫位置。這個(gè)新的讀寫位置用于表明下一次讀或?qū)憰r(shí)的起始索引。

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

io.ReadWriteSeeker:這個(gè)接口是io.Reader、io.Writerio.Seeker三個(gè)接口的組合。

2.2 io.Reader接口的實(shí)現(xiàn)類型

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

該類型的讀取方法Read返回的總數(shù)據(jù)量會受到限制。無論該方法被調(diào)用多少次。這個(gè)限制由該類型的字段N指明,單位是字節(jié)。

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

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

*io.teeReader:該類型是一個(gè)包級私有的數(shù)據(jù)類型,也是io.TeeReader函數(shù)結(jié)果值的實(shí)際類型。

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

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

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

當(dāng)這個(gè)結(jié)果值當(dāng)Read方法被調(diào)用,它會順序地從前面那些io.Reader類型的參數(shù)值中讀取數(shù)據(jù)。因此,我們也稱之為多對象讀取器。

*io.pipe:此類型是一個(gè)包級私有的數(shù)據(jù)類型。它不但實(shí)現(xiàn)了io.Reader接口,而且還實(shí)現(xiàn)了io.Writer接口。

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

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

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

在實(shí)際的面試中,只要應(yīng)聘者能夠從某一個(gè)方面出發(fā),說出io.Reader的擴(kuò)展接口及其存在意義,或者說清楚該接口的三五個(gè)實(shí)現(xiàn)類型,那么就可以算是基本回答正確了。

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) {
	// 創(chuàng)建一個(gè)字符串
	// 創(chuàng)建一個(gè)字符串讀取器,它的名字是 reader1。
	fmt.Println("創(chuàng)建一個(gè)字符串讀取器,它的名字是 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āng)前的所以,移動(dòng)%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)建一個(gè)新的限制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)建一個(gè)新的teeReader, 帶有一個(gè)reader和一個(gè)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)建一個(gè)section Reader 帶有一個(gè)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)建一個(gè)multi-reader, 帶有4個(gè)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)建一個(gè)新的內(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í)行完成
	// 在實(shí)際中沒必要這樣做
	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包的接口以及它們之間的關(guān)系

沒有嵌入其它接口并且只定義了一個(gè)方法的接口,總共有11個(gè)。其中有3個(gè)接口有著眾多的擴(kuò)展接口和實(shí)現(xiàn)類型,它們是:io.Reader、io.Writerio.Closer。

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

3.1 讀操作接口

上面已經(jīng)討論,核心接口io.Reader有5個(gè)擴(kuò)展接口,6個(gè)實(shí)現(xiàn)類型。更多的讀操作接口還有:

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

type ByteScanner interface {
	ByteReader
	UnreadByte() error
}

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

type RuneScanner interface {
	RuneReader
	UnreadRune() error
}

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

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

它只讀其所屬值中包含的字節(jié),而不對這個(gè)值進(jìn)行真正的修改。比如,它絕對不能修改已讀計(jì)數(shù)的值。

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

與之對應(yīng)的接口是io.ReaderFrom

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

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

io.Copyio.CopyBuffer,和io.CopyN一樣。因?yàn)樗鼈儍?nèi)部復(fù)制到時(shí)候,使用同一套代碼。

3.2 寫操作接口

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

基于io.Writer 擴(kuò)展的接口

io.ReadWriter

*io.pipe就是io.ReadWriter 接口的實(shí)現(xiàn)類型。

io.ReadWriteClose

io.ReadWriteSeeker

io.WriteCloser

io.WriteSeeker

io.ByteWriter

io.WriterAt

*io.File不但是io.WriterAt的實(shí)現(xiàn)類型,同時(shí)還實(shí)現(xiàn)了io.ReadWriterCloser、io.ReadWriteSeeker接口。

3.3 讀寫位置設(shè)定接口

io.Seeker接口作為一個(gè)讀寫位置設(shè)定相關(guān)的接口,僅定義了一個(gè)方法,叫Seek

基于io.Seeker擴(kuò)展的接口:

io.ReadSeeker

io.ReadWriteSeeker

io.WriteSeeker

io.WriteSeeker是基于io.Writerio.Seeker的擴(kuò)展接口

*strings.Reader*io.SectionReader都實(shí)現(xiàn)了io.Seeker接口,這兩個(gè)類型也都是io.ReaderAt接口的實(shí)現(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)

3.4 關(guān)閉操作

io.Closer

它的實(shí)現(xiàn)類型,在io包里只有io.PipeReaderio.PipeWriter

四、總結(jié)11個(gè)簡單接口和9個(gè)擴(kuò)展接口

4.1 讀取操作接口有5個(gè)

io.Reader

io.ByteReader

io.RuneReader

io.ReaderAt

io.WriterTo

4.2 寫入操作接口有4個(gè)

io.Writer

io.ByteWriter

io.WriterAt

io.ReaderFrom

4.3 關(guān)閉操作接口有1個(gè)

io.Closer

4.4 讀寫位置設(shè)定的接口有1個(gè)

io.Seeker

4.5 基于11簡單接口的擴(kuò)展接口有9個(gè)

io.ReadWriter

io.ReadCloser

io.ReadSeeker

io.ByteScanner

io.RuneScanner

io.ReadWriteCloser

io.ReadWriteSeeker

io.WriteCloser

io.WriteSeeker

到此這篇關(guān)于GOLang IO接口與工具使用方法講解的文章就介紹到這了,更多相關(guān)GO IO接口與工具內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang channle管道的基本使用及快速入門

    Golang channle管道的基本使用及快速入門

    管道是Go語言中實(shí)現(xiàn)并發(fā)的一種方式,它可以在多個(gè)goroutine之間進(jìn)行通信和數(shù)據(jù)交換,本文主要介紹了Golang channle管道的基本使用及快速入門,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Go語言官方依賴注入工具Wire的使用教程

    Go語言官方依賴注入工具Wire的使用教程

    依賴注入是一種實(shí)現(xiàn)控制反轉(zhuǎn)且用于解決依賴性問題的設(shè)計(jì)模式。Golang?中常用的依賴注入工具主要有?Inject?、Dig?等。但是今天主要介紹的是?Go?團(tuán)隊(duì)開發(fā)的?Wire,一個(gè)編譯期實(shí)現(xiàn)依賴注入的工具,感興趣的可以了解一下
    2022-09-09
  • 教你一招完美解決vscode安裝go插件失敗問題

    教你一招完美解決vscode安裝go插件失敗問題

    VSCode是我們開發(fā)go程序的常用工具,但是安裝VSCode成功后,創(chuàng)建一個(gè).go文件居然提示錯(cuò)誤了,所以下面下面這篇文章主要給大家介紹了如何通過一招完美解決vscode安裝go插件失敗問題的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • ubuntu下搭建Go語言(golang)環(huán)境

    ubuntu下搭建Go語言(golang)環(huán)境

    這篇文章主要介紹了ubuntu下搭建Go語言(golang)環(huán)境,需要的朋友可以參考下
    2015-01-01
  • GoLang中拼接字符串性能優(yōu)化方法詳解

    GoLang中拼接字符串性能優(yōu)化方法詳解

    最近在做性能優(yōu)化,有個(gè)函數(shù)里面的耗時(shí)特別長,看里面的操作大多是一些字符串拼接的操作,而字符串拼接在 golang 里面其實(shí)有很多種實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于Golang語言如何高效拼接字符串的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • 淺析Go語言中閉包的定義與使用

    淺析Go語言中閉包的定義與使用

    閉包是編程語言中的一個(gè)重要概念,它允許函數(shù)不僅僅是獨(dú)立的代碼塊,還可以攜帶數(shù)據(jù)和狀態(tài),本文將深入探討閉包的定義、用途和注意事項(xiàng),以及如何正確使用閉包,有需要的可以參考下
    2023-09-09
  • Go語言入門exec的基本使用示例

    Go語言入門exec的基本使用示例

    這篇文章主要為大家介紹了Go語言入門exec在go語言中的基本使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Go語言框架快速集成限流中間件詳解

    Go語言框架快速集成限流中間件詳解

    這篇文章主要為大家介紹了Go語言框架快速集成限流中間件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • GO語言類型轉(zhuǎn)換和類型斷言實(shí)例分析

    GO語言類型轉(zhuǎn)換和類型斷言實(shí)例分析

    這篇文章主要介紹了GO語言類型轉(zhuǎn)換和類型斷言,以實(shí)例形式詳細(xì)分析了類型轉(zhuǎn)換和類型斷言的概念與使用技巧,需要的朋友可以參考下
    2015-01-01
  • 使用Golang實(shí)現(xiàn)加權(quán)負(fù)載均衡算法的實(shí)現(xiàn)代碼

    使用Golang實(shí)現(xiàn)加權(quán)負(fù)載均衡算法的實(shí)現(xiàn)代碼

    這篇文章主要介紹了使用Golang實(shí)現(xiàn)加權(quán)負(fù)載均衡算法的實(shí)現(xiàn)代碼,詳細(xì)說明權(quán)重轉(zhuǎn)發(fā)算法的實(shí)現(xiàn),通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09

最新評論