Web开发
基本Web服务器
使用net/http包创建基本的Web服务器。
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
func main() {
// 注册处理函数
http.HandleFunc("/", handler)
// 启动服务器
fmt.Println("Server starting on :8080...")
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
路由处理
使用gorilla/mux实现更强大的路由功能。
package main
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
)
type User struct {
ID string `json:"id"`
Name string `json:"name"`
}
var users = []User{
{ID: "1", Name: "John"},
{ID: "2", Name: "Jane"},
}
func getUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
func getUser(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
for _, user := range users {
if user.ID == id {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
return
}
}
w.WriteHeader(http.StatusNotFound)
}
func main() {
r := mux.NewRouter()
// 注册路由
r.HandleFunc("/users", getUsers).Methods("GET")
r.HandleFunc("/users/{id}", getUser).Methods("GET")
// 启动服务器
http.ListenAndServe(":8080", r)
}
中间件
使用中间件处理通用功能,如日志记录、认证等。
package main
import (
"log"
"net/http"
"time"
)
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// 调用下一个处理器
next.ServeHTTP(w, r)
// 记录请求信息
log.Printf(
"%s %s %s %v",
r.Method,
r.RequestURI,
r.RemoteAddr,
time.Since(start),
)
})
}
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// 验证token
if !isValidToken(token) {
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func main() {
mux := http.NewServeMux()
// 注册路由
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
})
// 使用中间件
handler := loggingMiddleware(authMiddleware(mux))
// 启动服务器
http.ListenAndServe(":8080", handler)
}
模板渲染
使用html/template包渲染HTML模板。
package main
import (
"html/template"
"net/http"
)
type PageData struct {
Title string
Users []User
}
type User struct {
Name string
Email string
}
func renderTemplate(w http.ResponseWriter, r *http.Request) {
// 解析模板
tmpl, err := template.ParseFiles("templates/layout.html", "templates/users.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 准备数据
data := PageData{
Title: "User List",
Users: []User{
{Name: "John", Email: "john@example.com"},
{Name: "Jane", Email: "jane@example.com"},
},
}
// 渲染模板
if err := tmpl.Execute(w, data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func main() {
http.HandleFunc("/", renderTemplate)
http.ListenAndServe(":8080", nil)
}
静态文件服务
提供静态文件(如CSS、JavaScript、图片等)服务。
package main
import (
"net/http"
)
func main() {
// 创建文件服务器
fs := http.FileServer(http.Dir("static"))
// 注册静态文件路由
http.Handle("/static/", http.StripPrefix("/static/", fs))
// 注册其他路由
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
})
// 启动服务器
http.ListenAndServe(":8080", nil)
}
表单处理
处理HTML表单提交的数据。
package main
import (
"html/template"
"net/http"
)
type User struct {
Name string
Email string
Password string
}
func showForm(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles("templates/form.html"))
tmpl.Execute(w, nil)
}
func handleForm(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 解析表单数据
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 获取表单字段
user := User{
Name: r.FormValue("name"),
Email: r.FormValue("email"),
Password: r.FormValue("password"),
}
// 处理用户数据...
// 重定向到成功页面
http.Redirect(w, r, "/success", http.StatusSeeOther)
}
func main() {
http.HandleFunc("/", showForm)
http.HandleFunc("/submit", handleForm)
http.ListenAndServe(":8080", nil)
}
JSON处理
处理JSON数据的编码和解码。
package main
import (
"encoding/json"
"net/http"
)
type Product struct {
ID string `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
}
func getProducts(w http.ResponseWriter, r *http.Request) {
products := []Product{
{ID: "1", Name: "Laptop", Price: 999.99},
{ID: "2", Name: "Phone", Price: 499.99},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(products)
}
func createProduct(w http.ResponseWriter, r *http.Request) {
var product Product
if err := json.NewDecoder(r.Body).Decode(&product); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 处理产品数据...
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(product)
}
func main() {
http.HandleFunc("/products", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
getProducts(w, r)
case http.MethodPost:
createProduct(w, r)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
})
http.ListenAndServe(":8080", nil)
}
错误处理
处理Web应用中的错误情况。
package main
import (
"encoding/json"
"net/http"
)
type ErrorResponse struct {
Error string `json:"error"`
Message string `json:"message"`
Code int `json:"code"`
}
func handleError(w http.ResponseWriter, err error, status int) {
response := ErrorResponse{
Error: http.StatusText(status),
Message: err.Error(),
Code: status,
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(response)
}
func handler(w http.ResponseWriter, r *http.Request) {
// 模拟错误情况
if r.URL.Path == "/error" {
handleError(w, fmt.Errorf("something went wrong"), http.StatusInternalServerError)
return
}
if r.URL.Path == "/notfound" {
handleError(w, fmt.Errorf("resource not found"), http.StatusNotFound)
return
}
w.Write([]byte("OK"))
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}