在Linux系统中使用Go语言进行文件操作是一个常见的任务,Go的标准库提供了丰富的功能来处理文件。以下是一个详细的指南,涵盖了从基本文件操作到高级操作的各个方面。
使用os.Open
打开文件,使用os.OpenFile
以读写模式打开文件,如果文件不存在则创建它。使用defer
确保文件最终被关闭。
package main
import (
"log"
"os"
)
func main() {
// 打开文件(只读模式)
file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// 以读写模式打开文件,如果不存在则创建,权限设置为644
file, err = os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
}
os.ReadFile
一次性读取整个文件内容。bufio.NewScanner
逐行读取文件。bufio.NewReader
进行缓冲读取。// 读取整个文件
data, err := os.ReadFile("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// 逐行读取
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
// 缓冲读取
reader := bufio.NewReader(file)
for {
line, err := reader.ReadString('\n')
if err != nil {
if err == io.EOF {
break
}
log.Fatal(err)
}
fmt.Print(line)
}
os.WriteFile
写入整个文件内容。bufio.NewWriter
进行缓冲写入,并调用Flush
确保数据写入底层io.Writer
。// 写入整个文件
content := []byte("Hello, Linux!")
err := os.WriteFile("output.txt", content, 0644)
if err != nil {
log.Fatal(err)
}
// 缓冲写入
writer := bufio.NewWriter(file)
_, err = writer.WriteString("Hello, Linux!\n")
if err != nil {
log.Fatal(err)
}
writer.Flush()
使用os.Stat
获取文件信息,包括文件名、大小、权限、最后修改时间等。使用os.Chmod
修改文件权限,使用os.Chown
修改文件所有者。
fileInfo, err := os.Stat("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("File name:", fileInfo.Name())
fmt.Println("Size in bytes:", fileInfo.Size())
fmt.Println("Permissions:", fileInfo.Mode())
fmt.Println("Last modified:", fileInfo.ModTime())
fmt.Println("Is directory:", fileInfo.IsDir())
// 修改文件权限
err = os.Chmod("test.txt", 0755)
if err != nil {
log.Fatal(err)
}
// 修改文件所有者
err = os.Chown("test.txt", os.Getuid(), os.Getgid())
if err != nil {
log.Fatal(err)
}
os.Mkdir
创建单个目录,使用os.MkdirAll
创建多级目录。os.ReadDir
读取目录内容。os.Remove
删除单个目录,使用os.RemoveAll
递归删除目录。// 创建目录
err := os.Mkdir("mydir", 0755)
if err != nil {
log.Fatal(err)
}
// 创建多级目录
err = os.MkdirAll("path/to/dir", 0755)
if err != nil {
log.Fatal(err)
}
// 读取目录内容
files, err := os.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Println(file.Name())
}
// 删除目录
err = os.Remove("mydir")
if err != nil {
log.Fatal(err)
}
// 递归删除目录
err = os.RemoveAll("path/to/dir")
if err != nil {
log.Fatal(err)
}
使用os.Rename
重命名文件或移动文件。
// 重命名文件
err := os.Rename("oldname.txt", "newname.txt")
if err != nil {
log.Fatal(err)
}
// 移动文件(在同一文件系统中)
err = os.Rename("/tmp/file.txt", "/home/user/file.txt")
if err != nil {
log.Fatal(err)
}
使用os.Symlink
创建符号链接,使用os.Readlink
读取符号链接目标。
// 创建符号链接
err := os.Symlink("original.txt", "link.txt")
if err != nil {
log.Fatal(err)
}
// 读取符号链接目标
target, err := os.Readlink("link.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("Link target:", target)
使用syscall.Flock
实现文件锁定。
import "syscall"
func lockFile(f *os.File) error {
err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
if err != nil {
return fmt.Errorf("failed to lock file: %v", err)
}
return nil
}
func unlockFile(f *os.File) error {
err := syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
if err != nil {
return fmt.Errorf("failed to unlock file: %v", err)
}
return nil
}
defer
关闭文件:这样可以确保文件描述符不会泄漏。bufio
可以提高性能。ReadFile
一次性读取整个文件。ioutil.TempFile
创建临时文件:它会自动处理文件名冲突。通过掌握这些文件操作技术,你可以在Linux环境下高效地使用Go语言处理各种文件相关的任务。