文件操作和 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))
}最佳实践
- 总是检查错误:I/O 操作容易出错
- 使用 defer 关闭资源:确保文件、连接等资源被正确关闭
- 使用缓冲 I/O:提高性能
- 处理大文件时使用流式处理:避免内存溢出
- 使用 context 控制超时:网络操作应该设置超时
下一步
接下来我们将学习:
