網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
前言
IO 操作是我們?cè)诰幊讨胁豢杀苊鈺?huì)遇到的,例如讀寫(xiě)文件,Go語(yǔ)言的 io 包中提供了相關(guān)的接口,定義了相應(yīng)的規(guī)范,不同的數(shù)據(jù)類(lèi)型可以根據(jù)規(guī)范去實(shí)現(xiàn)相應(yīng)的方法,提供更加豐富的功能。
Go 語(yǔ)言提倡小接口 + 接口組合的方式,來(lái)擴(kuò)展程序的行為以及增加程序的靈活性。io代碼包恰恰就可以作為這樣的一個(gè)標(biāo)桿,它可以成為我們運(yùn)用這種技巧時(shí)的一個(gè)參考標(biāo)準(zhǔn)。io包中包含了大量接口,本篇文章我們就先來(lái)學(xué)習(xí)四個(gè)核心接口以及對(duì)應(yīng)的接口組合。
Reader
io.Reader接口定義了 Read 方法,用于讀取數(shù)據(jù)到字節(jié)數(shù)組中:
- 入?yún)ⅲ鹤止?jié)數(shù)組 p,會(huì)將數(shù)據(jù)讀入到 p 中
- 返回值:本次讀取的字節(jié)數(shù) n,以及遇到的錯(cuò)誤 err
type Reader interface { Read(p []byte) (n int, err error) }
方法功能詳解
- 方法讀取數(shù)據(jù)寫(xiě)入到字節(jié)數(shù)組 p 中,由于 p 是有大小的,所以一次至多讀取 len(p) 個(gè)字節(jié)
- 方法返回讀取的數(shù)據(jù)字節(jié)數(shù) n(0 <= n <= len(p)),以及讀取過(guò)程中遇到的 error
- 即使一次調(diào)用讀取到的數(shù)據(jù)小于 len(p),也可能會(huì)占用整個(gè)字節(jié)數(shù)組 p 作為暫存空間
- 如果數(shù)據(jù)源的數(shù)據(jù)量小于 len(p) 個(gè)字節(jié),方法只會(huì)讀取當(dāng)前可用數(shù)據(jù),不會(huì)等待更多數(shù)據(jù)的到來(lái)
何時(shí)返回error
- 在成功讀取了 n(n>0)個(gè)字節(jié)后,如果產(chǎn)生了 error 或者 讀到文件末尾 (end-of-file),本次調(diào)用必須要返回讀取的字節(jié)數(shù) n,但對(duì)于err 的值,可以選擇在本次直接返回 err(err!=nil),或者在下次調(diào)用的時(shí)候再返回 err (n=0, err!=nil)。常見(jiàn)的一個(gè)例子就是,讀取到n個(gè)字節(jié)后到達(dá)文件末尾(EOF),此時(shí)可以返回 err=EOF 或者 err=nil,下次調(diào)用返回 n=0,err=EOF。
- 調(diào)用者需要注意,每次調(diào)用后,如果 n>0,應(yīng)該先處理數(shù)據(jù),再考慮 err 是否為 nil。因?yàn)樯弦稽c(diǎn)已經(jīng)指出,如果讀取到 n>0 個(gè)字節(jié)后遇到 error,會(huì)同時(shí)返回 n>0 和 err!=nil,此時(shí)就需要先處理數(shù)據(jù)再考慮 err。
方法實(shí)現(xiàn)和調(diào)用需注意
- 如果想要實(shí)現(xiàn)該方法,不推薦同時(shí)返回 n=0 和 err=nil,除非 len(p)=0
- 如果調(diào)用該該方法返回 n=0 和 err=nil,可以認(rèn)為什么都沒(méi)有發(fā)生,不能認(rèn)為是讀到文件末尾了(end-of-file)
- 實(shí)現(xiàn)該方法后,一定不要持有字節(jié)數(shù)組p (保留下地址做他用)
Writer
io.Writer接口定義了 Write 方法,用于寫(xiě)數(shù)據(jù)到文件中
- 入?yún)ⅲ鹤止?jié)數(shù)組 p,會(huì)將 p 中的數(shù)據(jù)寫(xiě)入到文件中
- 返回值:成功寫(xiě)入完成的字節(jié)數(shù) n,以及遇到的錯(cuò)誤 err
type Writer interface { Write(p []byte) (n int, err error) }
方法功能詳解
- 該方法將 p 中的數(shù)據(jù)寫(xiě)到文件中
- 方法返回成功寫(xiě)入的字節(jié)數(shù) n(0 <= n <= len(p)),以及寫(xiě)入過(guò)程中遇到的錯(cuò)誤 err
- 如果 n<len(p),方法必須返回 err!=nil
- 方法一定不能修改字節(jié)數(shù)組 p,即使是臨時(shí)修改也不被允許
方法實(shí)現(xiàn)需注意
實(shí)現(xiàn)該方法后,一定不要持有字節(jié)數(shù)組p,只是用來(lái)讀取數(shù)據(jù)
Closer
io.Closer接口定義了 Close 方法,該方法用于關(guān)閉連接。
方法實(shí)現(xiàn)需注意
第一次調(diào)用該方法后,再次調(diào)用該方法應(yīng)該產(chǎn)生什么行為,該接口沒(méi)有定義,依賴(lài)實(shí)現(xiàn)方法自定義。
type Closer interface { Close() error }
Seeker
io.Seeker接口定義了 Seek 方法,該方法用于指定下次讀取或者寫(xiě)入時(shí)的偏移量
入?yún)ⅲ河?jì)算新偏移量的起始值 whence, 基于whence的偏移量offset
返回值:基于 whence 和 offset 計(jì)算后新的偏移量值,以及可能產(chǎn)生的錯(cuò)誤
type Seeker interface { Seek(offset int64, whence int) (int64, error) }
方法功能詳解
io包中定義了如下三種 whence
const ( SeekStart = 0 // 基于文件開(kāi)始位置 SeekCurrent = 1 // 基于當(dāng)前偏移量 SeekEnd = 2 // 基于文件結(jié)束位置 )
如果計(jì)算后新的偏移量,在文件起始位置之前,返回 error!=nil
任意正數(shù)的偏移量都是合法的,但是對(duì)數(shù)據(jù)源如何進(jìn)行I/O操作,依賴(lài)具體的實(shí)現(xiàn)方法
組合接口
在go語(yǔ)言中,可以利用接口的組合,來(lái)囊括其他接口中的方法,類(lèi)似于定義了一個(gè)父接口,可以包含多個(gè)子接口。如果一個(gè) struct 實(shí)現(xiàn)了所有子接口的方法,也就相當(dāng)于實(shí)現(xiàn)了父接口。小接口 + 接口組合的方式,很大程度上增加了程序的靈活性,在我們自己業(yè)務(wù)開(kāi)發(fā)過(guò)程中,可以借鑒這種做法。
針對(duì)上面四個(gè)最小粒度的接口,io包定義了如下幾種組合接口:
// ReadWriter 是 Read 和 Write 方法的組合 type ReadWriter interface { Reader Writer } // ReadCloser 是 Read 和 Close 方法的組合 type ReadCloser interface { Reader Closer } // WriteCloser 是 Write 和 Close 方法的組合 type WriteCloser interface { Writer Closer } // ReadWriteCloser 是 Read、Write 和 Close 方法的組合 type ReadWriteCloser interface { Reader Writer Closer } // ReadSeeker 是 Read 和 Seek 方法的組合 type ReadSeeker interface { Reader Seeker } // WriteSeeker 是 Write 和 Seek 方法的組合 type WriteSeeker interface { Writer Seeker } // ReadWriteSeeker 是 Read、Write 和 Seek 方法的組合 type ReadWriteSeeker interface { Reader Writer Seeker }
總結(jié)
本篇文章介紹了 io包 中的四大核心接口:
- Reader : 讀取文件中的數(shù)據(jù)到字節(jié)數(shù)組中
- Writer : 將字節(jié)數(shù)組的數(shù)據(jù)寫(xiě)入到文件中
- Closer : 用于關(guān)閉連接
- Seeker : 給定 whence 和 offset,計(jì)算得出新的offset,用于在特定位置開(kāi)始讀寫(xiě)
可以看到 Reader 和 Writer 接口中定義的方法中,都有字節(jié)數(shù)組p,而底層要操作的文件在方法中都沒(méi)有體現(xiàn)。Read方法是將文件的數(shù)據(jù)讀入字節(jié)數(shù)組p,Write 是將字節(jié)數(shù)組p的數(shù)據(jù)寫(xiě)入文件,這一點(diǎn)不要記混。
原文鏈接:https://juejin.cn/post/7041579897818447903
相關(guān)推薦
- 2023-03-22 gin正確多次讀取http?request?body內(nèi)容實(shí)現(xiàn)詳解_Golang
- 2022-09-13 Python?迭代器介紹及作用詳情_(kāi)python
- 2022-06-26 Android如何使用圓形揭露動(dòng)畫(huà)巧妙地隱藏或顯示View詳解_Android
- 2023-01-05 Presenting?Streams?in?Flutter小技巧_Android
- 2022-06-22 Android在Sqlite3中的應(yīng)用及多線(xiàn)程使用數(shù)據(jù)庫(kù)的建議(實(shí)例代碼)_Android
- 2023-05-06 docker?search命令的具體使用_docker
- 2022-03-23 QT實(shí)現(xiàn)定時(shí)關(guān)閉消息提示框_C 語(yǔ)言
- 2022-06-09 忘記Grafana不要緊2種Grafana重置admin密碼方法詳細(xì)步驟_服務(wù)器其它
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支