最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

重學Go語言之文件操作詳解

 更新時間:2023年08月08日 16:22:40   作者:程序員讀書  
有很多場景都需要對文件進行讀取或者寫入,比如讀取配置文件或者寫入日志文件,在Go語言中,操作文件應該算是一件比較簡單的事情,我們在這一篇文章中,一起來探究一下

有很多場景都需要對文件進行讀取或者寫入,比如讀取配置文件或者寫入日志文件,除此之外,有時候我們也需要修改文件名稱,遍歷目錄內的文件,刪除文件,在Go語言中,操作文件應該算是一件比較簡單的事情,我們在這一篇文章中,一起來探究一下。

文件句柄:os.File

Go語言中,標準庫os包下的File結構體表示一個文件句柄,獲得了os.File,就可以對文件進行各種操作,要獲得一個os.File文件句柄,有以下三種方式:

os.Create

通過os.Create()函數傳入一個文件名稱可以創(chuàng)建并獲得一個表示該文件的os.File結構體:

file,err := os.Create("./my.dat")

如果指定的文件不存在,調用該函數后,會創(chuàng)建文件,如果文件已經存在,則只會清空文件的內容。

os.Open

對于已經存在的文件,如果不想清空文件內容,只想打開該文件的話,可以用os.Open()函數:

file, err := os.Open("./my.dat")

用該函數打開一個文件句柄時,如果文件不存在,返回值err返回一個error類型的錯誤。

os.OpenFile

其實,os.Create()函數和os.Open()函數的底層都是調用os.OpenFile()函數,這一點從os.Creat()os.Open()函數的源碼可以得到證實:

//該源碼位于標準庫os包下的file.go文件中
func Open(name string) (*File, error) {
	return OpenFile(name, O_RDONLY, 0)
}
func Create(name string) (*File, error) {
	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}

os.OpenFile()函數簽名如下:

func OpenFile(name string, flag int, perm FileMode) (*File, error) 

從函數簽名可以看到調用os.OpenFile函數時要傳入三個參數,其中name是表示要打開的文件名。

而第二個參數flag表示打開文件的標志,比較常用有以下幾種取值:

  • O_RDONLY:只讀
  • O_WRONLY:只寫
  • O_RDWR:讀寫
  • O_APPEND:以追加的方式寫入
  • O_CREATE:文件不存在時創(chuàng)建
  • O_TRUNC:當文件存在時,將文件內容置空

可以同時指定多個標志,多個標志用邏輯運算符|連接起來,比如os.Create()函數在調用os.OpenFile函數時就傳入多個標志:

OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)

os.OpenFile()函數的第三個參數 FileMode就是指類Unix操作系統(tǒng)中的文件讀寫權限,即r(讀)、w(寫),x(執(zhí)行),一個文件的rwx有三組:

-rw-r--r--   1 root  staff  215  4 17 11:14 main.go

-rw-r--r--分別表示文件擁有者、擁有者所在群組、其他人對該文件的權限,如果沒有該權限用-表示。

rwx用八進制表示時r=4,w=2,x=1,所以上面main.go文件權限用八進制表示為0644。

無論是用哪種方式打開的文件句柄,最終都要記得關閉以釋放資源,比較標準的用法是用defer語句:

name := "./my.dat"
file,err := OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0755) 
if err != nil{
  panic(err)
}
defer file.Close()

讀取文件

要讀取文件的內容,在獲得文件句柄時,OpenFile函數的參數flag只需要傳O_RDONLY就可以了,而參數FileMode可以為0:

file, err := os.OpenFile("./my.dat", os.O_RDONLY, 0)

os.File有一個Read()方法,也就是說os.File實現io.Reader接口,Go標準庫很多的包可以處理io.Reader接口,比如ioutil,bufio,fmt等,因此有很多種方式可以讀取文件的內容。

直接讀取

os.FileRead方法就可以直接將文件內容讀取一個字節(jié)數組中,并返回讀取的長度和一個用于判斷是否出錯的error類型:

package main
import (
	"fmt"
	"io"
	"os"
)
func main() {
	f, err := os.Open("./my.dat")
	if err != nil {
		panic(err)
	}
	defer f.Close()
	for {
		b := make([]byte, 10) 
		n, err := f.Read(b) //將文件內容讀取到字節(jié)數組中
		if n == 0 || err == io.EOF {
			return
		}
		fmt.Println(n, string(b))
	}
}

在上面的例子中,我們循環(huán)讀取文件內容,直到讀取到文件末尾時,返回的字節(jié)長度0和一個io.EOF的error類型,這時候表示文件已經讀完,可以結束讀取了。

使用bufio包讀取文件

當要用bufio包讀取文件時,將調用bufio.NewReader()函數將io.Reader包裝為一個bufio.Reader結構體,該結構體封裝了很多更便捷讀取文件的方法:

func (b *Reader) Read(p []byte) (n int, err error)
func (b *Reader) ReadByte() (byte, error)
func (b *Reader) ReadBytes(delim byte) ([]byte, error)
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
func (b *Reader) ReadRune() (r rune, size int, err error)
func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
func (b *Reader) ReadString(delim byte) (string, error)

下面是ReadLine方法的使用示例:

package main
import (
	"bufio"
	"fmt"
	"io"
	"os"
)
func main() {
	file, err := os.OpenFile("./my.dat", os.O_RDWR, 0666)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	reader := bufio.NewReader(file)
	for {
    //按行讀取
		b, _, err := reader.ReadLine() 
		if err == io.EOF {
			break
		}
		fmt.Println(string(b))
	}
}

使用fmt包讀取文件

fmt包以FScan...開頭的函數可以按一定的格式掃描讀取文件里的內容:

func Fscan(r io.Reader, a ...any) (n int, err error)
func Fscanf(r io.Reader, format string, a ...any) (n int, err error)
func Fscanln(r io.Reader, a ...any) (n int, err error)

下面是Fscanln方法的使用示例:

package main
import (
	"fmt"
	"io"
	"os"
)
func main() {
	file, err := os.OpenFile("./my.dat", os.O_RDWR, 0666)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	for {
		var a1, a2 string
		_, err := fmt.Fscanln(file, &a1, &a2)
		fmt.Println(a2, a2)
		if err == io.EOF {
			break
		}
	}
}

使用ioutil包讀取文件

標準庫的ioutil包對讀取文件做好封裝,可以直接讀取整個文件的數據:

f, err := os.Open("./my.dat")
if err != nil {
		panic(err)
}
var b []byte
b,err := ioutil.ReadAll(f)

ioutil甚至封裝了直接讀取文件的函數:

var b []byte
b,err := ioutil.ReadFile("./my.dat")

寫入文件

要向文件寫入內容,在調用OpenFile()函數獲得句柄時flag參數要傳入O_WRONLY或者O_RDWR,如果是要往文件中以追加的形式在文件后面插入內容,還是需要O_APPEND:

OpenFile(name, O_RDWR|O_CREATE|O_APPEND, 0666)

os.FileWrite方法,也就是說os.File也實現了io.Writer接口,所以同樣可以調用fmt、bufio、ioutil包將數據寫入到文件中。

直接寫入

寫入文件最簡單的方式就是調用os.File類型的Write方法寫入一個字節(jié)數組:

package main
import "os"
func main() {
	file, err := os.OpenFile("./my.dat", os.O_RDWR, 0666)
	if err != nil {
		panic(file)
	}
	defer file.Close()
	file.Write([]byte("test222222"))
}

也可以調用os.FileWriteString直接寫入一個字符串:

file.WriteString("test222222")

使用bufio包寫入文件

bufio包的NewWriter可以將一個io.Writer包裝為bufio.Writer結構體,該結構體主要有以下幾個方法可以將數據寫入文件:

func (b *Writer) Write(p []byte) (nn int, err error)
func (b *Writer) WriteByte(c byte) error
func (b *Writer) WriteRune(r rune) (size int, err error)
func (b *Writer) WriteString(s string) (int, error)

上面幾個方法似乎與io.File自身所擁有的方法差別不大,但bufio包的寫入是帶有緩沖區(qū)的,也就是說當我們寫入數據時,不是立刻寫入到文件,而是寫到內存緩沖區(qū),最后調用Flush方法才將數據寫入文件。

package main
import (
	"bufio"
	"os"
)
func main() {
	file, err := os.OpenFile("./my.dat", os.O_RDWR, 0666)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	writer.Write([]byte("111111111"))
	writer.Flush()
}

使用fmt包寫入文件

fmt包以下三個函數可以將格式化的數據寫入到一個io.Writer:

func Fprint(w io.Writer, a ...any) (n int, err error)
func Fprintf(w io.Writer, format string, a ...any) (n int, err error)
func Fprintln(w io.Writer, a ...any) (n int, err error)

下面是使用fmt寫入文件的示例:

package main
import (
	"fmt"
	"os"
)
func main() {
	file, err := os.OpenFile("./my.dat", os.O_RDWR, 0666)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	fmt.Fprintf(file, "%s:%s", "username", "test")
}

使用ioutil包寫入文件

同樣的,ioutil包也對寫入文件做了封裝,使用一個函數便可以完成上碼代碼要完成的事情:

ioutil.WriteFile("./my.dat", []byte("22222"), 0666)

判斷是否為目錄

要判斷文件是否為目錄,在獲得os.File對象,可以調用該對象的Stat方法,該返回返回一個實現了os.FileInfo接口的對象:

type FileInfo interface {
	Name() string       // base name of the file
	Size() int64        // length in bytes for regular files; system-dependent for others
	Mode() FileMode     // file mode bits
	ModTime() time.Time // modification time
	IsDir() bool        // abbreviation for Mode().IsDir()
	Sys() any           // underlying data source (can return nil)
}

示例:

fileInfo, err := file.Stat()
if fileInfo.IsDir() {
	fmt.Println(fileInfo.Name())
}

遍歷目錄

如果想遍歷目錄,可以調用os.ReadDir()函數,該函數返回一個元素類型為os.DirEntry的切片:

func (f *File) ReadDir(n int) ([]DirEntry, error)

os.DirEntry是一個接口,其定義如下:

type DirEntry interface {
	Name() string
	IsDir() bool
	Type() FileMode
	Info() (FileInfo, error)
}

可以看到DirEntry接口也有IsDir()方法,因為可以再往下遍歷,下面是一個實現目錄遍歷的示例:

package main
import (
	"fmt"
	"log"
	"os"
)
func main() {
	base := "./"
	IterateFolder(base)
}
func IterateFolder(base string) {
	dirEntry, err := os.ReadDir(base)
	if err != nil {
		log.Fatal(err)
	}
	for _, v := range dirEntry {
		if v.IsDir() {
			IterateFolder(base + "/" + v.Name())
		} else {
			fmt.Println(v.Name())
		}
	}
}

修改文件名稱

修改文件名稱用os.Rename函數:

err := os.Rename("./1.txt", "./2.txt")

os.Rename函數也可以用于移動文件:

err := os.Rename("./1.txt", "./m/2.txt")

刪除文件

刪除一個文件或者一個空目錄,直接調用os包的Remove()函數即可:

fileName := "./1.txt"
os.Remove(fileName)

可以根據error的返回值是否為nil判斷是否刪除成功,比如我們刪除一個不存在的文件或者刪除一個非空的目錄:

//m為當前目錄下一個非空目錄
err := os.Remove("./m")
fmt.Println(err)

執(zhí)行結果:

remove ./m: directory not empty

對于非空目錄,如果要刪除,可以用os包的RemoveAll函數:

err := os.RemoveAll("./m")

小結

好了,至此,相信你對于在Go語言如何讀取和寫入文件應該掌握了吧,總結一下,在這篇文章中,主要講了以下幾點:

  • 如何獲得一個文件句柄os.File。
  • 如何以不同的方式讀取文件內容。
  • 如何以不同的方式向文件寫入內容。
  • 對文件的不同操作。

以上就是重學Go語言之文件操作詳解的詳細內容,更多關于Go文件操作的資料請關注腳本之家其它相關文章!

相關文章

  • go并發(fā)數據一致性事務的保障面試應答

    go并發(fā)數據一致性事務的保障面試應答

    這篇文章主要為大家介紹了go并發(fā)數據一致性事務的保障面試應答,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Go??Zerolog使用入門教程

    Go??Zerolog使用入門教程

    Zerolog是一個高性能的Go日志庫,通過零分配設計和結構化輸出JSON格式,適用于高并發(fā)場景,它支持日志級別、采樣、Context、Hook機制和同時輸出控制臺和日志文件等功能,本文介紹Go Zerolog使用入門教程,感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • Golang精編49面試題匯總(選擇題)

    Golang精編49面試題匯總(選擇題)

    這篇文章主要介紹了Golang精編49面試題匯總(選擇題),本文章內容詳細,具有很好的參考價值,希望對大家有所幫助,需要的朋友可以參考下
    2023-01-01
  • golang解析json數據的4種方法總結

    golang解析json數據的4種方法總結

    在日常工作中每一名開發(fā)者,不管是前端還是后端,都經常使用 JSON,下面這篇文章主要給大家介紹了關于golang解析json數據的4種方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-06-06
  • golang多次讀取http request body的問題分析

    golang多次讀取http request body的問題分析

    這篇文章主要給大家分析了golang多次讀取http request body的問題,文中通過代碼示例和圖文介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • Go泛型之泛型約束示例詳解

    Go泛型之泛型約束示例詳解

    這篇文章主要給大家介紹了關于Go泛型之泛型約束的相關資料,泛型是靜態(tài)語言中的一種編程方式,這種編程方式可以讓算法不再依賴于某個具體的數據類型,而是通過將數據類型進行參數化,以達到算法可復用的目的,需要的朋友可以參考下
    2023-12-12
  • Go中Zero日志使用指南

    Go中Zero日志使用指南

    本文主要介紹了Go中Zero日志使用指南,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-02-02
  • golang常用庫之字段參數驗證庫-validator使用詳解

    golang常用庫之字段參數驗證庫-validator使用詳解

    這篇文章主要介紹了golang常用庫:字段參數驗證庫-validator使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借價值,需要的朋友可以參考下
    2020-10-10
  • Go語言基于viper實現apollo多實例快速

    Go語言基于viper實現apollo多實例快速

    viper是適用于go應用程序的配置解決方案,這款配置管理神器,支持多種類型、開箱即用、極易上手。本文主要介紹了如何基于viper實現apollo多實例快速接入,感興趣的可以了解一下
    2023-01-01
  • 以alpine作為基礎鏡像構建Golang可執(zhí)行程序操作

    以alpine作為基礎鏡像構建Golang可執(zhí)行程序操作

    這篇文章主要介紹了以alpine作為基礎鏡像構建Golang可執(zhí)行程序操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評論

车致| 金平| 静安区| 泌阳县| 林西县| 彭州市| 夏河县| 昌乐县| 武定县| 天柱县| 安达市| 遂昌县| 苍梧县| 大厂| 岳普湖县| 绥中县| 秦皇岛市| 大丰市| 大理市| 呈贡县| 金平| 理塘县| 巴中市| 威海市| 广饶县| 盐城市| 合阳县| 云浮市| 体育| 邵阳县| 辉县市| 长治县| 从化市| 如皋市| 榕江县| 鲁山县| 普兰县| 南康市| 大庆市| 平塘县| 乌审旗|