golang学习笔记:标准库os
Golang 的os包是与操作系统交互的核心工具,提供了文件操作、环境变量管理、进程控制等功能。
常用方法
文件和目录操作
1. 文件操作
// 创建文件
file, err := os.Create("test.txt")
defer file.Close()// 打开文件
file, err = os.Open("test.txt") // 只读
file, err = os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE, 0644)// 文件打开模式
os.O_RDONLY // 只读
os.O_WRONLY // 只写
os.O_RDWR // 读写
os.O_APPEND // 追加
os.O_CREATE // 不存在则创建
os.O_TRUNC // 打开时清空
os.O_EXCL // 与O_CREATE一起使用,文件必须不存在
2.文件读写
// 写入文件
content := []byte("Hello, World!")
n, err := file.Write(content)
n, err = file.WriteString("Hello, World!")// 读取文件
data := make([]byte, 100)
n, err = file.Read(data)// 文件定位
pos, err := file.Seek(0, io.SeekStart) // 移动到开头
pos, err = file.Seek(10, io.SeekCurrent) // 从当前位置移动10字节
pos, err = file.Seek(0, io.SeekEnd) // 移动到末尾
3.文件信息
// 获取文件信息
info, err := os.Stat("test.txt")
if err != nil {if os.IsNotExist(err) {fmt.Println("文件不存在")}
}fmt.Println("文件名:", info.Name())
fmt.Println("大小:", info.Size())
fmt.Println("权限:", info.Mode())
fmt.Println("修改时间:", info.ModTime())
fmt.Println("是否是目录:", info.IsDir())// 检查文件是否存在
if _, err := os.Stat("file.txt"); err == nil {fmt.Println("文件存在")
} else if os.IsNotExist(err) {fmt.Println("文件不存在")
} else {fmt.Println("其他错误:", err)
}
4.目录操作
// 创建目录
err := os.Mkdir("mydir", 0755) // 创建单级目录
err = os.MkdirAll("path/to/dir", 0755) // 创建多级目录// 读取目录
files, err := os.ReadDir(".") // 读取当前目录
for _, file := range files {fmt.Println(file.Name(), file.IsDir())
}// 遍历目录
file, err := os.Open(".")
defer file.Close()
names, err := file.Readdirnames(0) // 读取所有文件名
文件和目录管理
1.文件操作
// 重命名文件
err := os.Rename("old.txt", "new.txt")// 删除文件
err = os.Remove("file.txt")// 删除目录(必须为空)
err = os.Remove("emptydir")// 强制删除目录及其内容
err = os.RemoveAll("directory")// 更改权限
err = os.Chmod("file.txt", 0644)// 更改所有者
err = os.Chown("file.txt", 501, 100) // UID, GID
2.链接操作
// 创建硬链接
err := os.Link("original.txt", "link.txt")// 创建符号链接
err = os.Symlink("original.txt", "symlink.txt")// 读取符号链接目标
target, err := os.Readlink("symlink.txt")
环境变量和参数
1.环境变量
// 获取环境变量
path := os.Getenv("PATH")
home := os.Getenv("HOME")// 设置环境变量
os.Setenv("MY_VAR", "my_value")// 获取所有环境变量
envVars := os.Environ()
for _, env := range envVars {fmt.Println(env) // 格式: KEY=VALUE
}// 查找可执行文件路径
execPath, err := os.Executable()// 获取当前工作目录
wd, err := os.Getwd()// 更改工作目录
err = os.Chdir("/path/to/dir")
2.命令行参数
// 获取命令行参数
args := os.Args
if len(args) > 1 {fmt.Println("第一个参数:", args[1])
}// 程序名称
programName := os.Args[0]
进程管理
1.进程操作
// 获取进程ID
pid := os.Getpid()
ppid := os.Getppid() // 父进程ID// 退出程序
os.Exit(0) // 正常退出
os.Exit(1) // 错误退出// 获取主机名
hostname, err := os.Hostname()// 获取用户信息
user, err := user.Current()
fmt.Println("用户名:", user.Username)
fmt.Println("用户ID:", user.Uid)
fmt.Println("家目录:", user.HomeDir)
2.执行外部命令
// 设置命令环境
cmd := exec.Command("ls", "-l")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = "/tmp" // 工作目录
cmd.Env = append(os.Environ(), "MY_VAR=value")// 执行命令
err := cmd.Run()// 获取命令输出
output, err := cmd.Output() // 获取标准输出
combined, err := cmd.CombinedOutput() // 获取标准输出和错误
标准输入输出
1.标准流
// 标准输入输出
os.Stdin // 标准输入
os.Stdout // 标准输出
os.Stderr // 标准错误// 使用示例
fmt.Fprintln(os.Stdout, "标准输出")
fmt.Fprintln(os.Stderr, "标准错误")// 从标准输入读取
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {line := scanner.Text()fmt.Println("输入:", line)
}
临时文件和目录
1.临时文件操作
// 创建临时文件
tempFile, err := os.CreateTemp("", "prefix*.txt")
defer os.Remove(tempFile.Name()) // 使用后删除
defer tempFile.Close()// 创建临时目录
tempDir, err := os.MkdirTemp("", "mydir")
defer os.RemoveAll(tempDir)// 写入临时文件
content := []byte("临时文件内容")
if _, err := tempFile.Write(content); err != nil {log.Fatal(err)
}
使用示例
1.文件工具函数
package fileutilimport ("os""path/filepath""io"
)// 检查文件是否存在
func FileExists(filename string) bool {_, err := os.Stat(filename)return !os.IsNotExist(err)
}// 复制文件
func CopyFile(src, dst string) error {source, err := os.Open(src)if err != nil {return err}defer source.Close()destination, err := os.Create(dst)if err != nil {return err}defer destination.Close()_, err = io.Copy(destination, source)return err
}// 读取文件内容
func ReadFileToString(filename string) (string, error) {content, err := os.ReadFile(filename)if err != nil {return "", err}return string(content), nil
}// 写入文件内容
func WriteStringToFile(filename, content string) error {return os.WriteFile(filename, []byte(content), 0644)
}// 获取文件大小
func GetFileSize(filename string) (int64, error) {info, err := os.Stat(filename)if err != nil {return 0, err}return info.Size(), nil
}
2.配置管理器
package configimport ("os""path/filepath""encoding/json"
)type ConfigManager struct {configDir stringconfigFile string
}func NewConfigManager(appName string) *ConfigManager {// 使用用户配置目录configDir, err := os.UserConfigDir()if err != nil {configDir = "."}appConfigDir := filepath.Join(configDir, appName)configFile := filepath.Join(appConfigDir, "config.json")return &ConfigManager{configDir: appConfigDir,configFile: configFile,}
}func (cm *ConfigManager) EnsureConfigDir() error {return os.MkdirAll(cm.configDir, 0755)
}func (cm *ConfigManager) SaveConfig(config interface{}) error {if err := cm.EnsureConfigDir(); err != nil {return err}data, err := json.MarshalIndent(config, "", " ")if err != nil {return err}return os.WriteFile(cm.configFile, data, 0644)
}func (cm *ConfigManager) LoadConfig(config interface{}) error {data, err := os.ReadFile(cm.configFile)if err != nil {if os.IsNotExist(err) {return nil // 配置文件不存在,返回默认配置}return err}return json.Unmarshal(data, config)
}// 使用示例
type AppConfig struct {ServerPort int `json:"server_port"`Database string `json:"database"`Debug bool `json:"debug"`
}func main() {configManager := NewConfigManager("myapp")config := &AppConfig{ServerPort: 8080,Database: "localhost",Debug: true,}// 保存配置if err := configManager.SaveConfig(config); err != nil {panic(err)}// 加载配置var loadedConfig AppConfigif err := configManager.LoadConfig(&loadedConfig); err != nil {panic(err)}
}
3.日志系统
package loggerimport ("os""log""fmt""time"
)type Logger struct {file *os.Filelogger *log.Logger
}func NewLogger(filename string) (*Logger, error) {file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)if err != nil {return nil, err}logger := log.New(file, "", log.LstdFlags)return &Logger{file: file,logger: logger,}, nil
}func (l *Logger) Close() error {return l.file.Close()
}func (l *Logger) Info(format string, v ...interface{}) {message := fmt.Sprintf("[INFO] "+format, v...)l.logger.Println(message)fmt.Println(message) // 同时输出到控制台
}func (l *Logger) Error(format string, v ...interface{}) {message := fmt.Sprintf("[ERROR] "+format, v...)l.logger.Println(message)fmt.Fprintln(os.Stderr, message) // 错误输出到标准错误
}func (l *Logger) Fatal(format string, v ...interface{}) {message := fmt.Sprintf("[FATAL] "+format, v...)l.logger.Fatalln(message)
}// 使用示例
func main() {logger, err := NewLogger("app.log")if err != nil {panic(err)}defer logger.Close()logger.Info("应用程序启动")logger.Info("用户 %s 登录", "Alice")logger.Error("数据库连接失败: %v", err)
}
4.文件监控
package filemonitorimport ("os""time""path/filepath"
)type FileMonitor struct {files map[string]time.Time
}func NewFileMonitor() *FileMonitor {return &FileMonitor{files: make(map[string]time.Time),}
}func (fm *FileMonitor) WatchFile(filename string) error {info, err := os.Stat(filename)if err != nil {return err}fm.files[filename] = info.ModTime()return nil
}func (fm *FileMonitor) CheckChanges() []string {var changed []stringfor filename, lastMod := range fm.files {info, err := os.Stat(filename)if err != nil {if os.IsNotExist(err) {changed = append(changed, filename+" (deleted)")delete(fm.files, filename)}continue}if info.ModTime().After(lastMod) {changed = append(changed, filename)fm.files[filename] = info.ModTime()}}return changed
}func (fm *FileMonitor) WatchDirectory(dir string) error {return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {if err != nil {return err}if !info.IsDir() {fm.files[path] = info.ModTime()}return nil})
}// 使用示例
func main() {monitor := NewFileMonitor()// 监控单个文件monitor.WatchFile("config.json")// 监控目录monitor.WatchDirectory("./data")// 定期检查变化ticker := time.NewTicker(5 * time.Second)defer ticker.Stop()for range ticker.C {changes := monitor.CheckChanges()if len(changes) > 0 {fmt.Println("文件变化:", changes)}}
}
5.命令行工具框架
package mainimport ("os""flag""fmt"
)type CLI struct {configFile stringverbose booloutput string
}func (cli *CLI) parseFlags() {flag.StringVar(&cli.configFile, "config", "config.json", "配置文件路径")flag.BoolVar(&cli.verbose, "verbose", false, "详细输出")flag.StringVar(&cli.output, "output", "", "输出文件")flag.Usage = func() {fmt.Fprintf(os.Stderr, "用法: %s [选项] [命令]\n", os.Args[0])fmt.Fprintln(os.Stderr, "选项:")flag.PrintDefaults()fmt.Fprintln(os.Stderr, "\n命令:")fmt.Fprintln(os.Stderr, " init 初始化配置")fmt.Fprintln(os.Stderr, " run 运行程序")fmt.Fprintln(os.Stderr, " version 显示版本")}flag.Parse()
}func (cli *CLI) run() error {if cli.verbose {fmt.Fprintf(os.Stderr, "配置文件: %s\n", cli.configFile)}if len(flag.Args()) == 0 {flag.Usage()os.Exit(1)}command := flag.Arg(0)switch command {case "init":return cli.initCommand()case "run":return cli.runCommand()case "version":return cli.versionCommand()default:return fmt.Errorf("未知命令: %s", command)}
}func (cli *CLI) initCommand() error {if cli.verbose {fmt.Fprintln(os.Stderr, "初始化配置...")}// 创建默认配置文件defaultConfig := `{"server_port": 8080,"database": "localhost"
}`return os.WriteFile(cli.configFile, []byte(defaultConfig), 0644)
}func (cli *CLI) runCommand() error {// 检查配置文件是否存在if _, err := os.Stat(cli.configFile); os.IsNotExist(err) {return fmt.Errorf("配置文件不存在,请先运行 init 命令")}// 读取配置并运行configData, err := os.ReadFile(cli.configFile)if err != nil {return err}if cli.verbose {fmt.Fprintf(os.Stderr, "配置内容: %s\n", string(configData))}fmt.Println("程序运行中...")return nil
}func (cli *CLI) versionCommand() error {fmt.Println("版本 1.0.0")return nil
}func main() {cli := &CLI{}cli.parseFlags()if err := cli.run(); err != nil {fmt.Fprintf(os.Stderr, "错误: %v\n", err)os.Exit(1)}
}
