Go Web 项目实战:构建 RESTful API、命令行工具及应用部署

Go Web 项目实战:构建 RESTful API、命令行工具及应用部署

Go 语言因其简洁高效、并发支持强大等特点,已经成为了后端开发的热门选择之一。本篇文章将通过实战案例带领你学习如何使用 Go 构建一个简单的 RESTful API,开发命令行工具,并展示如何使用 Docker 部署 Go 应用。通过这些实战内容,你可以更好地理解 Go 在实际开发中的应用。

1. 构建一个简单的 RESTful API

RESTful API 是基于 HTTP 协议的 API 设计风格,它通过 URL、HTTP 动词和状态码等约定来实现客户端与服务器端的通信。Go 的 net/http 包使得构建 RESTful API 非常简单。

1.1 使用 net/http 创建一个简单的 RESTful API

我们将构建一个简单的 Todo 应用,支持以下接口:

  • GET /todos:获取所有任务
  • POST /todos:创建一个新的任务
  • GET /todos/{id}:获取指定任务
  • DELETE /todos/{id}:删除指定任务
示例代码:
package mainimport ("encoding/json""fmt""net/http""strconv""sync"
)type Todo struct {ID   int    `json:"id"`Task string `json:"task"`
}var todos = []Todo{}
var idCounter = 1
var mutex sync.Mutex// 获取所有任务
func getTodos(w http.ResponseWriter, r *http.Request) {mutex.Lock()defer mutex.Unlock()w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(todos)
}// 创建一个新的任务
func createTodo(w http.ResponseWriter, r *http.Request) {mutex.Lock()defer mutex.Unlock()var todo Todoif err := json.NewDecoder(r.Body).Decode(&todo); err != nil {http.Error(w, err.Error(), http.StatusBadRequest)return}todo.ID = idCounteridCounter++todos = append(todos, todo)w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(todo)
}// 获取指定 ID 的任务
func getTodoByID(w http.ResponseWriter, r *http.Request) {mutex.Lock()defer mutex.Unlock()id, err := strconv.Atoi(r.URL.Query().Get("id"))if err != nil || id <= 0 {http.Error(w, "Invalid ID", http.StatusBadRequest)return}for _, todo := range todos {if todo.ID == id {w.Header().Set("Content-Type", "application/json")json.NewEncoder(w).Encode(todo)return}}http.Error(w, "Todo not found", http.StatusNotFound)
}// 删除指定 ID 的任务
func deleteTodoByID(w http.ResponseWriter, r *http.Request) {mutex.Lock()defer mutex.Unlock()id, err := strconv.Atoi(r.URL.Query().Get("id"))if err != nil || id <= 0 {http.Error(w, "Invalid ID", http.StatusBadRequest)return}for i, todo := range todos {if todo.ID == id {todos = append(todos[:i], todos[i+1:]...)w.WriteHeader(http.StatusNoContent)return}}http.Error(w, "Todo not found", http.StatusNotFound)
}func main() {http.HandleFunc("/todos", getTodos)           // GET /todoshttp.HandleFunc("/todos", createTodo)         // POST /todoshttp.HandleFunc("/todos", getTodoByID)        // GET /todos/{id}http.HandleFunc("/todos", deleteTodoByID)     // DELETE /todos/{id}fmt.Println("Starting server on :8080...")http.ListenAndServe(":8080", nil)
}
代码解释:
  • getTodos:处理 GET /todos 请求,返回所有任务。
  • createTodo:处理 POST /todos 请求,创建新的任务。
  • getTodoByID:处理 GET /todos/{id} 请求,根据任务 ID 返回指定任务。
  • deleteTodoByID:处理 DELETE /todos/{id} 请求,删除指定任务。

1.2 错误示例:没有错误处理

// 错误示例:没有正确处理 POST 请求的错误
func createTodo(w http.ResponseWriter, r *http.Request) {var todo Todojson.NewDecoder(r.Body).Decode(&todo)  // 错误:未检查解码错误todos = append(todos, todo)json.NewEncoder(w).Encode(todo)
}

在这个错误示例中,解码失败时没有进行错误处理。正确的做法是检查 Decode 的返回值,确保数据被正确解析。

1.3 正确示例:添加错误处理

// 正确示例:添加错误处理
func createTodo(w http.ResponseWriter, r *http.Request) {var todo Todoif err := json.NewDecoder(r.Body).Decode(&todo); err != nil {http.Error(w, err.Error(), http.StatusBadRequest)return}todos = append(todos, todo)json.NewEncoder(w).Encode(todo)
}

2. 使用 Go 构建命令行工具

Go 语言非常适合用于构建命令行工具,它提供了强大的标准库支持。我们将构建一个简单的命令行工具,允许用户通过命令行添加、删除和查看任务。

2.1 创建命令行工具

Go 标准库提供了 flag 包来解析命令行参数。

package mainimport ("flag""fmt"
)func main() {// 定义命令行参数var task stringvar list boolflag.StringVar(&task, "task", "", "Task description")flag.BoolVar(&list, "list", false, "List all tasks")flag.Parse()if list {fmt.Println("Listing all tasks...")} else if task != "" {fmt.Println("Adding task:", task)} else {fmt.Println("No action specified.")}
}
错误示例:没有处理缺失的参数
// 错误示例:没有处理缺失参数的情况
func main() {var task stringflag.StringVar(&task, "task", "", "Task description")flag.Parse()if task == "" {fmt.Println("Task is required")  // 错误:缺少必要的参数提示} else {fmt.Println("Adding task:", task)}
}

在上面的错误示例中,缺少了对用户输入无效或缺失参数的提示。

正确示例:增加参数验证
// 正确示例:增加参数验证
func main() {var task stringflag.StringVar(&task, "task", "", "Task description")flag.Parse()if task == "" {fmt.Println("Error: Task is required")flag.Usage()return}fmt.Println("Adding task:", task)
}

3. 部署 Go 应用(Docker)

Go 是一种非常适合容器化的语言,使用 Docker 可以方便地部署 Go 应用。接下来,我们将展示如何使用 Docker 部署一个简单的 Go 应用。

3.1 创建 Dockerfile

Dockerfile 是 Docker 构建镜像时的配置文件。我们需要为 Go 应用创建一个 Dockerfile,用来构建并运行 Go 应用。

# 使用 Go 官方镜像作为基础镜像
FROM golang:1.18-alpine# 设置工作目录
WORKDIR /app# 将当前目录下的所有文件复制到 Docker 容器的 /app 目录
COPY . .# 下载 Go 依赖
RUN go mod tidy# 编译 Go 应用
RUN go build -o main .# 暴露 8080 端口
EXPOSE 8080# 启动应用
CMD ["./main"]

3.2 构建 Docker 镜像

docker build -t go-web-app .

3.3 运行 Docker 容器

docker run -p 8080:8080 go-web-app

通过 docker run 启动容器,并将容器的 8080 端口映射到主机的 8080 端口。


4. 面试题与常见问题

以下是一些关于 Go Web 开发的常见面试题,帮助你准备面试:

面试题 1:Go 中的 RESTful

API 如何设计?

  • 回答:Go 的 net/http 包可以非常简洁地处理 HTTP 请求,结合 http.HandleFunc 来实现路由功能,通过定义不同的处理函数来实现 RESTful 风格的接口。

面试题 2:Go 的命令行工具如何实现?

  • 回答:Go 提供了 flag 包来解析命令行参数,还可以使用 cobra 等第三方库来构建复杂的命令行工具。

面试题 3:如何使用 Docker 部署 Go 应用?

  • 回答:通过编写 Dockerfile,利用 Go 官方镜像构建 Go 应用的 Docker 镜像,最后运行容器并将应用暴露到指定端口。

总结

通过本篇文章,你学习了如何使用 Go 构建一个简单的 RESTful API,创建命令行工具,并通过 Docker 部署 Go 应用。这些基础知识为你进一步学习 Go Web 开发打下了坚实的基础。希望本文能帮助你理解 Go 在实际开发中的应用,并且在面试中取得好成绩。

如果你对 Go Web 开发有任何疑问或想进一步学习,欢迎在评论区讨论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70346.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Http升级为Https - 开发/测试服环境

1.应用场景 主要用于开发/测试服环境将http升级为https, 防止前端web(浏览器)出现Mixed Content报错; 2.学习/操作 1.文档阅读 deepseek 问答; 2.整理输出 报错信息: Mixed Content: The page at <URL> was loaded over HTTPS, but requested an insecure XMLHttpRequ…

使用 AIStor 和 OpenSearch 增强搜索功能

在这篇文章中&#xff0c;我们将探讨搜索&#xff0c;特别是 OpenSearch 如何帮助我们识别模式或查看不断增长的数据中的趋势。例如&#xff0c;如果您正在查看运营数据&#xff0c;如果您的服务似乎是随机的&#xff0c;那么您需要尽可能回溯以识别模式并找出原因。这不仅适用…

Python——生成AIGC图像

文章目录 一、背景介绍 二、效果图展示 三、完整代码 四、分步解释 五、实用建议 1&#xff09;提示词技巧 2&#xff09;性能优化 3&#xff09;常见问题处理 4&#xff09;扩展功能建议 六、注意事项 1. 硬件要求 2. 法律合规 3. 模型安全 一、背景介绍 AIGC&a…

多任务(20250210)

1. 进程的概念 (1) 程序:是一段存放在外存中代码的集合(静态的) (2) 进程:是一个程序动态执行的过程,包括创建、调度、消亡(动态的) 2. 如何实现多任务 Linux中&#xff0c;通过进程、线性实现多任务 3. 进程 正在执行的程序&#xff08;动态&#xff09;&#xff0c;需…

【2025最新版】Chrome谷歌浏览器如何能恢复到之前的旧版本

背景 今天程序突然出了bug&#xff0c;无法自动测试了&#xff0c;显示Chrome版本不匹配&#xff0c;一看&#xff0c;Chrome居然在我已经关闭升级的情况下&#xff0c;又给我升级了&#xff0c;然后就悲剧了&#xff0c;我的代码不能用了。 于是&#xff0c;做了以下几步&…

解决OpenEuler系统修改句柄无效的问题

本文测试基于OpenEuler的操作系统&#xff0c;比如BC-Linux。 想要使修改文件句柄&#xff08;即最大打开文件数&#xff09;永久生效&#xff0c;通常需要编辑 /etc/security/limits.conf 文件。但可能出现修改了文件之后&#xff0c;并未生效的情况&#xff0c;下面就介绍下可…

自制AirTag,支持安卓/鸿蒙/PC/Home Assistant,无需拥有iPhone

苹果的AirTag很贵&#xff0c;虽然某强北有平价代替品&#xff0c;但是仍需要苹果设备才能绑定&#xff0c;才能查看位置。不支持安卓/鸿蒙/PC&#xff0c;也不支持集成到Home Assistant中。 AirTag 的原理 每个AirTag都会发送一个蓝牙信号&#xff0c;其可以被临近的苹果设备…

双重差分学习笔记

双重差分适用的研究场景&#xff1a; 研究某项政策或者冲击造成的影响 例如&#xff0c;某某小学在2024.12.12日颁布了小红花激励措施&#xff0c;我们要研究这项措施对学生成绩的影响&#xff0c;此时&#xff0c;就可以使用双重差分模型。 双重差分适用的数据类型&#xf…

python入门笔记5-集合与字典

元组 Python 的元组&#xff08;tuple&#xff0c;简写为tup&#xff09;与列表类似&#xff0c;不同之处在于元组的元素不能修改。 元组使用小括号​()​&#xff0c;列表使用方括号​[]​。 好处就是节省内存。 集合 集合是无序、不重复元素的容器。 用 {} 或 set() 创建…

DevOps自动化部署详解:从理念到实践

在软件开发日益快速迭代的今天&#xff0c;如何以高效、稳定且可重复的方式将代码变更从开发环境自动部署到生产环境成为企业竞争的重要因素。DevOps 正是在这一背景下应运而生&#xff0c;它打破开发、测试、运维之间的壁垒&#xff0c;通过自动化工具和流程&#xff0c;实现持…

Python 将PPT幻灯片和形状转换为多种图片格式(JPG, PNG, BMP, SVG, TIFF)

目录 安装所需的库 使用Python将PowerPoint幻灯片转换为JPG、PNG和BMP图片 按实际尺寸将幻灯片保存为图片 按自定义尺寸将幻灯片保存为图片 使用Python将PowerPoint幻灯片转换为SVG图片 使用Python将PowerPoint幻灯片转换为多页TIFF图片 使用Python将PowerPoint幻灯片中…

【设计模式】【创建型模式】工厂方法模式(Factory Methods)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 欢迎点赞、收藏、关注&#xff0c;跟上我的更新节奏 &#x1f3b5; 当你的天空突…

基于STM32的智能工业设备健康监测系统

1. 引言 工业设备故障导致的生产停滞问题日益突出&#xff0c;传统人工巡检方式效率低且难以捕捉早期隐患。本文设计了一款基于STM32的智能工业设备健康监测系统&#xff0c;通过振动分析、温度监测与声纹识别技术&#xff0c;实现设备状态实时评估、故障预警与维护决策支持&a…

第4章:在LangChain中如何实现响应式流(Response Streaming)

文章介绍了 LangChain4j 中的 响应流式传输&#xff08;Response Streaming&#xff09; 功能&#xff0c;展示了如何通过低层次的 LLM&#xff08;大语言模型&#xff09;API 实现逐个令牌&#xff08;token&#xff09;的流式响应。 响应式流&#xff08;Response Streaming&…

旧手机热点无法提供ipv6解决方法(emui 8 热点提供ipv6)

旧手机热点无法提供ipv6解决方法 手机&#xff1a;荣耀8x 系统版本: EMUI 8 网络&#xff1a;移动流量卡 解决方案 设置-》无线和网络-》移动网络-》接入点名称(APN)-》cmiot 修改 APN协议: IPv4/IPv6 修改 APN漫游协议: IPv4/IPv6

Memcached和redis对比了解

1.介绍 Memcached 是一个高性能、分布式的内存缓存系统&#xff0c;用于加速动态 Web 应用程序&#xff0c;减少数据库负载。它的核心功能是将数据存储在内存中&#xff0c;并通过基于键值对&#xff08;Key-Value&#xff09;的方式快速读取数据。 Redis 和 Memcached 选择建…

mysql之如何获知版本

你可以通过在 MySQL 命令行客户端执行简单的 SQL 查询来获取 MySQL 的版本信息。以下是获取 MySQL 版本的常见方法&#xff1a; 使用 SELECT VERSION(); 查询&#xff1a; SELECT VERSION();执行这个查询后&#xff0c;MySQL 会返回一个字符串&#xff0c;其中包含了 MySQL 服…

SOME/IP--协议英文原文讲解9

前言 SOME/IP协议越来越多的用于汽车电子行业中&#xff0c;关于协议详细完全的中文资料却没有&#xff0c;所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块&#xff1a; 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 4.2.1.4 T…

汽车免拆诊断案例 | 2010 款路虎揽胜车空调偶尔出风异常

故障现象  一辆2010款路虎揽胜车&#xff0c;搭载5.0 L发动机&#xff0c;累计行驶里程约为16万km。车主反映&#xff0c;接通空调开关后&#xff0c;有时出风忽大忽小&#xff0c;有时不出风&#xff0c;有时要等2 min左右才出风&#xff1b;有时两三天出现一次&#xff0c;…

【SQL】SQL多表查询

多表查询案例联系点击此处 &#x1f384;概念 一般我们说的多表查询都涉及外键和父子表之间的关系。比如一对多:一般前面指的是父表后面指的是子表。 ⭐分类 一对多(多对一) 多对多 一对一 ⭐一对多 &#x1f4e2;案例&#xff1a;部门与员工的关系 &#x1f4e2;关系&…