实现功能
主要实现一个简单web服务,主要功能
- 首页
- 文章详情页
- 文章列表页
搜索功能
主要知识点
- net/http 网络包
- html/template 模板解析
github.com/gorilla/mux HTTP请求多路复用器
代码实现
完整代码参考:
https://github.com/golangtips/yuque/releases/tag/v0.0.1
初始化目录结构
. ├── LICENSE ├── README.md ├── cmd │ └── main.go ├── go.mod ├── go.sum ├── handler │ └── post.go └── theme └── default ├── detail.html ├── home.html ├── list.html └── search.html
目录说明:
- cmd/main.go 入口函数
- handler http 处理请求处理函数
- theme 模板主题
- 启动函数
代码文件 main.go
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/golangtips/yuque/handler"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
// 文章详情页
r.Methods("GET").Path("/").HandlerFunc(handler.HomePage)
// 文章详情页
r.Methods("GET").Path("/posts/{slug:[a-zA-Z0-9.]+}").HandlerFunc(handler.PostDetail)
// 文章详情页
r.Methods("GET").Path("/posts").HandlerFunc(handler.PostList)
// 文章搜索页
r.Methods("GET").Path("/search").HandlerFunc(handler.Search)
server := &http.Server{
Handler: r,
Addr: ":8080",
WriteTimeout: 5 * time.Second,
ReadTimeout: 5 * time.Second,
}
errs := make(chan error)
// HTTP 服务
go (func() {
log.Println("启动HTTP服务")
errs <- server.ListenAndServe()
})()
// 退出信号处理
go (func() {
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
errs <- fmt.Errorf("%s", <-ch)
})()
// 退出日志
log.Println("exit", <-errs)
}
代码文件 hander/post.go
package handler
import (
"fmt"
"log"
"net/http"
"strconv"
"html/template"
"github.com/gorilla/mux"
)
// HomePage 首页
func HomePage(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("theme/default/home.html")
if err != nil {
log.Println(err)
return
}
t.Execute(w, map[string]string{
"content": "首页",
})
}
// PostDetail 文章详情页
func PostDetail(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
slug := params["slug"]
t, err := template.ParseFiles("theme/default/detail.html")
if err != nil {
log.Println(err)
return
}
t.Execute(w, map[string]string{
"content": "文章详情页" + slug,
})
}
// PostList 文章列表页
func PostList(w http.ResponseWriter, r *http.Request) {
// 分页参数
query := r.URL.Query()
page := query.Get("page")
pageSize := query.Get("pageSize")
pageInt, _ := strconv.Atoi(page)
pageSizeInt, _ := strconv.Atoi(pageSize)
if pageInt < 1 {
pageInt = 1
}
if pageSizeInt < 1 {
pageSizeInt = 10
}
t, err := template.ParseFiles("theme/default/list.html")
if err != nil {
log.Println(err)
return
}
t.Execute(w, map[string]string{
"content": fmt.Sprintf("文章列表页 page = %d pageSize = %d", pageInt, pageSizeInt),
})
}
// Search 搜索结果页
func Search(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("theme/default/search.html")
if err != nil {
log.Println(err)
return
}
t.Execute(w, map[string]string{
"content": "文章搜索页",
})
}
模板内容 detail/home/list/search.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>test</title>
</head>
<body>
<header>
<a href="/">首页</a>
<a href="/posts">文章列表页</a>
<a href="/posts/slug">文章详情页</a>
<a href="/search">文章搜索页</a>
</header>
<main>
{{ .content }}
</main>
</body>
</html>
启动 & 测试
go run cmd/main.go
打开浏览器,访问 http://localhost:8080/, 将会看下以下页面结果