Go 中文件目录基本操作
本文内容基于 AI 生成结果整理,可能包含不准确信息,仅供参考使用。
本文目标
- 掌握 os 库的目录操作:创建/删除目录、遍历目录等
- 熟练文件读写操作:包括打开/关闭文件、读写内容
- 理解路径操作方法:处理相对/绝对路径、路径拼接等
相对路径时是基于执行时的工作目录,而不是代码文件位置
例如:
/home/user/projects/myproject/file/mian.go 存在代码 os.Create("./test.txt")
当你在 /home/user/projects/myproject/ 执行 file/mian.go 的程序时
会在 /home/user/projects/myproject/ 目录下创建 test.txt 文件
文件操作
创建文件
go
file, err := os.Create("./test.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
os.Create()
创建新文件,如果文件已存在则会被截断(清空)- 返回
*os.File
和可能的错误 - 记得使用
defer
关闭文件
打开文件
go
file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
os.Open()
以只读方式打开文件- 返回
*os.File
和可能的错误
打开文件(带选项)
go
file, err := os.OpenFile("test.txt", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
-
os.OpenFile()
可以指定打开模式和权限 -
常用模式:
os.O_RDONLY
:只读os.O_WRONLY
:只写os.O_RDWR
:读写os.O_APPEND
:追加os.O_CREATE
:不存在则创建os.O_TRUNC
:打开时清空文件
写入文件
go
content := []byte("Hello, World!\n")
_, err := file.Write(content)
if err != nil {
log.Fatal(err)
}
Write()
方法写入字节切片- 返回写入的字节数和可能的错误
读取文件
go
data := make([]byte, 100)
count, err := file.Read(data)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read %d bytes: %q\n", count, data[:count])
Read()
方法读取到字节切片- 返回读取的字节数和可能的错误
文件信息
go
fileInfo, err := os.Stat("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("File name:", fileInfo.Name())
fmt.Println("Size:", fileInfo.Size())
fmt.Println("Permissions:", fileInfo.Mode())
fmt.Println("Last modified:", fileInfo.ModTime())
fmt.Println("Is directory:", fileInfo.IsDir())
os.Stat()
获取文件信息- 返回
os.FileInfo
接口,包含文件的各种属性
删除文件
go
err := os.Remove("test.txt")
if err != nil {
log.Fatal(err)
}
os.Remove()
删除文件或空目录
目录操作
创建目录
go
err := os.Mkdir("mydir", 0755)
if err != nil {
log.Fatal(err)
}
-
os.Mkdir()
创建单级目录 -
0755 是 Unix 权限位,表示所有者可读写执行,组和其他可读执行
创建多级目录
go
err := os.MkdirAll("parent/child/grandchild", 0755)
if err != nil {
log.Fatal(err)
}
os.MkdirAll()
创建多级目录
读取目录
go
entries, err := os.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, entry := range entries {
fmt.Println(entry.Name())
if entry.IsDir() {
fmt.Println(" (directory)")
}
}
os.ReadDir()
读取目录内容- 返回
[]os.DirEntry
,比file.Readdir
更高效
删除目录
go
err := os.Remove("mydir")
if err != nil {
log.Fatal(err)
}
os.Remove()
删除空目录
只会删除空目录,即使里面存在的是空文件。
删除目录及其内容
go
err := os.RemoveAll("parent")
if err != nil {
log.Fatal(err)
}
os.RemoveAll()
递归删除目录及其所有内容
路径操作
虽然 os 包提供了一些路径操作,但更推荐使用 path/filepath 包:
go
import "path/filepath"
// 获取当前工作目录
dir, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
// 拼接路径
fullPath := filepath.Join(dir, "subdir", "file.txt")
// 获取绝对路径
absPath, err := filepath.Abs("relative/path")
if err != nil {
log.Fatal(err)
}
// 获取路径的基名
base := filepath.Base("/path/to/file.txt") // "file.txt"
// 获取路径的目录部分
dirPath := filepath.Dir("/path/to/file.txt") // "/path/to"
遍历目录
go
func walkDir(dir string) error {
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
fmt.Println("Directory:", path)
} else {
fmt.Println("File:", path)
}
return nil
})
}
临时文件和目录
go
// 创建临时文件
// 使用 os.CreateTemp 在系统默认临时目录创建临时文件
// 第一个参数""表示使用默认临时目录
// 第二个参数"example.*.txt"是文件名模式,*会被随机字符替换
// 返回的 tempFile 是 *os.File 对象,代表创建的临时文件
tempFile, err := os.CreateTemp("", "example.*.txt")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tempFile.Name())
// 创建临时目录
// 使用 os.MkdirTemp 在系统默认临时目录创建临时目录
// 第一个参数""表示使用默认临时目录
// 第二个参数"example"是目录名前缀,会自动添加随机后缀
// 返回 tempDir 是创建的临时目录的完整路径
tempDir, err := os.MkdirTemp("", "example")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(tempDir)
简单案例
文件操作
go
package main
import (
"fmt"
"os"
)
func main() {
// 写入文件
data := []byte("WangLei so cool!")
// Deprecated: As of Go 1.16, this function simply calls [os.WriteFile].
//err := ioutil.WriteFile("test.txt", data, 0644)
err := os.WriteFile("test.txt", data, 0644)
if err != nil {
fmt.Println("写入文件错误:", err)
return
}
fmt.Println("文件写入成功")
// 读取文件
// Deprecated: As of Go 1.16, this function simply calls [os.ReadFile].
//content, err := ioutil.ReadFile("test.txt")
content, err := os.ReadFile("test.txt")
if err != nil {
fmt.Println("读取文件错误:", err)
return
}
fmt.Println("文件内容:", string(content))
// 检查文件是否存在
if _, err := os.Stat("test.txt"); os.IsNotExist(err) {
fmt.Println("文件不存在")
} else {
fmt.Println("文件存在")
}
// 删除文件
err = os.Remove("test.txt")
if err != nil {
fmt.Println("删除文件错误:", err)
return
}
fmt.Println("文件删除成功")
}
目录操作
go
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
// 创建目录
err := os.Mkdir("testdir", 0755)
if err != nil {
fmt.Println("创建目录错误:", err)
return
}
fmt.Println("目录创建成功")
// 创建多级目录
err = os.MkdirAll("testdir/subdir1/subdir2", 0755)
if err != nil {
fmt.Println("创建多级目录错误:", err)
return
}
fmt.Println("多级目录创建成功")
// 遍历目录
fmt.Println("目录内容:")
err = filepath.Walk("testdir", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
fmt.Println(path)
return nil
})
if err != nil {
fmt.Println("遍历目录错误:", err)
}
// 删除目录
err = os.RemoveAll("testdir")
if err != nil {
fmt.Println("删除目录错误:", err)
return
}
fmt.Println("目录删除成功")
}
文件复制
go
package main
import (
"fmt"
"io"
"os"
)
func copyFile(src, dst string) (int64, error) {
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer destination.Close()
nBytes, err := io.Copy(destination, source)
return nBytes, err
}
func main() {
if len(os.Args) != 3 {
fmt.Println("用法: filecopy <源文件> <目标文件>")
return
}
src := os.Args[1]
dst := os.Args[2]
bytesCopied, err := copyFile(src, dst)
if err != nil {
fmt.Println("复制文件错误:", err)
return
}
fmt.Printf("成功复制 %d 字节从 %s 到 %s\n", bytesCopied, src, dst)
}