实践项目

实践项目

本章节将通过实际项目示例,帮助您将 Go 的理论知识应用到实践中,并与 Python、Java 和 C#中的类似实现进行比较。

命令行应用

在 Go 中构建命令行工具

Go 非常适合构建高性能的命令行工具,标准库提供了强大的支持,同时也有优秀的第三方库如cobraurfave/cli

基本命令行应用示例

// Go实现
package main

import (
	"flag"
	"fmt"
	"os"
)

func main() {
	// 定义命令行参数
	name := flag.String("name", "World", "名称")
	times := flag.Int("times", 1, "重复次数")

	// 解析命令行参数
	flag.Parse()

	// 使用参数
	for i := 0; i < *times; i++ {
		fmt.Printf("Hello, %s!\n", *name)
	}
}

与其他语言的比较

# Python实现 (使用argparse)
import argparse

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--name", default="World", help="名称")
    parser.add_argument("--times", type=int, default=1, help="重复次数")

    args = parser.parse_args()

    for i in range(args.times):
        print(f"Hello, {args.name}!")

if __name__ == "__main__":
    main()
// Java实现 (使用Apache Commons CLI)
import org.apache.commons.cli.*;

public class HelloApp {
    public static void main(String[] args) {
        Options options = new Options();
        options.addOption(Option.builder("name")
                .hasArg()
                .desc("名称")
                .build());
        options.addOption(Option.builder("times")
                .hasArg()
                .type(Number.class)
                .desc("重复次数")
                .build());

        CommandLineParser parser = new DefaultParser();
        try {
            CommandLine cmd = parser.parse(options, args);
            String name = cmd.getOptionValue("name", "World");
            int times = Integer.parseInt(cmd.getOptionValue("times", "1"));

            for (int i = 0; i < times; i++) {
                System.out.println("Hello, " + name + "!");
            }
        } catch (Exception e) {
            System.err.println("解析参数出错: " + e.getMessage());
        }
    }
}
// C#实现
using System;
using CommandLine;

class Options {
    [Option('n', "name", Default = "World", HelpText = "名称")]
    public string Name { get; set; }

    [Option('t', "times", Default = 1, HelpText = "重复次数")]
    public int Times { get; set; }
}

class Program {
    static void Main(string[] args) {
        Parser.Default.ParseArguments<Options>(args)
            .WithParsed(opts => {
                for (int i = 0; i < opts.Times; i++) {
                    Console.WriteLine($"Hello, {opts.Name}!");
                }
            });
    }
}

使用第三方库构建更复杂的 CLI

对于更复杂的命令行应用,Go 中的cobra库是一个流行选择:

package main

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

func main() {
	var rootCmd = &cobra.Command{
		Use:   "myapp",
		Short: "一个示例CLI应用",
		Long:  "一个使用cobra构建的Go命令行应用示例",
	}

	var name string
	var times int

	var greetCmd = &cobra.Command{
		Use:   "greet",
		Short: "打印问候语",
		Run: func(cmd *cobra.Command, args []string) {
			for i := 0; i < times; i++ {
				fmt.Printf("Hello, %s!\n", name)
			}
		},
	}

	greetCmd.Flags().StringVarP(&name, "name", "n", "World", "名称")
	greetCmd.Flags().IntVarP(&times, "times", "t", 1, "重复次数")

	rootCmd.AddCommand(greetCmd)

	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

Web 服务

RESTful API 开发

Go 的标准库net/http提供了强大的 Web 服务开发能力,同时也有许多流行的 Web 框架如 Gin、Echo 等。

基本 HTTP 服务器

// Go实现
package main

import (
	"encoding/json"
	"log"
	"net/http"
)

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

var users = []User{
	{ID: 1, Name: "Alice"},
	{ID: 2, Name: "Bob"},
}

func getUsers(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(users)
}

func main() {
	http.HandleFunc("/users", getUsers)
	log.Println("服务器启动在 http://localhost:8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

使用 Gin 框架

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

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

var users = []User{
	{ID: 1, Name: "Alice"},
	{ID: 2, Name: "Bob"},
}

func main() {
	r := gin.Default()

	r.GET("/users", func(c *gin.Context) {
		c.JSON(http.StatusOK, users)
	})

	r.POST("/users", func(c *gin.Context) {
		var newUser User
		if err := c.BindJSON(&newUser); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}

		// 为简化示例,这里直接分配ID
		newUser.ID = len(users) + 1
		users = append(users, newUser)

		c.JSON(http.StatusCreated, newUser)
	})

	r.Run(":8080")
}

与其他语言的比较

# Python (Flask)
from flask import Flask, jsonify, request

app = Flask(__name__)

users = [
    {"id": 1, "name": "Alice"},
    {"id": 2, "name": "Bob"}
]

@app.route('/users', methods=['GET'])
def get_users():
    return jsonify(users)

@app.route('/users', methods=['POST'])
def create_user():
    new_user = request.get_json()
    new_user['id'] = len(users) + 1
    users.append(new_user)
    return jsonify(new_user), 201

if __name__ == '__main__':
    app.run(debug=True, port=8080)
// Java (Spring Boot)
@RestController
public class UserController {

    private List<User> users = new ArrayList<>(Arrays.asList(
        new User(1, "Alice"),
        new User(2, "Bob")
    ));

    @GetMapping("/users")
    public List<User> getUsers() {
        return users;
    }

    @PostMapping("/users")
    @ResponseStatus(HttpStatus.CREATED)
    public User createUser(@RequestBody User user) {
        user.setId(users.size() + 1);
        users.add(user);
        return user;
    }
}

@Data
@AllArgsConstructor
class User {
    private int id;
    private String name;
}
// C# (ASP.NET Core)
[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
    private static List<User> _users = new List<User>
    {
        new User { Id = 1, Name = "Alice" },
        new User { Id = 2, Name = "Bob" }
    };

    [HttpGet]
    public ActionResult<IEnumerable<User>> Get()
    {
        return _users;
    }

    [HttpPost]
    public ActionResult<User> Post(User user)
    {
        user.Id = _users.Count + 1;
        _users.Add(user);
        return CreatedAtAction(nameof(Get), new { id = user.Id }, user);
    }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

数据处理

处理文件和数据库

文件处理

// Go文件处理
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	// 写入文件
	file, err := os.Create("data.txt")
	if err != nil {
		fmt.Println("创建文件失败:", err)
		return
	}
	defer file.Close()

	_, err = file.WriteString("Hello, Go!\nThis is a file example.")
	if err != nil {
		fmt.Println("写入文件失败:", err)
		return
	}

	// 读取文件
	readFile, err := os.Open("data.txt")
	if err != nil {
		fmt.Println("打开文件失败:", err)
		return
	}
	defer readFile.Close()

	scanner := bufio.NewScanner(readFile)
	for scanner.Scan() {
		line := scanner.Text()
		fmt.Println(line)
		// 处理每一行
		if strings.Contains(line, "Go") {
			fmt.Println("找到Go关键字!")
		}
	}

	if err := scanner.Err(); err != nil {
		fmt.Println("读取文件失败:", err)
	}
}

数据库操作

// Go数据库操作 (使用database/sql和SQLite)
package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "github.com/mattn/go-sqlite3"
)

type User struct {
	ID   int
	Name string
	Age  int
}

func main() {
	// 打开数据库连接
	db, err := sql.Open("sqlite3", "./users.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// 创建表
	_, err = db.Exec(`CREATE TABLE IF NOT EXISTS users (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		name TEXT NOT NULL,
		age INTEGER
	)`);
	if err != nil {
		log.Fatal(err)
	}

	// 插入数据
	result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 30)
	if err != nil {
		log.Fatal(err)
	}

	id, _ := result.LastInsertId()
	fmt.Printf("插入用户ID: %d\n", id)

	// 查询数据
	rows, err := db.Query("SELECT id, name, age FROM users")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	var users []