package main
import (
"bufio"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// 文件读写
func readFile(filename string) (string, error) {
data, err := os.ReadFile(filename)
if err != nil {
return "", err
}
return string(data), nil
}
// 按行读取文件
func readFileByLines(filename string) ([]string, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, err
}
return lines, nil
}
// 写入文件
func writeFile(filename, content string) error {
return os.WriteFile(filename, []byte(content), 0644)
}
// 追加内容到文件
func appendToFile(filename, content string) error {
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer file.Close()
_, err = file.WriteString(content)
return err
}
// 目录操作
func listFiles(dir string) ([]string, error) {
entries, err := os.ReadDir(dir)
if err != nil {
return nil, err
}
var files []string
for _, entry := range entries {
files = append(files, entry.Name())
}
return files, nil
}
// 递归列出所有文件
func listAllFiles(dir string) ([]string, error) {
var files []string
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
files = append(files, path)
}
return nil
})
return files, err
}
// 复制文件
func copyFile(src, dst string) error {
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(dst)
if err != nil {
return err
}
defer destFile.Close()
_, err = io.Copy(destFile, sourceFile)
return err
}
// 获取文件信息
func getFileInfo(filename string) (os.FileInfo, error) {
return os.Stat(filename)
}
// 创建目录
func createDir(dirName string) error {
return os.MkdirAll(dirName, 0755)
}
func main() {
// 创建测试目录和文件
testDir := "./test_files"
createDir(testDir)
// 写入测试文件
testFile := filepath.Join(testDir, "test.txt")
content := "这是测试文件\n包含多行内容\n用于演示文件操作"
err := writeFile(testFile, content)
if err != nil {
fmt.Printf("写入文件错误: %v\n", err)
return
}
// 读取文件
data, err := readFile(testFile)
if err != nil {
fmt.Printf("读取文件错误: %v\n", err)
return
}
fmt.Printf("文件内容:\n%s\n", data)
// 按行读取
lines, err := readFileByLines(testFile)
if err != nil {
fmt.Printf("按行读取错误: %v\n", err)
return
}
fmt.Printf("文件行数: %d\n", len(lines))
// 追加内容
err = appendToFile(testFile, "\n追加的新行")
if err != nil {
fmt.Printf("追加内容错误: %v\n", err)
return
}
// 列出目录中的文件
files, err := listFiles(testDir)
if err != nil {
fmt.Printf("列出文件错误: %v\n", err)
return
}
fmt.Printf("目录中的文件: %v\n", files)
// 获取文件信息
info, err := getFileInfo(testFile)
if err != nil {
fmt.Printf("获取文件信息错误: %v\n", err)
return
}
fmt.Printf("文件大小: %d 字节\n", info.Size())
fmt.Printf("文件修改时间: %v\n", info.ModTime())
// 复制文件
copyFile := filepath.Join(testDir, "test_copy.txt")
err = copyFile(testFile, copyFile)
if err != nil {
fmt.Printf("复制文件错误: %v\n", err)
return
}
fmt.Printf("文件已复制到: %s\n", copyFile)
// 递归列出所有文件
allFiles, err := listAllFiles(".")
if err != nil {
fmt.Printf("递归列出文件错误: %v\n", err)
return
}
fmt.Printf("当前目录及子目录中的所有文件数量: %d\n", len(allFiles))
// 清理测试文件
os.RemoveAll(testDir)
fmt.Println("测试完成,已清理测试文件")
}
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"strings"
"time"
)
// HTTP客户端
func httpGet(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
// 带超时的HTTP客户端
func httpGetWithTimeout(url string, timeout time.Duration) (string, error) {
client := http.Client{
Timeout: timeout,
}
resp, err := client.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
// POST请求
func httpPost(url string, data interface{}) (string, error) {
jsonData, err := json.Marshal(data)
if err != nil {
return "", err
}
resp, err := http.Post(url, "application/json", strings.NewReader(string(jsonData)))
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
// HTTP服务器
func startHTTPServer() {
// 静态文件服务
fs := http.FileServer(http.Dir("./static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
// API路由
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World! 当前时间: %s", time.Now().Format("2006-01-02 15:04:05"))
})
http.HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if name == "" {
name = "Guest"
}
response := map[string]string{
"message": fmt.Sprintf("Hello, %s!", name),
"time": time.Now().Format(time.RFC3339),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
})
http.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
var data map[string]interface{}
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}
// 处理数据
data["processed"] = true
data["timestamp"] = time.Now().Unix()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
})
fmt.Println("HTTP服务器启动,监听端口: 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
// TCP连接处理
func handleConnection(conn net.Conn) {
defer conn.Close()
// 设置连接超时
conn.SetDeadline(time.Now().Add(30 * time.Second))
// 发送欢迎消息
conn.Write([]byte("欢迎连接TCP服务器!\n"))
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
text := scanner.Text()
if text == "quit" {
break
}
// 处理命令
response := processCommand(text)
conn.Write([]byte(response + "\n"))
}
if err := scanner.Err(); err != nil {
fmt.Printf("连接错误: %v\n", err)
}
fmt.Printf("客户端 %s 断开连接\n", conn.RemoteAddr())
}
// 处理TCP命令
func processCommand(command string) string {
parts := strings.Fields(command)
if len(parts) == 0 {
return "无效命令"
}
switch parts[0] {
case "time":
return fmt.Sprintf("当前时间: %s", time.Now().Format("2006-01-02 15:04:05"))
case "echo":
if len(parts) > 1 {
return strings.Join(parts[1:], " ")
}
return "echo需要参数"
case "reverse":
if len(parts) > 1 {
text := strings.Join(parts[1:], " ")
runes := []rune(text)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
return "reverse需要参数"
default:
return fmt.Sprintf("未知命令: %s", parts[0])
}
}
// TCP服务器
func startTCPServer() {
ln, err := net.Listen("tcp", ":8081")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
fmt.Println("TCP服务器启动,监听端口: 8081")
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
fmt.Printf("新客户端连接: %s\n", conn.RemoteAddr())
go handleConnection(conn)
}
}
// TCP客户端
func startTCPClient(serverAddr string) {
conn, err := net.Dial("tcp", serverAddr)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
fmt.Printf("已连接到TCP服务器: %s\n", serverAddr)
// 读取欢迎消息
scanner := bufio.NewScanner(conn)
if scanner.Scan() {
fmt.Println("服务器:", scanner.Text())
}
// 发送命令
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print("输入命令 (quit退出): ")
text, _ := reader.ReadString('\n')
text = strings.TrimSpace(text)
if text == "quit" {
break
}
// 发送命令
fmt.Fprintln(conn, text)
// 读取响应
if scanner.Scan() {
fmt.Println("服务器:", scanner.Text())
}
}
}
func main() {
if len(os.Args) < 2 {
fmt.Println("使用方法:")
fmt.Println(" HTTP服务器: go run network.go http")
fmt.Println(" TCP服务器: go run network.go tcp-server")
fmt.Println(" TCP客户端: go run network.go tcp-client <server:port>")
return
}
mode := os.Args[1]
switch mode {
case "http":
startHTTPServer()
case "tcp-server":
startTCPServer()
case "tcp-client":
if len(os.Args) < 3 {
fmt.Println("请指定服务器地址")
return
}
serverAddr := os.Args[2]
startTCPClient(serverAddr)
default:
fmt.Println("无效模式")
}
}
package main
import (
"database/sql"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
)
// 用户模型
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// 数据库配置
type DBConfig struct {
Driver string
Host string
Port int
Username string
Password string
Database string
}
// MySQL连接
func connectMySQL(config DBConfig) (*sql.DB, error) {
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=true",
config.Username, config.Password, config.Host, config.Port, config.Database)
db, err := sql.Open("mysql", dsn)
if err != nil {
return nil, err
}
// 测试连接
if err := db.Ping(); err != nil {
return nil, err
}
// 设置连接池
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)
return db, nil
}
// PostgreSQL连接
func connectPostgreSQL(config DBConfig) (*sql.DB, error) {
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
config.Host, config.Port, config.Username, config.Password, config.Database)
db, err := sql.Open("postgres", dsn)
if err != nil {
return nil, err
}
// 测试连接
if err := db.Ping(); err != nil {
return nil, err
}
// 设置连接池
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)
return db, nil
}
// SQLite连接
func connectSQLite(dbPath string) (*sql.DB, error) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return nil, err
}
// 测试连接
if err := db.Ping(); err != nil {
return nil, err
}
return db, nil
}
// 创建用户表
func createUserTable(db *sql.DB, driver string) error {
var query string
switch driver {
case "mysql":
query = `
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)`
case "postgres":
query = `
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)`
case "sqlite3":
query = `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
age INTEGER,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`
default:
return fmt.Errorf("不支持的数据库驱动: %s", driver)
}
_, err := db.Exec(query)
return err
}
// 创建用户
func createUser(db *sql.DB, user User) (int, error) {
query := "INSERT INTO users (name, email, age) VALUES (?, ?, ?)"
result, err := db.Exec(query, user.Name, user.Email, user.Age)
if err != nil {
return 0, err
}
id, err := result.LastInsertId()
if err != nil {
return 0, err
}
return int(id), nil
}
// 根据ID获取用户
func getUserByID(db *sql.DB, id int) (User, error) {
var user User
query := "SELECT id, name, email, age, created_at, updated_at FROM users WHERE id = ?"
err := db.QueryRow(query, id).Scan(
&user.ID, &user.Name, &user.Email, &user.Age, &user.CreatedAt, &user.UpdatedAt)
return user, err
}
// 获取所有用户
func getAllUsers(db *sql.DB) ([]User, error) {
query := "SELECT id, name, email, age, created_at, updated_at FROM users ORDER BY id"
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var users []User
for rows.Next() {
var user User
err := rows.Scan(
&user.ID, &user.Name, &user.Email, &user.Age, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
return nil, err
}
users = append(users, user)
}
if err = rows.Err(); err != nil {
return nil, err
}
return users, nil
}
// 更新用户
func updateUser(db *sql.DB, user User) error {
query := "UPDATE users SET name = ?, email = ?, age = ?, updated_at = ? WHERE id = ?"
_, err := db.Exec(query, user.Name, user.Email, user.Age, time.Now(), user.ID)
return err
}
// 删除用户
func deleteUser(db *sql.DB, id int) error {
query := "DELETE FROM users WHERE id = ?"
_, err := db.Exec(query, id)
return err
}
// 事务示例
func transferUsers(db *sql.DB, fromID, toID int) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer func() {
if p := recover(); p != nil {
tx.Rollback()
panic(p) // 重新抛出panic
} else if err != nil {
tx.Rollback()
} else {
err = tx.Commit()
}
}()
// 获取源用户
fromUser, err := getUserByID(db, fromID)
if err != nil {
return err
}
// 获取目标用户
toUser, err := getUserByID(db, toID)
if err != nil {
return err
}
// 交换年龄
fromUser.Age, toUser.Age = toUser.Age, fromUser.Age
// 更新用户
if err := updateUser(db, fromUser); err != nil {
return err
}
if err := updateUser(db, toUser); err != nil {
return err
}
return nil
}
func main() {
// 使用SQLite作为示例(无需额外安装)
db, err := connectSQLite("./test.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// 创建表
if err := createUserTable(db, "sqlite3"); err != nil {
log.Fatal(err)
}
// 创建用户
users := []User{
{Name: "张三", Email: "[email protected]", Age: 25},
{Name: "李四", Email: "[email protected]", Age: 30},
{Name: "王五", Email: "[email protected]", Age: 28},
}
for _, user := range users {
id, err := createUser(db, user)
if err != nil {
log.Printf("创建用户失败: %v", err)
continue
}
fmt.Printf("创建用户成功,ID: %d\n", id)
}
// 获取所有用户
allUsers, err := getAllUsers(db)
if err != nil {
log.Fatal(err)
}
fmt.Println("\n所有用户:")
for _, user := range allUsers {
fmt.Printf("ID: %d, 姓名: %s, 邮箱: %s, 年龄: %d\n",
user.ID, user.Name, user.Email, user.Age)
}
// 更新用户
if len(allUsers) > 0 {
user := allUsers[0]
user.Age = 35
if err := updateUser(db, user); err != nil {
log.Printf("更新用户失败: %v", err)
} else {
fmt.Printf("\n用户 %s 年龄已更新为 %d\n", user.Name, user.Age)
}
}
// 事务示例
if len(allUsers) >= 2 {
fromID := allUsers[0].ID
toID := allUsers[1].ID
fmt.Printf("\n交换用户 %d 和 %d 的年龄\n", fromID, toID)
if err := transferUsers(db, fromID, toID); err != nil {
log.Printf("事务失败: %v", err)
} else {
fmt.Println("事务成功")
}
}
// 再次获取所有用户
allUsers, err = getAllUsers(db)
if err != nil {
log.Fatal(err)
}
fmt.Println("\n更新后的用户:")
for _, user := range allUsers {
fmt.Printf("ID: %d, 姓名: %s, 邮箱: %s, 年龄: %d\n",
user.ID, user.Name, user.Email, user.Age)
}
// 删除用户
if len(allUsers) > 0 {
user := allUsers[0]
if err := deleteUser(db, user.ID); err != nil {
log.Printf("删除用户失败: %v", err)
} else {
fmt.Printf("\n用户 %s 已删除\n", user.Name)
}
}
}
package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"io"
"os"
"reflect"
"time"
)
// JSON序列化与反序列化
type Config struct {
Host string `json:"host"`
Port int `json:"port"`
Debug bool `json:"debug"`
Database struct {
Name string `json:"name"`
User string `json:"user"`
Password string `json:"password"`
} `json:"database"`
}
// 用户结构体
type User struct {
ID int `json:"id" xml:"id"`
Name string `json:"name" xml:"name"`
Email string `json:"email" xml:"email"`
Age int `json:"age" xml:"age"`
CreatedAt time.Time `json:"created_at" xml:"created_at"`
}
// 用户列表结构体(用于XML)
type UserList struct {
XMLName xml.Name `xml:"users"`
Users []User `xml:"user"`
}
// 保存配置为JSON
func saveConfig(config Config, filename string) error {
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
}
return os.WriteFile(filename, data, 0644)
}
// 从JSON加载配置
func loadConfig(filename string) (Config, error) {
data, err := os.ReadFile(filename)
if err != nil {
return Config{}, err
}
var config Config
err = json.Unmarshal(data, &config)
return config, err
}
// 保存用户为JSON
func saveUsersToJSON(users []User, filename string) error {
data, err := json.MarshalIndent(users, "", " ")
if err != nil {
return err
}
return os.WriteFile(filename, data, 0644)
}
// 从JSON加载用户
func loadUsersFromJSON(filename string) ([]User, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
var users []User
err = json.Unmarshal(data, &users)
return users, err
}
// 保存用户为XML
func saveUsersToXML(users []User, filename string) error {
userList := UserList{Users: users}
data, err := xml.MarshalIndent(userList, "", " ")
if err != nil {
return err
}
return os.WriteFile(filename, data, 0644)
}
// 从XML加载用户
func loadUsersFromXML(filename string) ([]User, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
var userList UserList
err = xml.Unmarshal(data, &userList)
return userList.Users, err
}
// 流式JSON处理
func streamJSONFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
decoder := json.NewDecoder(file)
// 读取开头的 [
token, err := decoder.Token()
if err != nil {
return err
}
if token != json.Delim('[') {
return fmt.Errorf("期望JSON数组开始,得到: %v", token)
}
// 读取数组中的每个对象
for decoder.More() {
var user User
err := decoder.Decode(&user)
if err != nil {
return err
}
fmt.Printf("用户: %+v\n", user)
}
// 读取结尾的 ]
token, err = decoder.Token()
if err != nil {
return err
}
if token != json.Delim(']') {
return fmt.Errorf("期望JSON数组结束,得到: %v", token)
}
return nil
}
// 流式XML处理
func streamXMLFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
decoder := xml.NewDecoder(file)
for {
token, err := decoder.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
switch se := token.(type) {
case xml.StartElement:
if se.Name.Local == "user" {
var user User
err := decoder.DecodeElement(&user, &se)
if err != nil {
return err
}
fmt.Printf("用户: %+v\n", user)
}
}
}
return nil
}
// 反射获取结构体标签
func printStructTags(obj interface{}) {
v := reflect.ValueOf(obj)
t := reflect.TypeOf(obj)
if t.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
if t.Kind() != reflect.Struct {
fmt.Println("不是结构体")
return
}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
jsonTag := field.Tag.Get("json")
xmlTag := field.Tag.Get("xml")
fmt.Printf("字段: %s, 类型: %v, JSON标签: %s, XML标签: %s\n",
field.Name, field.Type, jsonTag, xmlTag)
}
}
func main() {
// 创建示例配置
config := Config{
Host: "localhost",
Port: 8080,
Debug: true,
}
config.Database.Name = "mydb"
config.Database.User = "admin"
config.Database.Password = "password"
// 保存配置
err := saveConfig(config, "config.json")
if err != nil {
fmt.Printf("保存配置失败: %v\n", err)
return
}
// 加载配置
loadedConfig, err := loadConfig("config.json")
if err != nil {
fmt.Printf("加载配置失败: %v\n", err)
return
}
fmt.Printf("加载的配置: %+v\n", loadedConfig)
// 创建示例用户
users := []User{
{ID: 1, Name: "张三", Email: "[email protected]", Age: 25, CreatedAt: time.Now()},
{ID: 2, Name: "李四", Email: "[email protected]", Age: 30, CreatedAt: time.Now()},
{ID: 3, Name: "王五", Email: "[email protected]", Age: 28, CreatedAt: time.Now()},
}
// 保存用户为JSON
err = saveUsersToJSON(users, "users.json")
if err != nil {
fmt.Printf("保存用户JSON失败: %v\n", err)
return
}
// 保存用户为XML
err = saveUsersToXML(users, "users.xml")
if err != nil {
fmt.Printf("保存用户XML失败: %v\n", err)
return
}
// 从JSON加载用户
loadedUsers, err := loadUsersFromJSON("users.json")
if err != nil {
fmt.Printf("加载用户JSON失败: %v\n", err)
return
}
fmt.Println("\n从JSON加载的用户:")
for _, user := range loadedUsers {
fmt.Printf("ID: %d, 姓名: %s, 邮箱: %s, 年龄: %d\n",
user.ID, user.Name, user.Email, user.Age)
}
// 从XML加载用户
loadedUsersFromXML, err := loadUsersFromXML("users.xml")
if err != nil {
fmt.Printf("加载用户XML失败: %v\n", err)
return
}
fmt.Println("\n从XML加载的用户:")
for _, user := range loadedUsersFromXML {
fmt.Printf("ID: %d, 姓名: %s, 邮箱: %s, 年龄: %d\n",
user.ID, user.Name, user.Email, user.Age)
}
// 流式处理JSON
fmt.Println("\n流式处理JSON:")
err = streamJSONFile("users.json")
if err != nil {
fmt.Printf("流式处理JSON失败: %v\n", err)
}
// 流式处理XML
fmt.Println("\n流式处理XML:")
err = streamXMLFile("users.xml")
if err != nil {
fmt.Printf("流式处理XML失败: %v\n", err)
}
// 打印结构体标签
fmt.Println("\nUser结构体标签:")
printStructTags(User{})
// 清理文件
os.Remove("config.json")
os.Remove("users.json")
os.Remove("users.xml")
}
package main
import (
"fmt"
"math"
"os"
"runtime"
"runtime/pprof"
"sort"
"testing"
"time"
)
// 被测试的函数
func add(a, b int) int {
return a + b
}
func multiply(a, b int) int {
return a * b
}
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("division by zero")
}
return a / b, nil
}
// 计算斐波那契数列
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}
// 优化的斐波那契数列
func fibonacciOptimized(n int) int {
if n <= 1 {
return n
}
a, b := 0, 1
for i := 2; i <= n; i++ {
a, b = b, a+b
}
return b
}
// 排序函数
func bubbleSort(arr []int) []int {
n := len(arr)
result := make([]int, n)
copy(result, arr)
for i := 0; i < n-1; i++ {
for j := 0; j < n-i-1; j++ {
if result[j] > result[j+1] {
result[j], result[j+1] = result[j+1], result[j]
}
}
}
return result
}
// 单元测试
func TestAdd(t *testing.T) {
tests := []struct {
a, b int
expected int
}{
{1, 2, 3},
{-1, 1, 0},
{0, 0, 0},
{100, 200, 300},
}
for _, test := range tests {
result := add(test.a, test.b)
if result != test.expected {
t.Errorf("add(%d, %d) = %d; expected %d", test.a, test.b, result, test.expected)
}
}
}
func TestMultiply(t *testing.T) {
tests := []struct {
a, b int
expected int
}{
{2, 3, 6},
{-2, 3, -6},
{0, 5, 0},
{10, 10, 100},
}
for _, test := range tests {
result := multiply(test.a, test.b)
if result != test.expected {
t.Errorf("multiply(%d, %d) = %d; expected %d", test.a, test.b, result, test.expected)
}
}
}
func TestDivide(t *testing.T) {
// 测试正常情况
result, err := divide(10, 2)
if err != nil {
t.Errorf("divide(10, 2) returned error: %v", err)
}
if math.Abs(result-5.0) > 1e-9 {
t.Errorf("divide(10, 2) = %f; expected 5.0", result)
}
// 测试除零错误
_, err = divide(10, 0)
if err == nil {
t.Error("divide(10, 0) should return an error")
}
}
func TestFibonacci(t *testing.T) {
tests := []struct {
n, expected int
}{
{0, 0},
{1, 1},
{2, 1},
{3, 2},
{4, 3},
{5, 5},
{10, 55},
}
for _, test := range tests {
result := fibonacci(test.n)
if result != test.expected {
t.Errorf("fibonacci(%d) = %d; expected %d", test.n, result, test.expected)
}
}
}
func TestFibonacciOptimized(t *testing.T) {
tests := []struct {
n, expected int
}{
{0, 0},
{1, 1},
{2, 1},
{3, 2},
{4, 3},
{5, 5},
{10, 55},
{20, 6765},
}
for _, test := range tests {
result := fibonacciOptimized(test.n)
if result != test.expected {
t.Errorf("fibonacciOptimized(%d) = %d; expected %d", test.n, result, test.expected)
}
}
}
func TestBubbleSort(t *testing.T) {
tests := []struct {
input []int
expected []int
}{
{[]int{5, 3, 8, 4, 2}, []int{2, 3, 4, 5, 8}},
{[]int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4, 5}},
{[]int{5, 4, 3, 2, 1}, []int{1, 2, 3, 4, 5}},
{[]int{}, []int{}},
{[]int{42}, []int{42}},
}
for _, test := range tests {
result := bubbleSort(test.input)
if !equal(result, test.expected) {
t.Errorf("bubbleSort(%v) = %v; expected %v", test.input, result, test.expected)
}
}
}
// 辅助函数:比较两个整数切片是否相等
func equal(a, b []int) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
// 基准测试
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
add(1, 2)
}
}
func BenchmarkMultiply(b *testing.B) {
for i := 0; i < b.N; i++ {
multiply(123, 456)
}
}
func BenchmarkFibonacci(b *testing.B) {
for i := 0; i < b.N; i++ {
fibonacci(10)
}
}
func BenchmarkFibonacciOptimized(b *testing.B) {
for i := 0; i < b.N; i++ {
fibonacciOptimized(10)
}
}
func BenchmarkBubbleSort(b *testing.B) {
// 创建测试数据
data := make([]int, 100)
for i := range data {
data[i] = 100 - i // 逆序数组
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
bubbleSort(data)
}
}
func BenchmarkSort(b *testing.B) {
// 创建测试数据
data := make([]int, 100)
for i := range data {
data[i] = 100 - i // 逆序数组
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// 复制数据以避免修改原始数据
testData := make([]int, len(data))
copy(testData, data)
sort.Ints(testData)
}
}
// 性能分析
func profileCPU(filename string, fn func()) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
if err := pprof.StartCPUProfile(f); err != nil {
return err
}
defer pprof.StopCPUProfile()
fn()
return nil
}
// 内存分析
func profileMemory(filename string, fn func()) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
runtime.GC() // 获取最新的GC数据
if err := pprof.WriteHeapProfile(f); err != nil {
return err
}
fn()
return nil
}
// 示例函数
func ExampleAdd() {
result := add(2, 3)
fmt.Println(result)
// Output: 5
}
func ExampleFibonacci() {
fmt.Println(fibonacci(5))
// Output: 5
}
// 测试主函数
func main() {
// 性能分析示例
fmt.Println("开始性能分析...")
// CPU性能分析
err := profileCPU("cpu.prof", func() {
// 执行一些计算密集型任务
for i := 0; i < 1000; i++ {
fibonacciOptimized(20)
}
})
if err != nil {
fmt.Printf("CPU性能分析失败: %v\n", err)
} else {
fmt.Println("CPU性能分析完成,结果保存到 cpu.prof")
}
// 内存性能分析
err = profileMemory("mem.prof", func() {
// 创建一些数据
data := make([][]int, 100)
for i := range data {
data[i] = make([]int, 1000)
for j := range data[i] {
data[i][j] = i * j
}
}
})
if err != nil {
fmt.Printf("内存性能分析失败: %v\n", err)
} else {
fmt.Println("内存性能分析完成,结果保存到 mem.prof")
}
// 运行基准测试
fmt.Println("\n运行基准测试...")
result := testing.Benchmark(BenchmarkFibonacci)
fmt.Printf("fibonacci(10) 基准测试结果: %s\n", result)
result = testing.Benchmark(BenchmarkFibonacciOptimized)
fmt.Printf("fibonacciOptimized(10) 基准测试结果: %s\n", result)
// 比较两种斐波那契实现的性能
n := 30
start := time.Now()
result1 := fibonacci(n)
duration1 := time.Since(start)
start = time.Now()
result2 := fibonacciOptimized(n)
duration2 := time.Since(start)
fmt.Printf("\n斐波那契数列第%d项:\n", n)
fmt.Printf("递归实现: %d, 耗时: %v\n", result1, duration1)
fmt.Printf("优化实现: %d, 耗时: %v\n", result2, duration2)
fmt.Printf("性能提升: %.2fx\n", float64(duration1)/float64(duration2))
// 清理分析文件
os.Remove("cpu.prof")
os.Remove("mem.prof")
}
package main
import (
"archive/zip"
"bufio"
"crypto/md5"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
"time"
)
// 文件信息
type FileInfo struct {
Path string
Size int64
ModTime time.Time
Hash string
IsDir bool
}
// 备份信息
type BackupInfo struct {
Name string
Timestamp time.Time
Files []FileInfo
Size int64
}
// 备份管理器
type BackupManager struct {
sourceDir string
backupDir string
indexFile string
}
// 创建新的备份管理器
func NewBackupManager(sourceDir, backupDir string) *BackupManager {
return &BackupManager{
sourceDir: sourceDir,
backupDir: backupDir,
indexFile: filepath.Join(backupDir, "index.json"),
}
}
// 获取文件哈希
func getFileHash(filePath string) (string, error) {
file, err := os.Open(filePath)
if err != nil {
return "", err
}
defer file.Close()
hash := md5.New()
if _, err := io.Copy(hash, file); err != nil {
return "", err
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil
}
// 扫描目录获取文件信息
func (bm *BackupManager) scanDirectory() ([]FileInfo, error) {
var files []FileInfo
err := filepath.Walk(bm.sourceDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// 获取相对路径
relPath, err := filepath.Rel(bm.sourceDir, path)
if err != nil {
return err
}
// 跳过备份目录本身
if strings.HasPrefix(relPath, bm.backupDir) {
return nil
}
fileHash := ""
if !info.IsDir() {
fileHash, err = getFileHash(path)
if err != nil {
return err
}
}
files = append(files, FileInfo{
Path: relPath,
Size: info.Size(),
ModTime: info.ModTime(),
Hash: fileHash,
IsDir: info.IsDir(),
})
return nil
})
return files, err
}
// 创建备份
func (bm *BackupManager) Backup() error {
// 确保备份目录存在
if err := os.MkdirAll(bm.backupDir, 0755); err != nil {
return fmt.Errorf("创建备份目录失败: %v", err)
}
// 扫描源目录
files, err := bm.scanDirectory()
if err != nil {
return fmt.Errorf("扫描目录失败: %v", err)
}
// 创建备份名称
timestamp := time.Now().Format("20060102_150405")
backupName := fmt.Sprintf("backup_%s.zip", timestamp)
backupPath := filepath.Join(bm.backupDir, backupName)
// 创建ZIP文件
zipFile, err := os.Create(backupPath)
if err != nil {
return fmt.Errorf("创建备份文件失败: %v", err)
}
defer zipFile.Close()
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
var totalSize int64
// 添加文件到ZIP
for _, file := range files {
if file.IsDir {
continue
}
// 打开源文件
sourcePath := filepath.Join(bm.sourceDir, file.Path)
sourceFile, err := os.Open(sourcePath)
if err != nil {
return fmt.Errorf("打开源文件失败: %v", err)
}
// 在ZIP中创建文件
header, err := zip.FileInfoHeader(fileInfoFromPath(sourcePath))
if err != nil {
sourceFile.Close()
return fmt.Errorf("创建ZIP头失败: %v", err)
}
header.Name = file.Path
header.Method = zip.Deflate
writer, err := zipWriter.CreateHeader(header)
if err != nil {
sourceFile.Close()
return fmt.Errorf("在ZIP中创建文件失败: %v", err)
}
// 复制文件内容
_, err = io.Copy(writer, sourceFile)
sourceFile.Close()
if err != nil {
return fmt.Errorf("复制文件内容失败: %v", err)
}
totalSize += file.Size
}
// 保存备份信息
backupInfo := BackupInfo{
Name: backupName,
Timestamp: time.Now(),
Files: files,
Size: totalSize,
}
if err := bm.saveBackupInfo(backupInfo); err != nil {
return fmt.Errorf("保存备份信息失败: %v", err)
}
fmt.Printf("备份完成: %s (大小: %.2f MB)\n", backupName, float64(totalSize)/1024/1024)
return nil
}
// 从路径创建文件信息
func fileInfoFromPath(path string) os.FileInfo {
info, _ := os.Stat(path)
return info
}
// 保存备份信息
func (bm *BackupManager) saveBackupInfo(info BackupInfo) error {
// 这里简化处理,实际应用中可以使用JSON或其他格式
indexFile, err := os.OpenFile(bm.indexFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer indexFile.Close()
writer := bufio.NewWriter(indexFile)
defer writer.Flush()
line := fmt.Sprintf("%s|%s|%d\n", info.Name, info.Timestamp.Format(time.RFC3339), info.Size)
_, err = writer.WriteString(line)
return err
}
// 列出所有备份
func (bm *BackupManager) ListBackups() ([]BackupInfo, error) {
file, err := os.Open(bm.indexFile)
if err != nil {
if os.IsNotExist(err) {
return []BackupInfo{}, nil
}
return nil, err
}
defer file.Close()
var backups []BackupInfo
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, "|")
if len(parts) != 3 {
continue
}
timestamp, err := time.Parse(time.RFC3339, parts[1])
if err != nil {
continue
}
var size int64
fmt.Sscanf(parts[2], "%d", &size)
backups = append(backups, BackupInfo{
Name: parts[0],
Timestamp: timestamp,
Size: size,
})
}
// 按时间戳排序
sort.Slice(backups, func(i, j int) bool {
return backups[i].Timestamp.After(backups[j].Timestamp)
})
return backups, nil
}
// 恢复备份
func (bm *BackupManager) Restore(backupName string) error {
backupPath := filepath.Join(bm.backupDir, backupName)
// 打开ZIP文件
reader, err := zip.OpenReader(backupPath)
if err != nil {
return fmt.Errorf("打开备份文件失败: %v", err)
}
defer reader.Close()
// 解压文件
for _, file := range reader.File {
path := filepath.Join(bm.sourceDir, file.Name)
// 创建目录
if file.FileInfo().IsDir() {
if err := os.MkdirAll(path, file.FileInfo().Mode()); err != nil {
return fmt.Errorf("创建目录失败: %v", err)
}
continue
}
// 确保父目录存在
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return fmt.Errorf("创建父目录失败: %v", err)
}
// 打开ZIP中的文件
fileReader, err := file.Open()
if err != nil {
return fmt.Errorf("打开ZIP中的文件失败: %v", err)
}
// 创建目标文件
targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.FileInfo().Mode())
if err != nil {
fileReader.Close()
return fmt.Errorf("创建目标文件失败: %v", err)
}
// 复制文件内容
_, err = io.Copy(targetFile, fileReader)
fileReader.Close()
targetFile.Close()
if err != nil {
return fmt.Errorf("复制文件内容失败: %v", err)
}
}
fmt.Printf("恢复完成: %s\n", backupName)
return nil
}
// 增量备份
func (bm *BackupManager) IncrementalBackup() error {
// 获取最新的备份信息
backups, err := bm.ListBackups()
if err != nil {
return err
}
if len(backups) == 0 {
// 如果没有备份,执行完整备份
return bm.Backup()
}
// 获取当前文件信息
currentFiles, err := bm.scanDirectory()
if err != nil {
return err
}
// 这里简化处理,实际应用中需要比较文件哈希和修改时间
// 只备份有变化的文件
var changedFiles []FileInfo
for _, file := range currentFiles {
if file.IsDir {
continue
}
// 简化处理:备份最近修改的文件
if time.Since(file.ModTime) < 24*time.Hour {
changedFiles = append(changedFiles, file)
}
}
if len(changedFiles) == 0 {
fmt.Println("没有文件需要备份")
return nil
}
// 创建增量备份
timestamp := time.Now().Format("20060102_150405")
backupName := fmt.Sprintf("incremental_%s.zip", timestamp)
backupPath := filepath.Join(bm.backupDir, backupName)
// 创建ZIP文件
zipFile, err := os.Create(backupPath)
if err != nil {
return fmt.Errorf("创建备份文件失败: %v", err)
}
defer zipFile.Close()
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
var totalSize int64
// 添加变化的文件到ZIP
for _, file := range changedFiles {
sourcePath := filepath.Join(bm.sourceDir, file.Path)
sourceFile, err := os.Open(sourcePath)
if err != nil {
return fmt.Errorf("打开源文件失败: %v", err)
}
header, err := zip.FileInfoHeader(fileInfoFromPath(sourcePath))
if err != nil {
sourceFile.Close()
return fmt.Errorf("创建ZIP头失败: %v", err)
}
header.Name = file.Path
header.Method = zip.Deflate
writer, err := zipWriter.CreateHeader(header)
if err != nil {
sourceFile.Close()
return fmt.Errorf("在ZIP中创建文件失败: %v", err)
}
_, err = io.Copy(writer, sourceFile)
sourceFile.Close()
if err != nil {
return fmt.Errorf("复制文件内容失败: %v", err)
}
totalSize += file.Size
}
// 保存备份信息
backupInfo := BackupInfo{
Name: backupName,
Timestamp: time.Now(),
Files: changedFiles,
Size: totalSize,
}
if err := bm.saveBackupInfo(backupInfo); err != nil {
return fmt.Errorf("保存备份信息失败: %v", err)
}
fmt.Printf("增量备份完成: %s (文件数: %d, 大小: %.2f MB)\n",
backupName, len(changedFiles), float64(totalSize)/1024/1024)
return nil
}
func main() {
if len(os.Args) < 3 {
fmt.Println("使用方法:")
fmt.Println(" 完整备份: go run backup.go backup <源目录> <备份目录>")
fmt.Println(" 增量备份: go run backup.go incremental <源目录> <备份目录>")
fmt.Println(" 恢复备份: go run backup.go restore <源目录> <备份目录> <备份文件名>")
fmt.Println(" 列出备份: go run backup.go list <备份目录>")
return
}
command := os.Args[1]
switch command {
case "backup":
if len(os.Args) < 4 {
fmt.Println("请指定源目录和备份目录")
return
}
sourceDir := os.Args[2]
backupDir := os.Args[3]
manager := NewBackupManager(sourceDir, backupDir)
if err := manager.Backup(); err != nil {
fmt.Printf("备份失败: %v\n", err)
}
case "incremental":
if len(os.Args) < 4 {
fmt.Println("请指定源目录和备份目录")
return
}
sourceDir := os.Args[2]
backupDir := os.Args[3]
manager := NewBackupManager(sourceDir, backupDir)
if err := manager.IncrementalBackup(); err != nil {
fmt.Printf("增量备份失败: %v\n", err)
}
case "restore":
if len(os.Args) < 5 {
fmt.Println("请指定源目录、备份目录和备份文件名")
return
}
sourceDir := os.Args[2]
backupDir := os.Args[3]
backupName := os.Args[4]
manager := NewBackupManager(sourceDir, backupDir)
if err := manager.Restore(backupName); err != nil {
fmt.Printf("恢复失败: %v\n", err)
}
case "list":
if len(os.Args) < 3 {
fmt.Println("请指定备份目录")
return
}
backupDir := os.Args[2]
manager := NewBackupManager("", backupDir)
backups, err := manager.ListBackups()
if err != nil {
fmt.Printf("列出备份失败: %v\n", err)
return
}
if len(backups) == 0 {
fmt.Println("没有找到备份")
return
}
fmt.Println("可用备份:")
for _, backup := range backups {
fmt.Printf("%s - %s (%.2f MB)\n",
backup.Name,
backup.Timestamp.Format("2006-01-02 15:04:05"),
float64(backup.Size)/1024/1024)
}
default:
fmt.Println("未知命令")
}
}
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"regexp"
"strings"
"sync"
"time"
)
// 网页信息
type PageInfo struct {
URL string
Title string
Links []string
Error error
}
// 爬虫结构体
type Crawler struct {
visited map[string]bool
mutex sync.Mutex
maxDepth int
delay time.Duration
userAgent string
resultChan chan PageInfo
wg sync.WaitGroup
}
// 创建新的爬虫
func NewCrawler(maxDepth int, delay time.Duration) *Crawler {
return &Crawler{
visited: make(map[string]bool),
maxDepth: maxDepth,
delay: delay,
userAgent: "GoCrawler/1.0",
resultChan: make(chan PageInfo, 100),
}
}
// 提取网页标题
func extractTitle(html string) string {
// 简单的正则表达式提取标题
titleRegex := regexp.MustCompile(`<title>(.*?)</title>`)
matches := titleRegex.FindStringSubmatch(html)
if len(matches) > 1 {
return strings.TrimSpace(matches[1])
}
return ""
}
// 提取链接
func (c *Crawler) extractLinks(baseURL string, html string) []string {
// 提取所有href属性
linkRegex := regexp.MustCompile(`<a[^>]+href=["']([^"']+)["']`)
matches := linkRegex.FindAllStringSubmatch(html, -1)
var links []string
base, err := url.Parse(baseURL)
if err != nil {
return links
}
for _, match := range matches {
if len(match) > 1 {
href := match[1]
// 解析相对URL
parsedURL, err := url.Parse(href)
if err != nil {
continue
}
absoluteURL := base.ResolveReference(parsedURL).String()
// 只保留同域名的链接
if parsedURL.Host == "" || parsedURL.Host == base.Host {
links = append(links, absoluteURL)
}
}
}
return links
}
// 获取网页内容
func (c *Crawler) fetchPage(urlStr string) (string, error) {
// 检查是否已访问
c.mutex.Lock()
if c.visited[urlStr] {
c.mutex.Unlock()
return "", fmt.Errorf("URL已访问: %s", urlStr)
}
c.visited[urlStr] = true
c.mutex.Unlock()
// 创建请求
req, err := http.NewRequest("GET", urlStr, nil)
if err != nil {
return "", err
}
req.Header.Set("User-Agent", c.userAgent)
// 发送请求
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
// 检查状态码
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("HTTP错误: %d", resp.StatusCode)
}
// 读取内容
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
// 检查内容类型
contentType := resp.Header.Get("Content-Type")
if !strings.Contains(contentType, "text/html") {
return "", fmt.Errorf("非HTML内容: %s", contentType)
}
return string(body), nil
}
// 爬取单个页面
func (c *Crawler) crawlPage(urlStr string, depth int) {
defer c.wg.Done()
// 检查深度
if depth > c.maxDepth {
return
}
// 延迟请求
time.Sleep(c.delay)
// 获取页面内容
html, err := c.fetchPage(urlStr)
// 提取信息
pageInfo := PageInfo{
URL: urlStr,
Error: err,
}
if err == nil {
pageInfo.Title = extractTitle(html)
pageInfo.Links = c.extractLinks(urlStr, html)
// 爬取链接页面
for _, link := range pageInfo.Links {
c.wg.Add(1)
go c.crawlPage(link, depth+1)
}
}
// 发送结果
c.resultChan <- pageInfo
}
// 开始爬取
func (c *Crawler) Crawl(startURL string) []PageInfo {
// 启动爬取
c.wg.Add(1)
go c.crawlPage(startURL, 0)
// 启动结果收集器
var results []PageInfo
done := make(chan struct{})
go func() {
for page := range c.resultChan {
results = append(results, page)
}
close(done)
}()
// 等待所有爬取完成
c.wg.Wait()
close(c.resultChan)
// 等待结果收集完成
<-done
return results
}
// 保存结果到文件
func saveResults(results []PageInfo, filename string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
for _, page := range results {
if page.Error != nil {
fmt.Fprintf(file, "URL: %s\n错误: %v\n\n", page.URL, page.Error)
} else {
fmt.Fprintf(file, "URL: %s\n标题: %s\n链接数: %d\n\n",
page.URL, page.Title, len(page.Links))
}
}
return nil
}
// 打印统计信息
func printStats(results []PageInfo) {
var successCount, errorCount int
var totalLinks int
for _, page := range results {
if page.Error != nil {
errorCount++
} else {
successCount++
totalLinks += len(page.Links)
}
}
fmt.Printf("\n爬取统计:\n")
fmt.Printf("成功页面: %d\n", successCount)
fmt.Printf("失败页面: %d\n", errorCount)
fmt.Printf("总链接数: %d\n", totalLinks)
fmt.Printf("平均每页链接数: %.2f\n", float64(totalLinks)/float64(successCount))
}
func main() {
if len(os.Args) < 2 {
fmt.Println("使用方法: go run crawler.go <起始URL> [深度] [延迟(秒)]")
return
}
startURL := os.Args[1]
maxDepth := 2
delay := 1 * time.Second
if len(os.Args) >= 3 {
fmt.Sscanf(os.Args[2], "%d", &maxDepth)
}
if len(os.Args) >= 4 {
delaySec := 0
fmt.Sscanf(os.Args[3], "%d", &delaySec)
delay = time.Duration(delaySec) * time.Second
}
fmt.Printf("开始爬取: %s (深度: %d, 延迟: %v)\n", startURL, maxDepth, delay)
// 创建爬虫
crawler := NewCrawler(maxDepth, delay)
// 开始爬取
start := time.Now()
results := crawler.Crawl(startURL)
duration := time.Since(start)
// 打印结果
fmt.Printf("\n爬取完成,耗时: %v\n", duration)
printStats(results)
// 保存结果
filename := fmt.Sprintf("crawl_results_%s.txt", time.Now().Format("20060102_150405"))
if err := saveResults(results, filename); err != nil {
fmt.Printf("保存结果失败: %v\n", err)
} else {
fmt.Printf("结果已保存到: %s\n", filename)
}
// 打印前几个结果
fmt.Println("\n前5个结果:")
count := 0
for _, page := range results {
if count >= 5 {
break
}
if page.Error != nil {
fmt.Printf("%d. %s - 错误: %v\n", count+1, page.URL, page.Error)
} else {
fmt.Printf("%d. %s - 标题: %s\n", count+1, page.URL, page.Title)
}
count++
}
}
package main
import (
"database/sql"
"fmt"
"log"
"os"
"strconv"
"strings"
"time"
_ "github.com/mattn/go-sqlite3"
)
// 用户模型
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
Address string `json:"address"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// 用户服务
type UserService struct {
db *sql.DB
}
// 创建新的用户服务
func NewUserService(dbPath string) (*UserService, error) {
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return nil, err
}
// 测试连接
if err := db.Ping(); err != nil {
return nil, err
}
// 创建表
if err := createUserTable(db); err != nil {
return nil, err
}
return &UserService{db: db}, nil
}
// 创建用户表
func createUserTable(db *sql.DB) error {
query := `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
age INTEGER,
address TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`
_, err := db.Exec(query)
return err
}
// 创建用户
func (us *UserService) CreateUser(user User) (int, error) {
query := `
INSERT INTO users (name, email, age, address)
VALUES (?, ?, ?, ?)
`
result, err := us.db.Exec(query, user.Name, user.Email, user.Age, user.Address)
if err != nil {
return 0, fmt.Errorf("创建用户失败: %v", err)
}
id, err := result.LastInsertId()
if err != nil {
return 0, fmt.Errorf("获取用户ID失败: %v", err)
}
return int(id), nil
}
// 根据ID获取用户
func (us *UserService) GetUser(id int) (User, error) {
query := `
SELECT id, name, email, age, address, created_at, updated_at
FROM users
WHERE id = ?
`
var user User
err := us.db.QueryRow(query, id).Scan(
&user.ID, &user.Name, &user.Email, &user.Age,
&user.Address, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
if err == sql.ErrNoRows {
return User{}, fmt.Errorf("用户不存在")
}
return User{}, fmt.Errorf("获取用户失败: %v", err)
}
return user, nil
}
// 根据邮箱获取用户
func (us *UserService) GetUserByEmail(email string) (User, error) {
query := `
SELECT id, name, email, age, address, created_at, updated_at
FROM users
WHERE email = ?
`
var user User
err := us.db.QueryRow(query, email).Scan(
&user.ID, &user.Name, &user.Email, &user.Age,
&user.Address, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
if err == sql.ErrNoRows {
return User{}, fmt.Errorf("用户不存在")
}
return User{}, fmt.Errorf("获取用户失败: %v", err)
}
return user, nil
}
// 更新用户
func (us *UserService) UpdateUser(user User) error {
query := `
UPDATE users
SET name = ?, email = ?, age = ?, address = ?, updated_at = ?
WHERE id = ?
`
_, err := us.db.Exec(query, user.Name, user.Email, user.Age, user.Address, time.Now(), user.ID)
if err != nil {
return fmt.Errorf("更新用户失败: %v", err)
}
return nil
}
// 删除用户
func (us *UserService) DeleteUser(id int) error {
query := `DELETE FROM users WHERE id = ?`
result, err := us.db.Exec(query, id)
if err != nil {
return fmt.Errorf("删除用户失败: %v", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("获取影响行数失败: %v", err)
}
if rowsAffected == 0 {
return fmt.Errorf("用户不存在")
}
return nil
}
// 获取所有用户
func (us *UserService) ListUsers() ([]User, error) {
query := `
SELECT id, name, email, age, address, created_at, updated_at
FROM users
ORDER BY id
`
rows, err := us.db.Query(query)
if err != nil {
return nil, fmt.Errorf("查询用户失败: %v", err)
}
defer rows.Close()
var users []User
for rows.Next() {
var user User
err := rows.Scan(
&user.ID, &user.Name, &user.Email, &user.Age,
&user.Address, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
return nil, fmt.Errorf("扫描用户数据失败: %v", err)
}
users = append(users, user)
}
if err = rows.Err(); err != nil {
return nil, fmt.Errorf("遍历用户数据失败: %v", err)
}
return users, nil
}
// 搜索用户
func (us *UserService) SearchUsers(keyword string) ([]User, error) {
query := `
SELECT id, name, email, age, address, created_at, updated_at
FROM users
WHERE name LIKE ? OR email LIKE ? OR address LIKE ?
ORDER BY id
`
searchPattern := "%" + keyword + "%"
rows, err := us.db.Query(query, searchPattern, searchPattern, searchPattern)
if err != nil {
return nil, fmt.Errorf("搜索用户失败: %v", err)
}
defer rows.Close()
var users []User
for rows.Next() {
var user User
err := rows.Scan(
&user.ID, &user.Name, &user.Email, &user.Age,
&user.Address, &user.CreatedAt, &user.UpdatedAt)
if err != nil {
return nil, fmt.Errorf("扫描用户数据失败: %v", err)
}
users = append(users, user)
}
if err = rows.Err(); err != nil {
return nil, fmt.Errorf("遍历用户数据失败: %v", err)
}
return users, nil
}
// 获取用户统计信息
func (us *UserService) GetUserStats() (map[string]int, error) {
stats := make(map[string]int)
// 总用户数
var totalUsers int
err := us.db.QueryRow("SELECT COUNT(*) FROM users").Scan(&totalUsers)
if err != nil {
return nil, fmt.Errorf("获取总用户数失败: %v", err)
}
stats["total"] = totalUsers
// 按年龄段统计
ageGroups := []struct {
name string
query string
}{
{"young", "SELECT COUNT(*) FROM users WHERE age < 18"},
{"adult", "SELECT COUNT(*) FROM users WHERE age BETWEEN 18 AND 60"},
{"senior", "SELECT COUNT(*) FROM users WHERE age > 60"},
}
for _, group := range ageGroups {
var count int
err := us.db.QueryRow(group.query).Scan(&count)
if err != nil {
return nil, fmt.Errorf("获取%s用户数失败: %v", group.name, err)
}
stats[group.name] = count
}
return stats, nil
}
// 关闭数据库连接
func (us *UserService) Close() error {
return us.db.Close()
}
// 显示菜单
func showMenu() {
fmt.Println("\n===== 用户管理系统 =====")
fmt.Println("1. 创建用户")
fmt.Println("2. 查看用户")
fmt.Println("3. 更新用户")
fmt.Println("4. 删除用户")
fmt.Println("5. 列出所有用户")
fmt.Println("6. 搜索用户")
fmt.Println("7. 用户统计")
fmt.Println("8. 退出")
fmt.Print("请选择操作: ")
}
// 读取用户输入
func readInput(prompt string) string {
fmt.Print(prompt)
var input string
fmt.Scanln(&input)
return strings.TrimSpace(input)
}
// 读取整数输入
func readIntInput(prompt string) int {
for {
input := readInput(prompt)
value, err := strconv.Atoi(input)
if err != nil {
fmt.Println("请输入有效的整数")
continue
}
return value
}
}
func main() {
// 创建用户服务
userService, err := NewUserService("./users.db")
if err != nil {
log.Fatalf("创建用户服务失败: %v", err)
}
defer userService.Close()
fmt.Println("欢迎使用用户管理系统")
for {
showMenu()
choice := readInput("")
switch choice {
case "1":
// 创建用户
name := readInput("姓名: ")
email := readInput("邮箱: ")
age := readIntInput("年龄: ")
address := readInput("地址: ")
user := User{
Name: name,
Email: email,
Age: age,
Address: address,
}
id, err := userService.CreateUser(user)
if err != nil {
fmt.Printf("创建用户失败: %v\n", err)
} else {
fmt.Printf("用户创建成功,ID: %d\n", id)
}
case "2":
// 查看用户
id := readIntInput("用户ID: ")
user, err := userService.GetUser(id)
if err != nil {
fmt.Printf("获取用户失败: %v\n", err)
} else {
fmt.Printf("ID: %d\n", user.ID)
fmt.Printf("姓名: %s\n", user.Name)
fmt.Printf("邮箱: %s\n", user.Email)
fmt.Printf("年龄: %d\n", user.Age)
fmt.Printf("地址: %s\n", user.Address)
fmt.Printf("创建时间: %s\n", user.CreatedAt.Format("2006-01-02 15:04:05"))
}
case "3":
// 更新用户
id := readIntInput("用户ID: ")
// 先获取现有用户信息
user, err := userService.GetUser(id)
if err != nil {
fmt.Printf("获取用户失败: %v\n", err)
continue
}
fmt.Println("当前用户信息:")
fmt.Printf("姓名: %s\n", user.Name)
fmt.Printf("邮箱: %s\n", user.Email)
fmt.Printf("年龄: %d\n", user.Age)
fmt.Printf("地址: %s\n", user.Address)
// 获取新信息
name := readInput("新姓名 (留空保持不变): ")
if name != "" {
user.Name = name
}
email := readInput("新邮箱 (留空保持不变): ")
if email != "" {
user.Email = email
}
ageInput := readInput("新年龄 (留空保持不变): ")
if ageInput != "" {
age, err := strconv.Atoi(ageInput)
if err == nil {
user.Age = age
}
}
address := readInput("新地址 (留空保持不变): ")
if address != "" {
user.Address = address
}
if err := userService.UpdateUser(user); err != nil {
fmt.Printf("更新用户失败: %v\n", err)
} else {
fmt.Println("用户更新成功")
}
case "4":
// 删除用户
id := readIntInput("用户ID: ")
// 确认删除
confirm := readInput(fmt.Sprintf("确定要删除ID为%d的用户吗? (y/n): ", id))
if strings.ToLower(confirm) == "y" {
if err := userService.DeleteUser(id); err != nil {
fmt.Printf("删除用户失败: %v\n", err)
} else {
fmt.Println("用户删除成功")
}
} else {
fmt.Println("取消删除")
}
case "5":
// 列出所有用户
users, err := userService.ListUsers()
if err != nil {
fmt.Printf("获取用户列表失败: %v\n", err)
continue
}
if len(users) == 0 {
fmt.Println("没有用户")
continue
}
fmt.Println("\n用户列表:")
fmt.Println("ID\t姓名\t邮箱\t年龄")
for _, user := range users {
fmt.Printf("%d\t%s\t%s\t%d\n", user.ID, user.Name, user.Email, user.Age)
}
case "6":
// 搜索用户
keyword := readInput("搜索关键词: ")
users, err := userService.SearchUsers(keyword)
if err != nil {
fmt.Printf("搜索用户失败: %v\n", err)
continue
}
if len(users) == 0 {
fmt.Println("没有找到匹配的用户")
continue
}
fmt.Printf("\n找到%d个匹配的用户:\n", len(users))
fmt.Println("ID\t姓名\t邮箱\t年龄")
for _, user := range users {
fmt.Printf("%d\t%s\t%s\t%d\n", user.ID, user.Name, user.Email, user.Age)
}
case "7":
// 用户统计
stats, err := userService.GetUserStats()
if err != nil {
fmt.Printf("获取用户统计失败: %v\n", err)
continue
}
fmt.Println("\n用户统计:")
fmt.Printf("总用户数: %d\n", stats["total"])
fmt.Printf("青少年用户 (<18岁): %d\n", stats["young"])
fmt.Printf("成年用户 (18-60岁): %d\n", stats["adult"])
fmt.Printf("老年用户 (>60岁): %d\n", stats["senior"])
case "8":
// 退出
fmt.Println("感谢使用用户管理系统,再见!")
return
default:
fmt.Println("无效的选择,请重新输入")
}
}
}
A: 使用bufio.Scanner或分块读取,避免内存溢出
A: 使用sql.DB的SetMaxOpenConns、SetMaxIdleConns等方法配置
A: 使用race detector:go run -race main.go
完成本阶段学习后,进入第四阶段:完整项目实践