Golang 语雀内容系统(1) - 简单web服务

ByteWanderer
• 阅读 571

实现功能

主要实现一个简单web服务,主要功能

  • 首页
  • 文章详情页
  • 文章列表页
  • 搜索功能

    主要知识点

  • net/http 网络包
  • html/template 模板解析
  • github.com/gorilla/mux HTTP请求多路复用器

    代码实现

完整代码参考:
https://github.com/golangtips/yuque/releases/tag/v0.0.1

  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 模板主题
  1. 启动函数

代码文件 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/, 将会看下以下页面结果
Golang 语雀内容系统(1) - 简单web服务

点赞
收藏
评论区
推荐文章
Stella981 Stella981
3年前
Python之socket编程进阶版
1.socket之简单的ssh功能2.socket之简单的ftp服务器3.socketserver的用法4.socketserver的多并发的实现1.socket实现ssh服务 1.1我们现在Windows环境下试一下ssh的功能!(https://oscimg.oschina.net/oscnet/c77879672f0
Stella981 Stella981
3年前
Python+Selenium自动化篇
本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子。0.元素定位方法主要有:id定位:find\_element\_by\_id('')name定位:find\_element\_by\_name('')class定位:find\_element\_by\_class\_name(''
Stella981 Stella981
3年前
Android零基础入门第41节:使用SimpleAdapter
  通过ArrayAdapter实现Adapter虽然简单、易用,但ArrayAdapter的功能比较有限,它的每个列表项只能给一个TextView动态填充内容。如果开发者需要实现更复杂的列表项,则可以考虑使用SimpleAdapter。!(http://si1.go2yd.com/getimage/0FtTjblBPiy)一、使用Simp
Stella981 Stella981
3年前
Nginx的反向调度功能
1.案例实现Nginx反向代理;2.反向代理的理论知识拓展.一,实验Nginx的反向代理功能 使用Nginx实现Web反向代理功能,实现如下功能:后端Web服务器两台,可以使用httpd实现Nginx采用轮询的方式调用后端Web服务器两台Web服务器的权重要求设置为不同的值最大失败次数为1,失败超时时间为
Wesley13 Wesley13
3年前
BIO和NIO
BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 NIO(事件驱动):同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动
Wesley13 Wesley13
3年前
Java 线程池原理分析
1.简介线程池可以简单看做是一组线程的集合,通过使用线程池,我们可以方便的复用线程,避免了频繁创建和销毁线程所带来的开销。在应用上,线程池可应用在后端相关服务中。比如Web服务器,数据库服务器等。以Web服务器为例,假如Web服务器会收到大量短时的HTTP请求,如果此时我们简单的为每个HTTP请求创建一个处理线程,那么服务器
Stella981 Stella981
3年前
Servlet的使用
1\.什么是Servlet      sun公司制定的一种用来扩展web服务器功能的组件规范(1)扩展web服务器功能             早期的web服务器,比如apachewebserver,iis等,只能处理静态资源的请求(即需要事先将html文件写好并保存到web服务器相应的目录下),不能处理动态资源
Wesley13 Wesley13
3年前
Java 程序动态替换 docx 模板中定制值的实现例子
项目系统中打印功能,导出word文档功能是挺常用的,本文介绍自定文档模板,程序实现模板内容中值替代的功能。模板文件template.docx !(https://oscimg.oschina.net/oscnet/fddfe774b063f795b701911f99ad581538f.png)​执行main publi
Stella981 Stella981
3年前
HTTP协议简单了解,如何简单的实现一个web服务器
其实这个协议有很多的可以分析的,然而HTTP又是最常用的协议了,于是就从这个入手吧。分析用到的工具:firefoxWSExplorer先通过一个浏览器访问http://127.0.0.1:8080(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2F127.0.0.1%3A808
Wesley13 Wesley13
3年前
JavaFX+SpringBoot+验证码功能的小型薪酬管理系统
2020.07.22更新1概述1.1简介一个简单的小型薪酬管理系统,前端JavaFX后端SpringBoot,功能倒没多少,主要精力放在了UI和前端的一些逻辑上面,后端其实做得很简单。主要功能:用户注册/登录验证码找回密码用户修改信息,修改头像
美凌格栋栋酱 美凌格栋栋酱
4个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(