Skip to content

文件操作和 I/O

Go 语言提供了丰富的 I/O 操作功能,包括文件读写、JSON/XML 处理、网络编程等。

文件操作

读取文件

读取整个文件

go
import (
    "io/ioutil"
    "os"
)

// 方式 1: ioutil.ReadFile (Go 1.16+ 推荐使用 os.ReadFile)
data, err := os.ReadFile("file.txt")
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(data))

// 方式 2: 使用 os.Open
file, err := os.Open("file.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

data, err := io.ReadAll(file)
if err != nil {
    log.Fatal(err)
}

逐行读取

go
import (
    "bufio"
    "os"
)

file, err := os.Open("file.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

scanner := bufio.NewScanner(file)
for scanner.Scan() {
    line := scanner.Text()
    fmt.Println(line)
}

if err := scanner.Err(); err != nil {
    log.Fatal(err)
}

按块读取

go
file, err := os.Open("file.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

buffer := make([]byte, 1024)
for {
    n, err := file.Read(buffer)
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    fmt.Print(string(buffer[:n]))
}

写入文件

写入整个文件

go
import "os"

data := []byte("Hello, World!")
err := os.WriteFile("output.txt", data, 0644)
if err != nil {
    log.Fatal(err)
}

追加写入

go
file, err := os.OpenFile("file.txt", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
    log.Fatal(err)
}
defer file.Close()

_, err = file.WriteString("新的一行\n")
if err != nil {
    log.Fatal(err)
}

使用 bufio 写入

go
file, err := os.Create("output.txt")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

writer := bufio.NewWriter(file)
writer.WriteString("第一行\n")
writer.WriteString("第二行\n")
writer.Flush()  // 确保数据写入

文件信息

go
import (
    "os"
    "fmt"
)

info, err := os.Stat("file.txt")
if err != nil {
    log.Fatal(err)
}

fmt.Println("文件名:", info.Name())
fmt.Println("大小:", info.Size())
fmt.Println("修改时间:", info.ModTime())
fmt.Println("是否目录:", info.IsDir())
fmt.Println("权限:", info.Mode())

目录操作

go
import "os"

// 创建目录
err := os.Mkdir("mydir", 0755)
if err != nil {
    log.Fatal(err)
}

// 创建多级目录
err = os.MkdirAll("path/to/dir", 0755)

// 读取目录
entries, err := os.ReadDir(".")
if err != nil {
    log.Fatal(err)
}

for _, entry := range entries {
    fmt.Println(entry.Name())
}

JSON 处理

编码(Marshal)

go
import "encoding/json"

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
    City string `json:"city,omitempty"`  // omitempty: 空值时不输出
}

person := Person{Name: "Alice", Age: 30}
data, err := json.Marshal(person)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(data))  // {"name":"Alice","age":30}

// 格式化输出
data, _ = json.MarshalIndent(person, "", "  ")

解码(Unmarshal)

go
jsonData := `{"name":"Alice","age":30}`

var person Person
err := json.Unmarshal([]byte(jsonData), &person)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("%+v\n", person)

JSON 流处理

go
import (
    "encoding/json"
    "os"
)

// 编码到文件
file, _ := os.Create("data.json")
encoder := json.NewEncoder(file)
encoder.Encode(person)

// 从文件解码
file, _ = os.Open("data.json")
decoder := json.NewDecoder(file)
var person2 Person
decoder.Decode(&person2)

XML 处理

XML 编码

go
import "encoding/xml"

type Person struct {
    XMLName xml.Name `xml:"person"`
    Name    string   `xml:"name"`
    Age     int      `xml:"age"`
}

person := Person{Name: "Alice", Age: 30}
data, err := xml.MarshalIndent(person, "", "  ")
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(data))

XML 解码

go
xmlData := `<person><name>Alice</name><age>30</age></person>`

var person Person
err := xml.Unmarshal([]byte(xmlData), &person)
if err != nil {
    log.Fatal(err)
}

网络编程

HTTP 客户端

go
import (
    "net/http"
    "io"
    "os"
)

// GET 请求
resp, err := http.Get("https://api.example.com/data")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(body))

// POST 请求
data := strings.NewReader(`{"key":"value"}`)
resp, err := http.Post("https://api.example.com/data", "application/json", data)

HTTP 服务器

go
import "net/http"

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

自定义 HTTP 客户端

go
client := &http.Client{
    Timeout: 10 * time.Second,
}

req, _ := http.NewRequest("GET", "https://api.example.com", nil)
req.Header.Set("Authorization", "Bearer token")

resp, err := client.Do(req)

完整示例

go
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
    Email string `json:"email"`
}

func main() {
    // 写入 JSON 文件
    user := User{ID: 1, Name: "Alice", Email: "alice@example.com"}
    data, _ := json.MarshalIndent(user, "", "  ")
    os.WriteFile("user.json", data, 0644)
    
    // 读取 JSON 文件
    file, _ := os.Open("user.json")
    defer file.Close()
    
    var user2 User
    json.NewDecoder(file).Decode(&user2)
    fmt.Printf("用户: %+v\n", user2)
    
    // HTTP 请求
    resp, _ := http.Get("https://api.github.com/users/octocat")
    defer resp.Body.Close()
    
    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
}

最佳实践

  1. 总是检查错误:I/O 操作容易出错
  2. 使用 defer 关闭资源:确保文件、连接等资源被正确关闭
  3. 使用缓冲 I/O:提高性能
  4. 处理大文件时使用流式处理:避免内存溢出
  5. 使用 context 控制超时:网络操作应该设置超时

下一步

接下来我们将学习:

基于 VitePress 构建