Golang中从Pat路由器切换到ServeMux的方法

Golang中从Pat路由器切换到ServeMux的方法 Hugo 是一个用 Go 构建的静态网站生成器。使用 Hugo 时,您可以为内容创建 Markdown 文件,HTML 将自动生成。

非静态设置的一个原因是能够拥有联系表单,而无需暴露您的电子邮件。这是一种让人们发送消息的简单方式,无需他们编写电子邮件。

您可能知道 Formspree 或类似的服务。它们提供了在页面上使用标准 HTML 表单的可能性,它们会处理消息并通过邮件发送给您,这样您就不需要自己管理数据库和所有那些东西。

我将在 Go 中构建一个非常简单的联系表单,但用于自托管。想法是 API 应该独立于我的 Hugo 项目。我有多个需要联系表单的项目。

我为所有感兴趣的人建立了一个公共仓库:https://gitlab.com/joergklein/smtpmailer

以下是一个代码片段。我使用 pat 作为路由器。我认为使用公共库中的 ServeMux 会更好。

请查看仓库,我需要帮助将 pat 改为 ServeMux。

package main

import (
	"github.com/bmizerany/pat"
	"html/template"
	"log"
	"net/http"
)

func main() {
	mux := pat.New()
	mux.Get("/", http.HandlerFunc(index))
	mux.Post("/", http.HandlerFunc(send))
	mux.Get("/confirmation", http.HandlerFunc(confirmation))

	log.Println("Listening on port 8080")
	http.ListenAndServe(":8080", mux)
}

func index(w http.ResponseWriter, r *http.Request) {
	render(w, "templates/index.html", nil)
}

func send(w http.ResponseWriter, r *http.Request) {
	msg := &Message{
		Name:    r.FormValue("name"),
		Email:   r.FormValue("email"),
		Subject: r.FormValue("subject"),
		Content: r.FormValue("content"),
	}

	if msg.Validate() == false {
		render(w, "templates/index.html", msg)
		return
	}

	if err := msg.Deliver(); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	http.Redirect(w, r, "/confirmation", http.StatusSeeOther)
}

func confirmation(w http.ResponseWriter, r *http.Request) {
	render(w, "templates/confirmation.html", nil)
}

func render(w http.ResponseWriter, filename string, data interface{}) {
	tmpl, err := template.ParseFiles(filename)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	if err := tmpl.Execute(w, data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

更多关于Golang中从Pat路由器切换到ServeMux的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中从Pat路由器切换到ServeMux的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下是使用标准库 ServeMux 替换 pat 路由器的修改版本。主要变化包括使用 http.HandleFunc 注册路由,并处理不同 HTTP 方法(GET 和 POST)在同一路径上的区分。

package main

import (
    "html/template"
    "log"
    "net/http"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", handleIndexAndSend)
    mux.HandleFunc("/confirmation", confirmation)

    log.Println("Listening on port 8080")
    http.ListenAndServe(":8080", mux)
}

func handleIndexAndSend(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        index(w, r)
    case http.MethodPost:
        send(w, r)
    default:
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
}

func index(w http.ResponseWriter, r *http.Request) {
    render(w, "templates/index.html", nil)
}

func send(w http.ResponseWriter, r *http.Request) {
    msg := &Message{
        Name:    r.FormValue("name"),
        Email:   r.FormValue("email"),
        Subject: r.FormValue("subject"),
        Content: r.FormValue("content"),
    }

    if !msg.Validate() {
        render(w, "templates/index.html", msg)
        return
    }

    if err := msg.Deliver(); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    http.Redirect(w, r, "/confirmation", http.StatusSeeOther)
}

func confirmation(w http.ResponseWriter, r *http.Request) {
    render(w, "templates/confirmation.html", nil)
}

func render(w http.ResponseWriter, filename string, data interface{}) {
    tmpl, err := template.ParseFiles(filename)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    if err := tmpl.Execute(w, data); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

关键修改说明:

  1. 导入移除:删除了 github.com/bmizerany/pat 导入。
  2. 路由器初始化:使用 http.NewServeMux() 创建标准路由器。
  3. 路由注册
    • 使用 mux.HandleFunc("/", handleIndexAndSend) 处理根路径的 GET 和 POST 请求。
    • 使用 mux.HandleFunc("/confirmation", confirmation) 处理确认页面。
  4. 方法处理:在 handleIndexAndSend 函数中,通过 r.Method 检查请求方法,分别调用 index(GET)或 send(POST)函数。对于不支持的 HTTP 方法,返回 405 Method Not Allowed 错误。

此修改保持了原有功能,同时移除了对第三方 pat 库的依赖。确保您的 Message 结构体和相关方法(如 ValidateDeliver)在代码中正确定义。

回到顶部