關(guān)于Go語(yǔ)言中的IO操作詳解
在現(xiàn)代軟件開發(fā)中,高效的輸入輸出(I/O)操作是提高程序性能的關(guān)鍵之一。Go語(yǔ)言提供了豐富的I/O操作接口,使得文件讀寫、網(wǎng)絡(luò)通信等任務(wù)變得簡(jiǎn)單而高效。
Go語(yǔ)言的I/O操作主要通過(guò)標(biāo)準(zhǔn)庫(kù)中的io包和os包實(shí)現(xiàn)。o包提供了一系列用于輸入和輸出操作的基本接口和原語(yǔ)。這些接口和原語(yǔ)構(gòu)成了Go語(yǔ)言中處理I/O操作的基礎(chǔ),支持多種I/O設(shè)備的讀寫操作,包括文件、網(wǎng)絡(luò)連接、內(nèi)存緩沖區(qū)等。而os包則提供了對(duì)操作系統(tǒng)功能的封裝,包括文件操作、進(jìn)程管理等。
一、os包簡(jiǎn)介
os包是Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的一個(gè)重要包,提供了操作系統(tǒng)相關(guān)的功能接口。通過(guò)os包,我們可以執(zhí)行各種底層操作,如讀取和寫入文件、獲取系統(tǒng)信息、執(zhí)行外部命令等。
二、常用函數(shù)與示例
1. 文件操作
1.1 獲取文件信息
Stat:獲取文件信息對(duì)象,符號(hào)鏈接會(huì)跳轉(zhuǎn)。
Lstat:獲取文件信息對(duì)象,符號(hào)鏈接不跳轉(zhuǎn)。
package main
import (
"fmt"
"os"
)
//看下fileinfo接口
// file
// 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 : 權(quán)限
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
// 獲取更加詳細(xì)的文件信息, *syscall.Stat_t 反射來(lái)獲取
Sys() any // underlying data source (can return nil)
*/
func main() {
// 獲取某個(gè)文件的狀態(tài)
//func Stat(name string) (FileInfo, error)
fileinfo, err := os.Stat("F:\\goworks\\src\\jingtian\\yufa\\type別名\\type別名.go")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(fileinfo.Name()) // 文件名 demo01.go
fmt.Println(fileinfo.IsDir()) // 是否目錄 false
fmt.Println(fileinfo.ModTime()) // 文件的修改時(shí)間 2024-09-26 10:03:01.0946679 +0800 CST
fmt.Println(fileinfo.Size()) // 文件大小 1542 字節(jié)數(shù)
fmt.Println(fileinfo.Mode()) // 權(quán)限 -rw-rw-rw-
}

1.2 創(chuàng)建文件
Create:創(chuàng)建文件,如果文件存在,則清空原文件。
package main
import (
"fmt"
"os"
)
func main() {
//創(chuàng)建文件,文件不存在就創(chuàng)建文件,如果文件存在,則清空原文件。
// func Create(name string) (*File, error)
file, err := os.Create("example.txt")
if err != nil {
fmt.Println(err)
return
}
//關(guān)閉文件,延遲執(zhí)行
defer file.Close()
//向文件中寫內(nèi)容
// func (f *File) WriteString(s string) (n int, err error)
_, err = file.WriteString("Hello, World!")
if err != nil {
fmt.Println(err)
}
fmt.Println("File created successfully")
}
文件創(chuàng)建,并且寫入成功

創(chuàng)建的文件默認(rèn)權(quán)限是0666

1.3 刪除文件
Remove:刪除文件或目錄(單一文件)只能刪除空文件夾,文件不存在會(huì)報(bào)錯(cuò)。如果文件夾中有文件也刪不掉
RemoveAll:遞歸刪除文件或目錄,文件或目錄不存在不報(bào)錯(cuò),返回nil。

package main
import (
"fmt"
"os"
)
func main() {
// 刪除文件
// func Remove(name string) error
//文件不存在會(huì)報(bào)錯(cuò)
err := os.Remove("example.txt")
if err != nil {
fmt.Println(err)
} else {
fmt.Println("File removed successfully")
}
// 遞歸刪除目錄
// func RemoveAll(path string) error
//目錄不存在返回nil 不會(huì)報(bào)錯(cuò)
//可以刪除指定目錄下的目錄或文件
err = os.RemoveAll("testdir\\mydir.go")
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Directory removed successfully")
}
}

1.4 重命名或移動(dòng)文件
Rename:重命名文件或移動(dòng)文件。
package main
import (
"fmt"
"os"
)
func main() {
// 重命名文件
// func Rename(oldpath, newpath string) error
err := os.Rename("張三.txt", "新張三.txt")
if err != nil {
fmt.Println(err)
} else {
fmt.Println("File renamed successfully")
}
// 移動(dòng)文件
err = os.Rename("新張三.txt", "testdir\\新張三.txt")
if err != nil {
fmt.Println(err)
} else {
fmt.Println("File moved successfully")
}
}
1.5 打開文件
使用os.Open函數(shù)可以打開一個(gè)文件,返回一個(gè)*os.File類型的文件對(duì)象。如果文件打開失敗,會(huì)返回一個(gè)錯(cuò)誤。
package main
import (
"fmt"
"os"
)
func main() {
//func Open(name string) (*File, error)
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
fmt.Println("File opened successfully")
//打印打開的文件,是個(gè)內(nèi)存地址
fmt.Println("Reading file:", file)
}

打開文件常用方式二:os.OpenFile
在Go語(yǔ)言中,文件的讀寫操作是使用非常頻繁的功能之一。os.OpenFile函數(shù)是Go標(biāo)準(zhǔn)庫(kù)中用于打開文件的強(qiáng)大工具,它允許以多種模式打開文件,并可以設(shè)置文件的權(quán)限。
os.OpenFile函數(shù)簡(jiǎn)介
os.OpenFile函數(shù)用法如下:
func OpenFile(name string, flag int, perm FileMode) (File, error)
name:要打開的文件名或路徑。
flag:打開文件的模式,可以是多個(gè)標(biāo)志的按位或組合。常見(jiàn)的標(biāo)志包括:
os.O_RDONLY:只讀模式。
os.O_WRONLY:只寫模式。
os.O_RDWR:讀寫模式。
os.O_APPEND:追加模式,在文件末尾寫入數(shù)據(jù)而不覆蓋原有數(shù)據(jù)。只要有這個(gè)參數(shù),就會(huì)采用追加模式
os.O_CREATE:如果文件不存在則創(chuàng)建文件。
os.O_EXCL:與O_CREATE一起使用,可執(zhí)行權(quán)限。
os.O_SYNC:同步模式,將文件更改刷新到磁盤。
os.O_TRUNC:截?cái)嗄J?,清空文件?nèi)容。
perm:文件權(quán)限,表示文件的讀寫權(quán)限,默認(rèn)為0666(即所有用戶都可讀寫)。
返回值是一個(gè)指向打開文件的File對(duì)象和一個(gè)可能出現(xiàn)的錯(cuò)誤。如果文件打開成功,則可以通過(guò)該文件對(duì)象進(jìn)行讀取和寫入操作。
使用os.OpenFile寫文件
以下是一個(gè)使用os.OpenFile函數(shù)寫文件的示例:
package main
import (
"fmt"
"os"
)
func main() {
// 以追加、創(chuàng)建、讀寫模式打開文件
file, err := os.OpenFile("./example.txt", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
if err != nil {
fmt.Println("打開文件失敗:", err)
return
}
defer file.Close() // 確保在函數(shù)執(zhí)行完畢后關(guān)閉文件
// 寫入文件
_, err = file.Write([]byte("Hello, Go!\n"))
if err != nil {
fmt.Println("寫入文件失敗:", err)
return
}
fmt.Println("文件寫入成功")
}
將內(nèi)容追加到文件中

1.6 讀取文件
使用os.File對(duì)象的Read方法可以從文件中讀取數(shù)據(jù)。Read方法會(huì)將數(shù)據(jù)讀取到一個(gè)字節(jié)切片中,并返回讀取的字節(jié)數(shù)和可能發(fā)生的錯(cuò)誤。
需要借助 file.Read([]byte)讀取 ,將file中的數(shù)據(jù)讀取到 []byte 中, n,err n讀取到的行數(shù),err 錯(cuò)誤,EOF錯(cuò)誤,就代表文件讀取完畢了
一直調(diào)用read,就代表光標(biāo)往后移動(dòng)…
以下是一個(gè)使用os.Open函數(shù)讀文件的示例:
package main
import (
"fmt"
"os"
)
// 讀取文件數(shù)據(jù)
func main() {
// 我們習(xí)慣于在建立連接時(shí)候通過(guò)defer來(lái)關(guān)閉連接,保證程序不會(huì)出任何問(wèn)題,或者忘記關(guān)閉
// 建立連接
file, _ := os.Open("example.txt")
// 關(guān)閉連接
defer file.Close()
// 讀代碼 ,Go 的錯(cuò)誤機(jī)制,讓我們專心可以寫業(yè)務(wù)代碼。
// 1、創(chuàng)建一個(gè)容器 (二進(jìn)制文本文件--0100101010 => 讀取流到一個(gè)容器 => 讀取容器的數(shù)據(jù))
//一次性讀取的內(nèi)容長(zhǎng)度為切片的長(zhǎng)度,切片長(zhǎng)度為2,容量為1024
bs := make([]byte, 2, 1024) // 緩沖區(qū),可以接受我們讀取的數(shù)據(jù) 這里設(shè)置的是一次性讀取兩個(gè)字節(jié)
fmt.Printf("字節(jié)切片數(shù)據(jù)類型%T\n", bs)
// 2、讀取到緩沖區(qū)中。 // 漢字一個(gè)漢字占 3個(gè)字節(jié)
// func (f *File) Read(b []byte) (n int, err error) 返回讀到的字節(jié)數(shù)和錯(cuò)誤
// At end of file, Read returns 0, io.EOF. 讀到文件末尾返回0和io.EOF
n, err := file.Read(bs)
fmt.Println(n)
fmt.Println(err)
//每次讀取光標(biāo)移動(dòng)切片的長(zhǎng)度,將讀取的內(nèi)容存到切片中。如果讀取的文件是文本數(shù)據(jù),可以通過(guò)string方法將切片中的內(nèi)容轉(zhuǎn)換為字符串
//如果是MP4呀,音樂(lè),圖片等文件,就不要用string轉(zhuǎn)換了
fmt.Println(string(bs)) // 讀取到的字符串 ab
//繼續(xù)往下讀
// 光標(biāo)不停的向下去指向,讀取出來(lái)的內(nèi)容就存到我們的容器中。
file.Read(bs)
fmt.Println(string(bs)) // 讀取到的字符串 cd
file.Read(bs)
fmt.Println(string(bs)) // 讀取到的字符串 e
//讀到文件末尾,得到的n是0,err是EOF
n, err = file.Read(bs)
fmt.Println(n)
fmt.Println(err) // EOF ,讀取到了文件末尾。err就會(huì)返回EOF。
//最后讀到了e,將原來(lái)切片中的cd的c覆蓋了,得到的最終結(jié)果是ed
fmt.Println(string(bs)) // 讀取到的字符串
}

1.7 IO寫
寫的話,要考慮文件的權(quán)限問(wèn)題,大致流程如下
建立連接 (設(shè)置權(quán)限:可讀可寫,擴(kuò)充這個(gè)文件的append) os.OpenFile
關(guān)閉連接
寫入文件常用的方法
- file.Write
- file.WriteString
先看下example.txt文件

package main
import (
"fmt"
"os"
)
func main() {
fileName := "example.txt"
// 權(quán)限:如果我們要向一個(gè)文件中追加內(nèi)容, O_APPEND, 如果沒(méi)有,就是從頭開始寫
file, _ := os.OpenFile(fileName, os.O_WRONLY|os.O_RDONLY|os.O_APPEND, os.ModePerm)
defer file.Close()
// 操作 字節(jié)切片寫入
bs := []byte{65, 66, 67, 68, 69} // A B C D E ASCII編碼
// func (f *File) Write(b []byte) (n int, err error)
//write方法 寫入的是二進(jìn)制數(shù)據(jù)字節(jié)流,即字節(jié)切片
n, err := file.Write(bs)
if err != nil {
fmt.Println(err)
}
fmt.Println(n)
// string類型的寫入,可以直接將字符串寫入到文件中
n, err = file.WriteString("hhahahahah哈哈哈哈哈哈哈")
if err != nil {
fmt.Println(err)
}
fmt.Println(n)
}

再看下example.txt文件,可以看到我們寫入的內(nèi)容全部追加到文件末尾

如果打開文件的方式不包含os.O_APPEND 則是將源文件覆蓋寫。os.O_APPEND的意思是,在打開文件時(shí),將光標(biāo)移動(dòng)到文件末尾
2. 目錄操作
2.1 創(chuàng)建目錄
Mkdir:使用指定的權(quán)限和名稱創(chuàng)建一個(gè)目錄,目錄存在會(huì)報(bào)錯(cuò)。
MkdirAll:遞歸創(chuàng)建目錄,包括任何必要的上級(jí)目錄,目錄存在不報(bào)錯(cuò)。
package main
import (
"fmt"
"os"
)
func main() {
// 創(chuàng)建單個(gè)目錄
// func Mkdir(name string, perm FileMode) error
// os.ModePerm 是0777的權(quán)限
//mkidr創(chuàng)建目錄,目錄存在的情況下,會(huì)報(bào)錯(cuò) Cannot create a file when that file already exists.
err := os.Mkdir("singledir", os.ModePerm)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Single directory created successfully")
}
// 遞歸創(chuàng)建目錄,目錄存在不報(bào)錯(cuò)
// func MkdirAll(path string, perm FileMode) error
err = os.MkdirAll("nested/dirs/test", os.ModePerm)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Nested directories created successfully")
}
}
2.2 更改當(dāng)前工作目錄
Getwd:獲取當(dāng)前工作目錄。
Chdir:修改當(dāng)前工作目錄。
package main
import (
"fmt"
"os"
)
func main() {
// 獲取當(dāng)前工作目錄
path, err := os.Getwd()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Current working directory:", path)
// 修改當(dāng)前工作目錄
err = os.Chdir("../")
if err != nil {
fmt.Println(err)
return
}
path, err = os.Getwd()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("New working directory:", path)
}

3. 環(huán)境變量
3.1 獲取環(huán)境變量
Environ:返回所有的環(huán)境變量,格式為“key=value”的字符串切片。
Getenv:檢索并返回名為key的環(huán)境變量的值,如果不存在則返回空字符串。
Setenv:
函數(shù)定義:func Setenv(key, value string) error
功能:設(shè)置名為key的環(huán)境變量,如果出錯(cuò)會(huì)返回該錯(cuò)誤。
package main
import (
"fmt"
"os"
"strings"
)
func main() {
// 設(shè)置環(huán)境變量
err := os.Setenv("MY_ENV_VAR", "my_value")
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Environment variable set successfully")
}
// 獲取并打印剛設(shè)置的環(huán)境變量
value := os.Getenv("MY_ENV_VAR")
fmt.Println("MY_ENV_VAR:", value)
//查看所有環(huán)境變量
envs := os.Environ()
for _, env := range envs {
cache := strings.Split(env, "=")
fmt.Printf("key=%v value=%v\n", cache[0], cache[1])
}
// 清除所有環(huán)境變量(謹(jǐn)慎使用)
// err = os.Clearenv()
// if err != nil {
// fmt.Println(err)
// } else {
// fmt.Println("All environment variables cleared")
// }
}

4. 程序退出
Exit:讓當(dāng)前程序以給出的狀態(tài)碼code退出。一般來(lái)說(shuō),狀態(tài)碼0表示成功,非0表示出錯(cuò)。程序會(huì)立刻終止,并且defer的函數(shù)不會(huì)被執(zhí)行。
package main
import (
"fmt"
"os"
)
func main() {
// 正常退出
fmt.Println("Exiting the program successfully")
//os.Exit(0)
// 異常退出(不會(huì)執(zhí)行到這里的代碼)
fmt.Println("This line will not be executed")
os.Exit(1)
}

5. 獲取系統(tǒng)信息
Hostname:返回內(nèi)核提供的主機(jī)名。
Getuid:返回調(diào)用者的用戶ID。
Getgid:返回調(diào)用者的組ID。
Getpid:返回調(diào)用者所在進(jìn)程的進(jìn)程ID。
package main
import (
"fmt"
"os"
)
func main() {
// 獲取主機(jī)名
hostname, err := os.Hostname()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Hostname:", hostname)
// 獲取用戶ID
uid := os.Getuid()
fmt.Println("User ID:", uid)
// 獲取組ID
gid := os.Getgid()
fmt.Println("Group ID:", gid)
// 獲取進(jìn)程ID
pid := os.Getpid()
fmt.Println("Process ID:", pid)
}

6. 執(zhí)行外部命令
os/exec包用于執(zhí)行外部命令,它提供了更高級(jí)別的接口來(lái)創(chuàng)建和管理進(jìn)程。
1. 執(zhí)行簡(jiǎn)單命令
package main
import (
"fmt"
"os/exec"
)
func main() {
//查看系統(tǒng)中是否安裝有該命令
cmd_path, err := exec.LookPath("ipconfig")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("系統(tǒng)中有該命令,命令路徑為:", cmd_path)
//Command每個(gè)參數(shù)都不能包含空格。多個(gè)參數(shù),用引號(hào)包裹,逗號(hào)隔開
cmd := exec.Command("ipconfig")
// 如果不需要命令的輸出,直接調(diào)用cmd.Run()即可
err2 := cmd.Run()
if err2 != nil {
fmt.Println("Error:", err2)
} else {
fmt.Println("Command executed successfully")
}
}

使用exec.Command函數(shù)創(chuàng)建一個(gè)代表外部命令的Cmd對(duì)象,然后使用Run方法執(zhí)行命令并等待其完成。
我們使用 exec.Command() 創(chuàng)建了一個(gè)執(zhí)行 ipconfig 命令的 *exec.Cmd,然后使用 Run() 方法啟動(dòng)了命令。
請(qǐng)注意,使用 exec.Command() 創(chuàng)建的命令默認(rèn)不會(huì)有任何輸出。如果我們想獲取命令的標(biāo)準(zhǔn)輸出,我們可以使用 Output() 或 CombinedOutput() 方法。如果我們想獲取命令的標(biāo)準(zhǔn)錯(cuò)誤輸出,我們需要單獨(dú)設(shè)置 Cmd.Stderr 字段。
2. 獲取命令輸出
使用Output方法運(yùn)行命令并返回其標(biāo)準(zhǔn)輸出的內(nèi)容。
package main
import (
"fmt"
"os/exec"
)
func main() {
//查看系統(tǒng)中是否安裝有該命令
cmd_path, err := exec.LookPath("ipconfig")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("系統(tǒng)中有該命令,命令路徑為:", cmd_path)
cmd := exec.Command("ipconfig")
output, err := cmd.Output()
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Command output:", string(output))
}
}
3. 處理標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤
CombinedOutput
func (c *Cmd) CombinedOutput() ([]byte, error)
說(shuō)明:運(yùn)行命令并返回組合到一起的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤
package main
import (
"fmt"
"os/exec"
)
func main() {
//查看系統(tǒng)中是否安裝有該命令
cmd_path, err := exec.LookPath("ping")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("系統(tǒng)中有該命令,命令路徑為:", cmd_path)
// 創(chuàng)建一個(gè)新的命令,例如運(yùn)行dir命令
cmd := exec.Command("ping", "www.baidu.com")
//獲取標(biāo)準(zhǔn)輸出
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("標(biāo)準(zhǔn)輸出為:", string(out))
}

三、文件復(fù)制
文件復(fù)制需要考慮的問(wèn)題:
1、拿到需求,分析需求,編輯函數(shù) copy()
2、編寫參數(shù)(源文件,目標(biāo)地址,緩沖區(qū)大小)
3、讀取源文件,保存到緩沖區(qū)中
4、讀取緩沖區(qū)的內(nèi)容,將內(nèi)容寫入到新文件中
5、確保源文件讀取完畢了,使用到for()循環(huán)。循環(huán)結(jié)束標(biāo)志 io.EOF或者讀取到的字節(jié)數(shù)為0
1. 自定義的文件復(fù)制實(shí)現(xiàn)
我們創(chuàng)建個(gè)目錄utils。里面創(chuàng)建個(gè)copy.go
package utils
import (
"fmt"
"io"
"os"
)
// Copy 方法需要參數(shù)為:source 源文件 ,destination 目標(biāo)文件,緩沖區(qū)大小
func Copy(source, destination string, bufferSize int) {
// 讀取文件,讀文件open方法就可以
sourceFile, err := os.Open(source)
if err != nil {
fmt.Println("Open錯(cuò)誤:", err)
}
// 輸出文件 O_WRONLY , O_CREATE 如果不不存在,則會(huì)創(chuàng)建
destinationFile, err := os.OpenFile(destination, os.O_WRONLY|os.O_CREATE, os.ModePerm)
if err != nil {
fmt.Println("OpenFile錯(cuò)誤:", err)
}
// 關(guān)閉連接
defer sourceFile.Close()
defer destinationFile.Close()
// 專注業(yè)務(wù)代碼,拷貝
// 創(chuàng)建緩沖區(qū)大小
buf := make([]byte, bufferSize)
// 循環(huán)讀取,寫入
for {
//一次讀取設(shè)置的緩沖區(qū)大小的數(shù)據(jù)
n, err := sourceFile.Read(buf)
// 循環(huán)結(jié)束標(biāo)志
if n == 0 || err == io.EOF {
fmt.Println("讀取完畢源文件,復(fù)制完畢")
break
} else if err != nil {
fmt.Println("讀取錯(cuò)誤:", err)
return // 錯(cuò)誤之后,必須要return終止函數(shù)執(zhí)行。
}
// 將緩沖區(qū)的東西寫出到目標(biāo)文件
// 因?yàn)檠h(huán)寫入過(guò)程中沒(méi)有關(guān)閉文件,所以可以持續(xù)寫入
//根據(jù)實(shí)際讀取的長(zhǎng)度寫入,防止最后一次讀取時(shí),讀取的少于緩沖區(qū)長(zhǎng)度
_, err = destinationFile.Write(buf[:n])
if err != nil {
fmt.Println("寫出錯(cuò)誤:", err)
}
}
}

調(diào)用我們的copy方法,實(shí)現(xiàn)文件copy
package main
import "jingtian/yufa/io操作/utils"
func main() {
source := "C:\\Users\\dell\\Desktop\\appsearch.zip"
dest := "F:\\goworks\\src\\jingtian\\yufa\\io操作\\目標(biāo)文件.zip"
utils.Copy(source, dest, 1024)
}

運(yùn)行,可以將源文件復(fù)制到目標(biāo)地址

2. 使用系統(tǒng)自帶的io.Copy()方法復(fù)制
// Copy2 使用系統(tǒng)自帶的io.Copy方法
func Copy2(source, destination string) {
// 讀取文件
sourceFile, err := os.Open(source)
if err != nil {
fmt.Println("Open錯(cuò)誤:", err)
}
// 輸出文件 O_WRONLY , O_CREATE 如果不不存在,則會(huì)創(chuàng)建
destinationFile, err := os.OpenFile(destination, os.O_WRONLY|os.O_CREATE, os.ModePerm)
if err != nil {
fmt.Println("OpenFile錯(cuò)誤:", err)
}
// 關(guān)閉
defer sourceFile.Close()
defer destinationFile.Close()
// 具體的實(shí)現(xiàn)
// 不用我們自己寫循環(huán)讀取寫入了,直接調(diào)用系統(tǒng)的io.Copy()方法
// func Copy(dst Writer, src Reader) (written int64, err error) 返回寫入的字節(jié)數(shù)和錯(cuò)誤
written, err := io.Copy(destinationFile, sourceFile)
if err != nil {
fmt.Println("復(fù)制時(shí)出現(xiàn)錯(cuò)誤", err)
return
}
fmt.Println("文件的字節(jié)大小:", written)
}
3. 使用os.ReadFile和os.WriteFile來(lái)實(shí)現(xiàn)讀取寫入,從而實(shí)現(xiàn)復(fù)制
// Copy3 使用os.ReadFile和os.WriteFile來(lái)實(shí)現(xiàn)讀取寫入,從而實(shí)現(xiàn)復(fù)制
func Copy3(source, destination string) {
// func ReadFile(name string) ([]byte, error)
fileBuffer, _ := os.ReadFile(source)
//func WriteFile(name string, data []byte, perm FileMode) error
err := os.WriteFile(destination, fileBuffer, 0644)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("文件復(fù)制完成")
}
4. io.CopyBuffer() 適合大文件復(fù)制
// Copy4 io.CopyBuffer() 適合大文件
func Copy4(source, destination string, bufferSize int) {
// 讀取文件
sourceFile, err := os.Open(source)
if err != nil {
fmt.Println("Open錯(cuò)誤:", err)
}
// 輸出文件 O_WRONLY , O_CREATE 如果不不存在,則會(huì)創(chuàng)建
destinationFile, err := os.OpenFile(destination, os.O_WRONLY|os.O_CREATE, os.ModePerm)
if err != nil {
fmt.Println("OpenFile錯(cuò)誤:", err)
}
// 關(guān)閉
defer sourceFile.Close()
defer destinationFile.Close()
// 具體的實(shí)現(xiàn)
// 創(chuàng)建緩沖區(qū)大小
buf := make([]byte, bufferSize)
// 不用我們自己寫循環(huán)讀取寫入了,直接調(diào)用系統(tǒng)的io.Copy()方法
//io.copy這個(gè)適合小文件,大文件使用io.CopyBuffer
// func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
written, err := io.CopyBuffer(destinationFile, sourceFile, buf)
if err != nil {
fmt.Println("復(fù)制時(shí)出現(xiàn)錯(cuò)誤", err)
return
}
fmt.Println("文件的字節(jié)大小:", written)
}
以上就是關(guān)于Go語(yǔ)言中的IO操作詳解的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言IO操作的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang中匿名組合實(shí)現(xiàn)偽繼承的方法
這篇文章主要介紹了Golang中匿名組合實(shí)現(xiàn)偽繼承的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Go語(yǔ)言實(shí)現(xiàn)數(shù)組去重的20種實(shí)現(xiàn)方式總結(jié)
數(shù)組去重是最常見(jiàn)的算法,本文整理 Go 數(shù)組和切片去重的 20 種寫法,按 5 個(gè)策略分類,幫你理解每類的核心思路,大家可以根據(jù)自己的需求進(jìn)行選擇2026-05-05
用Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)Web服務(wù)之項(xiàng)目介紹
從本節(jié)開始將從后端到前端一步一步實(shí)現(xiàn)一個(gè)Go語(yǔ)言Web服務(wù),后端除了MySQL驅(qū)動(dòng),全部使用Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)來(lái)實(shí)現(xiàn)一個(gè)小型項(xiàng)目,本篇將簡(jiǎn)單的介紹一下項(xiàng)目開發(fā)要準(zhǔn)備的流程,感興趣的同學(xué)可以閱讀一下2023-05-05
如何使用Golang發(fā)送Get和Post請(qǐng)求
這篇文章主要給大家介紹了關(guān)于如何使用Golang發(fā)送Get和Post請(qǐng)求的相關(guān)資料,Go語(yǔ)言(Golang)的標(biāo)準(zhǔn)庫(kù)提供了處理HTTP請(qǐng)求的功能,這使得將Go用于web應(yīng)用程序變得非常容易,需要的朋友可以參考下2023-06-06
golang 后臺(tái)進(jìn)程的啟動(dòng)和停止操作
這篇文章主要介紹了golang 后臺(tái)進(jìn)程的啟動(dòng)和停止操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04
Go語(yǔ)言實(shí)現(xiàn)從PDF自動(dòng)化提取條碼的開發(fā)全流程解析
在實(shí)際的業(yè)務(wù)場(chǎng)景中,我們常常需要從?PDF?文件中提取條碼信息,本文將通過(guò)?Go?語(yǔ)言開發(fā)一個(gè)自動(dòng)掃描目錄內(nèi)所有?PDF?并提取條碼的工具,感興趣的小伙伴可以了解下2025-11-11
golang時(shí)間字符串和時(shí)間戳轉(zhuǎn)換的案例
這篇文章主要介紹了golang時(shí)間字符串和時(shí)間戳轉(zhuǎn)換的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12

