Go 原生开发博客项目系列(第一篇)
项目原视频地址:www.bilibili.com/video/BV1VS…
html + css 地址:www.mszlu.com/
练手级项目教程,使用原生Go开发。
初始化项目
mkdir blog
go init mod blog
touch main.go
首页开发
http.Server
开启服务。http.HandleFunc("/" index)
注册路由。http.ListenAndServe
监听端口启动服务。
当访问 /resource
路径的时候,会加载 public/resource/
下的资源。
func main() {
server := http.Server{
Addr: "127.0.0.1:8085",
}
http.HandleFunc("/", index)
http.Handle("/resource/", http.StripPrefix("/resource/", http.FileServer(http.Dir("public/resource/"))))
if err := server.ListenAndServe(); err != nil {
log.Println(err)
}
}
index
go
语言中的 template
库。ParseFiles
函数去解析 html
页面。
func index(w http.ResponseWriter, r *http.Request) {
var indexData IndexData
indexData.Title = "go"
t := template.New("index.html")
path, _ := os.Getwd()
indexHtml := path + "/template/index.html"
t, err := t.ParseFiles(indexHtml)
if err != nil {
log.Println(err)
}
t.Execute(w, indexData)
}
按照这个思路,需要将所有的 html 页面进行解析。这样我们的代码就变成了,下面这样。
func index(w http.ResponseWriter, r *http.Request) {
var indexData IndexData
indexData.Title = "go"
t := template.New("index.html")
path, _ := os.Getwd()
indexHtml := path + "/template/index.html"
home := path + "/template/home.html"
head := path + "/template/layout/header.html"
footer := path + "/template/layout/footer.html"
personal := path + "/template/layout/personal.html"
post := path + "/template/layout/post-list.html"
pagination := path + "/template/layout/pagination.html"
t, err := t.ParseFiles(indexHtml, home, head, footer, personal, post, pagination)
if err != nil {
log.Println(err)
}
t.Execute(w, indexData)
}
定义数据结构
blog-go/models/category.go
package models
type Category struct {
Cid int
Name string
CreateAt string
UpdateAt string
}
blog-go/models/home.go
package models
import "blog-go/config"
type HomeResponse struct {
config.Viewer
Categorys []Category
Posts []PostMore
Total int
Page int
Pages []int
PageEnd bool
}
blog-go/models/post.go
package models
import (
"blog-go/config"
"html/template"
"time"
)
type Post struct {
Pid int `json:"pid"`
Title string `json:"title"`
Slug string `json:"slug"`
Content string `json:"content"`
Markdown string `json:"markdown"`
CategoryId int `json:"categoryId"`
UserId int `json:"userId"`
ViewCount int `json:"viewCount"`
Type int `json:"type"`
CreateAt time.Time `json:"createAt"`
UpdateAt time.Time `json:"updateAt"`
}
type PostMore struct {
Pid int `json:"pid"`
Title string `json:"title"`
Slug string `json:"slug"`
Content template.HTML `json:"content"`
CategoryId int `json:"categoryId"`
CategoryName string `json:"categoryName"`
UserId int `json:"userId"`
UserName string `json:"userName"`
ViewCount int `json:"viewCount"`
Type int `json:"type"`
CreateAt string `json:"createAt"`
UpdateAt string `json:"updateAt"`
}
type PostReq struct {
Pid int `json:"pid"`
Title string `json:"title"`
Slug string `json:"slug"`
Content string `json:"content"`
Markdown string `json:"markdown"`
CategoryId int `json:"categoryId"`
UserId int `json:"userId"`
Type int `json:"type"`
}
type SearchResp struct {
Pid int `orm:"pid" json:"pid"`
Title string `orm:"title" json:"title"`
}
type PostRes struct {
config.Viewer
config.SystemConfig
Article PostMore
}
config
toml
TOML 的目标是成为一个极简的配置文件格式。TOML 被设计成可以无歧义地被映射为哈希表,从而被多种语言解析。
更多知识点,可以查看这个网站:
blog-go/config/config.toml
这里就是一些配置的数据
[viewer]
Title = "学习"
Description = "电子书学习"
Logo = "/resource/images/logo.png"
Navigation = ["首页","/", "GO语言","/golang", "归档","/pigeonhole", "关于","/about"]
juejin = "https://juejin.cn/"
Zhihu = "https://www.zhihu.com/"
Avatar = "https://cdn.pixabay.com/photo/2013/07/13/12/47/girl-160326_1280.png"
UserName = "落落子"
UserDesc = "38岁离婚带两娃"
[system]
CdnURL = "https://static.mszlu.com/goblog/es6/md-assets"
QiniuAccessKey = "替换自己的"
QiniuSecretKey = "替换自己的"
Valine = true
ValineAppid = "替换自己的"
ValineAppkey = "替换自己的"
ValineServerURL = "替换自己的"
通过 toml.DecodeFile
来解析 toml 文件。
blog-go/config/config.go
package config
import (
"github.com/BurntSushi/toml"
"log"
"os"
)
type tomlConfig struct {
Viewer Viewer
System SystemConfig
}
type Viewer struct {
Title string
Description string
Logo string
Navigation []string
juejin string
Avatar string
UserName string
UserDesc string
}
type SystemConfig struct {
AppName string
Version float32
CurrentDir string
CdnURL string
QiniuAccessKey string
QiniuSecretKey string
Valine bool
ValineAppid string
ValineAppkey string
ValineServerURL string
}
var Cfg *tomlConfig
func init() {
Cfg = new(tomlConfig)
Cfg.System.AppName = "blog"
Cfg.System.Version = 1.0
currentDir, _ := os.Getwd()
Cfg.System.CurrentDir = currentDir
_, err := toml.DecodeFile("config/config.toml", &Cfg)
if err != nil {
log.Println(err)
}
}
index 页面
为页面添加模拟数据。
package main
import (
"blog-go/config"
"blog-go/models"
"html/template"
"log"
"net/http"
"time"
)
func IsODD(num int) bool {
return num%2 == 0
}
func GetNextName(strs []string, index int) string {
return strs[index+1]
}
func Date(layout string) string {
return time.Now().Format(layout)
}
func index(w http.ResponseWriter, r *http.Request) {
// ...
t.Funcs(template.FuncMap{"isODD": IsODD, "getNextName": GetNextName, "date": Date})
// ....
var categorys = []models.Category{
{
Cid: 1,
Name: "go",
},
}
var posts = []models.PostMore{
{
Pid: 1,
Title: "go博客",
Content: "内容",
UserName: "落落子",
ViewCount: 123,
CreateAt: "2022-02-20",
CategoryId: 1,
CategoryName: "go",
Type: 0,
},
}
var homeData = &models.HomeResponse{
Viewer: config.Cfg.Viewer,
Categorys: categorys,
Posts: posts,
Total: 1,
Pages: []int{1},
PageEnd: true,
}
t.Execute(w, homeData)
}
func main() {
// ...
}
打开页面
转载自:https://juejin.cn/post/7127821468649390110