<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Go文件系統的概念

Linux愛好者 ? 來源:Linux愛好者 ? 作者:Linux愛好者 ? 2022-10-17 10:05 ? 次閱讀

什么神奇問題 ?

Go 在文件 IO 的場景有個神奇的事情。打開一個文件的時候,返回的竟然不是 interface ,而是一個 os.File 結構體的指針。

funcOpen(namestring)(*File,error){
returnOpenFile(name,O_RDONLY,0)
}

劃重點:這個意味著,Go 的文件系統的概念和 OS 的文件系統的概念直接關聯起來。你必須傳入一個文件路徑,并且必須真的要去打開一個操作系統的文件。

不用接口,而是跟具體類型強相關的話,會導致后續的擴展性不好。比如,全都是 os 包的使用,那么將操作強綁定在 OS 文件系統上。

最常見的,在單測的時候用的這種方式的話,就真的要在操作系統上打開文件做操作。Go 的設計者對此一直耿耿于懷,但是也很無奈。因為用戶已經用上了,Go 的承諾是往前兼容,直接修改原有語義和接口肯定不行。

怎么辦?

Go 1.16 給了我們答案。Go 給了我們一個 io.FS 的封裝。Go 的意圖是在自己的語言層面再做一層 FS 的抽象,這樣就能和 OS 的 FS 解耦開來。io.FS 可以是任何奇形怪狀的 FS ,只要你實現了規定好的 FS 接口。下一步來看下 Go 1.16 帶來的幾個核心改動。

有人說 Go 都 1.19 了,還看 1.16 ?

因為 Go 的 io/fs 是在 Go 1.16 引入的。在 io 方面有比較大的一個變化。

Go 1.16 關于 io 有哪些改變 ?

新增了一個 io/fs 的包,抽象了一個 FS 出來。

embed 的 package 用了這個抽象。

規整 io/ioutil 里面的內容。

接下來我們一個個看下。

io.FS 的抽象

1Go 為什么要抽象 FS ?

前面已經提到,Go 的文件系統的概念和 OS 的文件系統的概念直接關聯起來。這個給擴展性帶來了不方便。最重要的,Go 已經發現有和 OS 不同的文件系統的需求了,就是 embed FS 。

embed 是 Go 提供的一個打包文件到二進制的功能,也是類似文件系統的一種需求。但是卻不是直接位于 OS 上的文件系統(vfs 那套東西)。

所以在 Go 1.16 順勢就一起上了。引入了 io.FS 的定義,并且 embed 就直接用上了這層抽象。

![[fs 封裝層次.png]]

2來看下 FS 接口的定義

Go 的實現者們很強,推薦的是小接口。也就是最小化、原子化的接口語義。從 io/fs 的定義就能看到很強的功力。

//文件系統的接口
typeFSinterface{
Open(namestring)(File,error)
}

//文件的接口
typeFileinterface{
Stat()(FileInfo,error)
Read([]byte)(int,error)
Close()error
}

這,就是最簡單的 FS 。 這個就是文件系統極簡的樣子,只需要有一個 Open 方法,返回一個文件即可。

也就是說,Go 理解的文件系統,只要能實現一個 Open 方法,返回一個 File 的 interface ,這個 File 只需要實現 Stat,Read,Close 方法即可。

有沒有發現,OS 的 FS 已經滿足了條件。所以,Go 的 FS 可以是 OS 的 FS ,自然也可以是其他的實現。

Go 在此 io.FS 的基礎上,再去擴展接口,增加文件系統的功能。比如,加個 ReadDir 就是一個有讀目錄的文件系統 ReadDirFS :

typeReadDirFSinterface{
FS
//讀目錄
ReadDir(namestring)([]DirEntry,error)
}

加個 Glob 方法,就成為一個具備路徑通配符查詢的文件系統:

typeGlobFSinterface{
FS
//路徑通配符的功能
Glob(patternstring)([]string,error)
}

加個 Stat ,就變成一個路徑查詢的文件系統:

typeStatFSinterface{
FS
//查詢某個路徑的文件信息
Stat(namestring)(FileInfo,error)
}

這些非常經典的文件系統的定義 Go 在 io/fs 里面已經做好了。

3io.FS 怎么使用呢?

我們的目標是實現一個 Go 的 FS ,這個定義已經在 io.FS 有了。我們只需要寫一個結構體,實現它的方法,那么你就可以說這是一個 FS 了。

這里其實就可以有非常多的想象空間,比如,可以是 OS 的 FS,也可以是 memory FS ,hash FS 等等。網上有不少例子。但其實標準庫已經有一個最好的例子,那就是 embed FS 。

我們來看下 embed 怎么實現一個內嵌的文件系統。embed 的實現在 embed/embed.go 這個文件中,非常精簡。

首先,在 embed package 里定義了一個結構體 FS ,這個結構體將是 io.FS 的具體實現。

//作為具體FS的實現
typeFSstruct{
files*[]file
}

//代表一個內嵌文件
typefilestruct{
namestring
datastring//文件的數據全在內存里
hash[16]byte//truncatedSHA256hash
}

embed 里面的 FS 結構體只需要實現 Open 這個方法即可:

//Open的具體實現
func(fFS)Open(namestring)(fs.File,error){
//通過名字匹配查找到file對象
file:=f.lookup(name)
//如果沒找到
iffile==nil{
returnnil,&fs.PathError{Op:"open",Path:name,Err:fs.ErrNotExist}
}
//如果是目錄結構
iffile.IsDir(){
return&openDir{file,f.readDir(name),0},nil
}
//找到了就封裝成openFile結構體
return&openFile{file,0},nil
}

上面的 Open ,如果是文件的化,返回的是一個 openFile 的結構體 ,作為 io.File 接口的具體實現:

//代表一個文件的實現
typeopenFilestruct{
f*file//thefileitself
offsetint64//currentreadoffset
}
func(f*openFile)Close()error{returnnil}
func(f*openFile)Stat()(fs.FileInfo,error){returnf.f,nil}
func(f*openFile)Read(b[]byte)(int,error){
//判斷偏移是否符合預期
iff.offset>=int64(len(f.f.data)){
return0,io.EOF
}
iff.offset

如上,只需要實現 Read,Stat,Close 方法即可。這就是一個完整的、Go 層面的 FS 的實現。

你可以如下使用 embed 文件系統:

//go:embedhello.txt
varfembed.FS

funcmain(){
//打開文件
file,err:=f.Open("hello.txt")
//...
//讀文件
n,err=file.Read(/*buffer*/)
}

上面的例子,編譯的時候會把當前目錄下的一個 hello.txt 文件打包到二進制文件。程序啟動的時候可以把它讀出來。

注意:f 這個變量,編譯器會安排填充好。進程啟動時它是有值的。

Go 1.16 關于 IO 其他的改動

除了上面提到的 io/fs 和 embed fs ,Go 對之前的 io 的一些結構也做了更準確的調整分類。把之前大雜燴的 io/ioutil 里面的東西拆出來了。移到對應的 io 包和 os 包。為了兼容性,ioutil 包并沒有直接刪除,而是導入。比如:

Discard 移到了 io 庫實現

ReadAll 移到了 io 庫實現

NopCloser 移到了 io 庫實現

ReadFile 移到 os 庫實現

WriteFile 移到 os 庫實現

基本上 ioutil 這個 package 是被掏空了。Go 1.16 只是為了兼容性還沒刪。

Go 的 FS 封裝有啥用呢 ?

好處其實很多,最明顯的兩個:

單測方便了。

有類似 embed FS 這種非 OS 文件系統的需求,可以有方法擴展了。

總結

Go 在自己的層面封裝出一個 io.FS 的抽象,意圖和 OS 的 FS 解耦。這樣可以給程序員帶來更多的想象空間 ;

embed FS 具備典型的 FS 的界面,但是它并不是直接位于 OS 的文件系統。所以它非常適合作為首個用 io.FS 的實踐;

以后盡量用 io.FS 來管理的文件,這樣可以做到和 OS 解耦,方便做單測;

ioutil 可以少用,它的功能已經被移到更明確的 package 里實現了;

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    7737

    瀏覽量

    148699
  • 操作系統
    +關注

    關注

    37

    文章

    6318

    瀏覽量

    121972
  • 文件系統
    +關注

    關注

    0

    文章

    272

    瀏覽量

    19707

原文標題:Go 眼中的文件系統是什么? io.FS

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Go文件系統概念及實現

    Go文件 IO 的場景有個神奇的事情。打開一個文件的時候,返回的竟然不是 interface ,而是一個 os.File 結構體的指針。
    發表于 10-17 10:00 ?476次閱讀

    Linux文件系統課程

    本章學習目標理解什么是文件系統了解文件系統工作原理理解Fedora Core Linux文件系統的結構掌握Fedora Core Linux文件系統的類型、權限和修改方法掌握如何安裝、
    發表于 04-10 17:07 ?0次下載

    NTFS文件系統,NTFS文件系統是什么意思

    NTFS文件系統,NTFS文件系統是什么意思 NTFS是Windows NT以及之后的Windows 2000、Windows XP、Windows Server 2003、Windows Server 2008
    發表于 03-29 10:38 ?5695次閱讀

    XfS文件系統,XfS文件系統是什么意思

    XfS文件系統,XfS文件系統是什么意思 XfS文件系統是SGI開發的高級日志文件系統,XFS極具伸縮性,非常健壯。所幸的是SGI將其移植到了Lin
    發表于 03-29 10:39 ?4089次閱讀

    Linux根文件系統簡介

    Linux根文件系統簡介 什么是根文件   根文件系統首先是一種文件系統,但是相對于普通的文件系統,它的特殊之處在于,它是內核啟動時所m
    發表于 04-21 17:01 ?5036次閱讀

    FatFs文件系統使用

    STM系列FatFs文件系統使用文件,希望對大家有幫助。
    發表于 11-06 18:10 ?8次下載

    嵌入式系統文件系統比較

    Linux支持多種文件系統,包括ext2、ext3、vfat、ntfs、iso9660、jffs、romfs和nfs等,為了對各類文件系統 進行統一管理,Linux引入了虛擬文件系統VFS
    發表于 11-01 15:35 ?1次下載

    文件系統是什么?淺談EXT文件系統歷史

    在先前關于Linux文件系統的文章中,我很想去深入地討論更多EXT文件系統的特性的信息。所以,首先讓我們來回答這個問題:什么是文件系統?一個文件系統應該遵循以下特點。
    發表于 06-28 09:03 ?5448次閱讀
    <b class='flag-5'>文件系統</b>是什么?淺談EXT<b class='flag-5'>文件系統</b>歷史

    linux文件系統中的虛擬文件系統設計詳解

    Linux 中允許眾多不同的文件系統共存,如 ext2, ext3, vfat 等。通過使用同一套文件 I/O 系統 調用即可對 Linux 中的任意文件進行操作而無需考慮其所在的具體
    發表于 04-02 14:37 ?1605次閱讀
    linux<b class='flag-5'>文件系統</b>中的虛擬<b class='flag-5'>文件系統</b>設計詳解

    一文解讀文件系統的作用性(二)

    我就嘗試著來模擬一次文件系統的演進過程,于是,我們來到了那一天,那天之前,人們還沒有文件系統概念。 友情提示 : 下面將在荒誕的場景下演進人類合理的訴求 神說,要有光,于是,光照大地 神說,要有風,于是,風動四方 神說,人類要
    的頭像 發表于 09-21 14:17 ?1567次閱讀
    一文解讀<b class='flag-5'>文件系統</b>的作用性(二)

    如何去自制文件系統?開發文件系統為什么難?

    我們先從什么是文件系統講起,簡單介紹一些探索文件系統的基礎知識。
    的頭像 發表于 06-11 16:27 ?3171次閱讀
    如何去自制<b class='flag-5'>文件系統</b>?開發<b class='flag-5'>文件系統</b>為什么難?

    嵌入式Linux開發之文件系統目錄結構介紹

    中。一、與windows區別Linux不像windows有盤符的概念,只有一個根目錄概念,所有文件系統(硬盤、U盤、CDROM、網絡文件系統)都以一個子目錄掛根目錄下某一子目錄下。在L
    發表于 11-01 16:31 ?3次下載
    嵌入式Linux開發之<b class='flag-5'>文件系統</b>目錄結構介紹

    FATFS文件系統詳解

    一、文件系統負責管理和存儲文件信息的軟件機構稱為文件管理系統,簡稱文件系統。即在磁盤上組織文件
    發表于 11-29 09:51 ?29次下載
    FATFS<b class='flag-5'>文件系統</b>詳解

    什么是分布式文件系統

    我們無時無刻不在使用文件系統,進行開發時在使用文件系統,瀏覽網頁時在使用文件系統,玩手機時也在使用文件系統。
    的頭像 發表于 03-10 16:21 ?3714次閱讀

    Linux的文件系統特點

    Linux的文件系統特點 文件系統要有嚴格的組織形式,使得文件能夠以塊為單位進行存儲。 文件系統中也要有索引區,用來方便查找一個文件分成的多
    的頭像 發表于 11-09 14:48 ?605次閱讀
    Linux的<b class='flag-5'>文件系統</b>特點
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>