实战案例
通过实际案例,读者可以将所学的文件与 IO 知识应用到实际项目中。本章将介绍几个常见的实战案例,包括日志文件管理、配置文件处理、数据导入导出以及大文件处理等。
9.1 日志文件管理
日志文件是记录系统运行状态和错误信息的重要文件。日志管理包括日志的创建、写入、滚动等操作。
Go 示例代码(日志文件写入和滚动):
package main
import (
"fmt"
"os"
"time"
)
const (
logFilePath = "application.log"
maxFileSize = 1 * 1024 * 1024 // 1 MB
backupSuffix = ".bak"
)
func checkFileSize(filePath string) bool {
fileInfo, err := os.Stat(filePath)
if err != nil {
return false
}
return fileInfo.Size() >= maxFileSize
}
func rotateLogFile(filePath string) error {
backupPath := filePath + backupSuffix
err := os.Rename(filePath, backupPath)
if err != nil {
return fmt.Errorf("error rotating log file: %v", err)
}
return nil
}
func logMessage(filePath, message string) error {
if checkFileSize(filePath) {
if err := rotateLogFile(filePath); err != nil {
return err
}
}
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("error opening log file: %v", err)
}
defer file.Close()
timestamp := time.Now().Format("2006-01-02 15:04:05")
_, err = fmt.Fprintf(file, "[%s] %s\n", timestamp, message)
if err != nil {
return fmt.Errorf("error writing to log file: %v", err)
}
return nil
}
func main() {
messages := []string{
"Application started",
"Processing request",
"Request processed successfully",
"Application stopped",
}
for _, msg := range messages {
if err := logMessage(logFilePath, msg); err != nil {
fmt.Println("Error logging message:", err)
}
}
}
9.2 配置文件处理
配置文件用于存储应用程序的配置参数,常见的格式有 JSON、YAML 和 TOML。本例介绍如何读取和写入 JSON 格式的配置文件。
Go 示例代码(读取和写入 JSON 配置文件):
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type Config struct {
ServerPort int `json:"server_port"`
Database string `json:"database"`
Username string `json:"username"`
Password string `json:"password"`
}
func loadConfig(filePath string) (*Config, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("error opening config file: %v", err)
}
defer file.Close()
var config Config
decoder := json.NewDecoder(file)
if err := decoder.Decode(&config); err != nil {
return nil, fmt.Errorf("error decoding config file: %v", err)
}
return &config, nil
}
func saveConfig(filePath string, config *Config) error {
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
return fmt.Errorf("error marshalling config: %v", err)
}
err = ioutil.WriteFile(filePath, data, 0644)
if err != nil {
return fmt.Errorf("error writing config file: %v", err)
}
return nil
}
func main() {
configFilePath := "config.json"
// Sample configuration
config := &Config{
ServerPort: 8080,
Database: "mydatabase",
Username: "admin",
Password: "password",
}
// Save configuration
if err := saveConfig(configFilePath, config); err != nil {
fmt.Println("Error saving config:", err)
}
// Load configuration
loadedConfig, err := loadConfig(configFilePath)
if err != nil {
fmt.Println("Error loading config:", err)
} else {
fmt.Printf("Loaded config: %+v\n", loadedConfig)
}
}
9.3 数据导入导出
数据导入导出是将数据从一个系统迁移到另一个系统的常见操作。本例介绍如何导入和导出 CSV 格式的数据。
Go 示例代码(导入和导出 CSV 文件):
package main
import (
"encoding/csv"
"fmt"
"os"
)
type Record struct {
Name string
Age int
Email string
}
func exportCSV(filePath string, records []Record) error {
file, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("error creating file: %v", err)
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
for _, record := range records {
row := []string{record.Name, fmt.Sprintf("%d", record.Age), record.Email}
if err := writer.Write(row); err != nil {
return fmt.Errorf("error writing to CSV file: %v", err)
}
}
return nil
}
func importCSV(filePath string) ([]Record, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("error opening file: %v", err)
}
defer file.Close()
reader := csv.NewReader(file)
rows, err := reader.ReadAll()
if err != nil {
return nil, fmt.Errorf("error reading CSV file: %v", err)
}
var records []Record
for _, row := range rows {
age, _ := strconv.Atoi(row[1])
record := Record{Name: row[0], Age: age, Email: row[2]}
records = append(records, record)
}
return records, nil
}
func main() {
filePath := "data.csv"
records := []Record{
{"Alice", 30, "alice@example.com"},
{"Bob", 25, "bob@example.com"},
}
// Export records to CSV
if err := exportCSV(filePath, records); err != nil {
fmt.Println("Error exporting CSV:", err)
}
// Import records from CSV
importedRecords, err := importCSV(filePath)
if err != nil {
fmt.Println("Error importing CSV:", err)
} else {
fmt.Printf("Imported records: %+v\n", importedRecords)
}
}
9.4 大文件处理
大文件处理需要特别注意内存和性能问题,常见的方法包括分块读取和多线程处理。
Go 示例代码(分块读取大文件):
package main
import (
"bufio"
"fmt"
"os"
)
const chunkSize = 1024 * 1024 // 1 MB
func processChunk(chunk []byte) {
// 处理分块数据
fmt.Printf("Processing chunk of size %d\n", len(chunk))
}
func readLargeFile(filePath string) {
file, err := os.Open(filePath)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
reader := bufio.NewReader(file)
buffer := make([]byte, chunkSize)
for {
bytesRead, err := reader.Read(buffer)
if err != nil && err.Error() != "EOF" {
fmt.Println("Error reading file:", err)
break
}
if bytesRead == 0 {
break
}
processChunk(buffer[:bytesRead])
}
}
func main() {
filePath := "largefile.dat"
readLargeFile(filePath)
}
通过学习本章内容,读者将能够掌握日志文件管理、配置文件处理、数据导入导出以及大文件处理等实战案例,从而在实际项目中灵活应用这些技术。