Golang小项目(1)
Golang小项目(1)
前言
本项目适合Golang初学者,通过简单的项目实践来加深对Golang的基本语法和Web开发的理解。
正文
项目结构
.
├── main.go
└── static
├── form.html
└── index.html
项目流程图
定义三个路由:
/
:首页,显示static/index.html
页面/hello
:欢迎页面,显示hello
/form
:表单页面,显示static/form.html
页面
项目初始化
package main
// 导入必要的包
import (
"fmt"
"log"
"net/http"
)
func main(){
}
在static目录下创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Static Website</title>
</head>
<body>
<h2>Static Website</h2>
</body>
</html>
在static目录下创建form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Page</title>
</head>
<body>
<div>
<form action="/form" method="POST">
<label>Name</label><input name="name" type="text" value=""/>
<label>Address</label><input name="address" type="text" value=""/>
<input type="submit" value="Submit"/>
</form>
</div>
</body>
</html>
编写程序主入口
func main() {
// 创建一个 HTTP 文件服务器,用于提供静态文件
fileServer := http.FileServer(http.Dir("./static"))
// 将根路径 / 绑定到 fileServer 处理器。这意味着所有根路径的请求都由 fileServer 处理,提供 ./static 目录中的文件。
http.Handle("/", fileServer)
// 将 /form 路径绑定到 formHandler 函数。这意味着对 /form 的请求将由 formHandler 处理。
http.HandleFunc("/form", formHandler)
// 将 /hello 路径绑定到 helloHandler 函数。这意味着对 /hello 的请求将由 helloHandler 处理。
http.HandleFunc("/hello", helloHandler)
// 打印一条消息,表示服务器正在启动,监听 8080 端口。
fmt.Fprintf("Starting server at port 8080\n")
// 启动一个 HTTP 服务器,监听 8080 端口。如果启动失败,err 将不为空。
// nil 表示使用默认的 ServeMux 路由器。
if err := http.ListenAndServe(":8080",nil); err != nil {
// 如果服务器启动失败,记录错误并终止程序。
log.Fatal(err)
}
}
编写路由处理函数
// 表单处理函数
// w 为 http.ResponseWriter 的实例,用于向客户端返回响应。
// r 为 http.Request 的实例,包含了客户端的请求信息。
func formHandler(w http.ResponseWriter, r *http.Request){
// 尝试解析表单数据。如果解析失败,将打印err信息。
if err := r.ParseForm(); err != nil {
fmt.Fprintf(w, "ParseForm() err: %v", err)
// 结束函数执行
return
}
// 如果表单解析成功,向响应写入成功信息。
fmt.Fprintf(w, "POST request successful")
// 获取form.html页面中表单中名为 name 和 address 的字段值。
name := r.FormValue("name")
address := r.FormValue("address")
// 将 name 和 address 字段值写入响应 w。
fmt.Fprintf(w, "Name = %s\n", name)
fmt.Fprintf(w, "Address = %s\n", address)
}
/// 欢迎页面处理函数
func helloHandler(w http.ResponseWriter, r *http.Request){
// 检查request请求的 URL 路径是否为 /hello,如果不是,返回 404 错误响应。
if r.URL.Path != "/hello" {
http.Error(w, "404 not found", http.StatusNotFound)
// 结束函数执行
return
}
// 检查请求的方法是否为 GET,如果不是,返回 405 错误(即请求方法不允许)。
if r.Method != "GET" {
http.Error(w, "method is not supported", http.StatusNotFound)
return
}
// 如果路径和方法均匹配,向响应写入 "hello!"。
fmt.Fprintf(w, "hello!")
}
运行项目
go build main.go
go run main.go
打开浏览器,访问 http://localhost:8080/ ,显示
Static Website
页面。
打开浏览器,访问 http://localhost:8080/hello ,显示hello!
页面。
打开浏览器,访问 http://localhost:8080/form.html ,显示Form Page
页面,并可以输入姓名和地址。
每日小技巧:指针传递
在 Go 语言中,* 用于声明和操作指针。具体到 r *http.Request 中的 *,它表示 r 是一个指向 http.Request 类型的指针。下面详细解释了在这种上下文中使用 * 的含义和作用:
- 声明指针
在函数参数中使用 * 来声明指针类型。这意味着参数 r 是一个 http.Request 的指针,而不是 http.Request 的值本身。
func handleRequest(r *http.Request) { // 这里的 r 是 *http.Request 类型 }
- 访问和操作 http.Request 对象
- 通过指针访问字段: 使用指针 *http.Request 可以直接访问和修改 http.Request 对象的字段,因为指针指向了实际的 http.Request 对象,而不是其副本。
- 修改请求: 如果函数需要对请求进行修改(例如修改请求头或解析请求体),使用指针可以直接在原始对象上进行操作。
func modifyHeader(r *http.Request) { r.Header.Set("X-Custom-Header", "Value") // 修改请求头 }
- 避免对象复制
- 节省内存: 如果 http.Request 是一个大结构体,直接传递指针而不是整个结构体可以减少内存使用和复制开销。
- 提高性能: 传递指针避免了将整个结构体复制到函数调用栈,从而提高了性能。
- 指针解引用
- 获取实际值: 如果你有一个指向 http.Request 的指针,可以通过解引用(*r)来访问实际的 http.Request 对象。
func printRequestMethod(r *http.Request) { fmt.Println(r.Method) // 访问请求方法 }
- 一致性和标准库
- 与标准库一致: Go 的标准库中处理 HTTP 请求的函数普遍使用 *http.Request,这为开发者提供了一种一致的编程模式,并确保了对 http.Request 的高效处理。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Fender