• 原生GO开发的博客系统


    Go博客实战教程,是一个练手级项目教程,使用原生Go开发,未使用任何框架。

    如何使用原生Go开发一个web项目
    循序渐进,掌握编程思维和思路
    初步具有工程思维,能适应一般的开发工作

    1. 搭建项目

    package main
    
    import (
    	"encoding/json"
    	"log"
    	"net/http"
    )
    
    type IndexData struct {
    	Title string `json:"title"`
    	Desc string `json:"desc"`
    }
    func index(w http.ResponseWriter,r *http.Request)  {
    	w.Header().Set("Content-Type","application/json")
    	var indexData IndexData
    	indexData.Title = "码神之路go博客"
    	indexData.Desc = "现在是入门教程"
    	jsonStr,_ := json.Marshal(indexData)
    	w.Write(jsonStr)
    }
    
    func main()  {
    	//程序入口,一个项目 只能有一个入口
    	//web程序,http协议 ip port
    	server := http.Server{
    		Addr: "127.0.0.1:8080",
    	}
    	http.HandleFunc("/",index)
    	if err := server.ListenAndServe();err != nil{
    		log.Println(err)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2. 响应页面

    func indexHtml(w http.ResponseWriter,r *http.Request)  {
    	t := template.New("index.html")
    	viewPath, _ := os.Getwd()
    	t,_ = t.ParseFiles(viewPath + "/template/index.html")
    	var indexData IndexData
    	indexData.Title = "码神之路go博客"
    	indexData.Desc = "现在是入门教程"
    	err := t.Execute(w,indexData)
    	fmt.Println(err)
    }
    
    func main()  {
    	//程序入口,一个项目 只能有一个入口
    	//web程序,http协议 ip port
    	server := http.Server{
    		Addr: "127.0.0.1:8080",
    	}
    	http.HandleFunc("/",index)
    	http.HandleFunc("/index.html",indexHtml)
    	if err := server.ListenAndServe();err != nil{
    		log.Println(err)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
     hello mszlu blog!!
    {{.Title}}
     {{.Desc}}
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3. 首页

    3.1 页面解析

    func index(w http.ResponseWriter,r *http.Request)  {
    	var indexData IndexData
    	indexData.Title = "码神之路go博客"
    	indexData.Desc = "现在是入门教程"
    	t := template.New("index.html")
    	//1. 拿到当前的路径
    	path,_ := os.Getwd()
    	//访问博客首页模板的时候,因为有多个模板的嵌套,解析文件的时候,需要将其涉及到的所有模板都进行解析
    	home := path + "/template/home.html"
    	header := 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,_ = t.ParseFiles(path + "/template/index.html",home,header,footer,personal,post,pagination)
    
    	//页面上涉及到的所有的数据,必须有定义
    	t.Execute(w,indexData)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.2 首页数据格式定义

    config/config.go

    package config
    
    type Viewer struct {
    	Title string
    	Description  string
    	Logo  string
    	Navigation  []string
    	Bilibili 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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    models/category.go

    package models
    
    type Category struct {
    	Cid      int
    	Name     string
    	CreateAt string
    	UpdateAt string
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    models/post.go

    package models
    
    import (
    	"goblog/config"
    	"html/template"
    	"time"
    )
    
    type Post struct {
    	Pid        int    `json:"pid"`                // 文章ID
    	Title      string `json:"title"`            // 文章ID
    	Slug       string `json:"slug"`              // 自定也页面 path
    	Content    string `json:"content"`        // 文章的html
    	Markdown   string `json:"markdown"`      // 文章的Markdown
    	CategoryId int    `json:"categoryId"` //分类id
    	UserId     int    `json:"userId"`         //用户id
    	ViewCount  int    `json:"viewCount"`   //查看次数
    	Type       int    `json:"type"`              //文章类型 0 普通,1 自定义文章
    	CreateAt   time.Time `json:"createAt"`     // 创建时间
    	UpdateAt   time.Time `json:"updateAt"`     // 更新时间
    }
    
    type PostMore struct {
    	Pid          int    `json:"pid"`                    // 文章ID
    	Title        string `json:"title"`                // 文章ID
    	Slug         string `json:"slug"`                  // 自定也页面 path
    	Content      template.HTML `json:"content"`            // 文章的html
    	CategoryId   int    `json:"categoryId"`     // 文章的Markdown
    	CategoryName string `json:"categoryName"` // 分类名
    	UserId       int    `json:"userId"`             // 用户id
    	UserName     string `json:"userName"`         // 用户名
    	ViewCount    int    `json:"viewCount"`       // 查看次数
    	Type         int    `json:"type"`                  // 文章类型 0 普通,1 自定义文章
    	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"` // 文章ID
    	Title string `orm:"title" json:"title"`
    }
    
    type PostRes struct {
    	config.Viewer
    	config.SystemConfig
    	Article PostMore
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    models/home.go

    package models
    
    
    type HomeData struct {
    	config.Viewer
    	Categorys []Category
    	Posts []PostMore
    	Total int
    	Page int
    	Pages []int
    	PageEnd bool
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4. 配置文件读取

    config.toml:

    [viewer]
        Title = "码神之路Go语言博客"
        Description = "码神之路Go语言博客"
        Logo = "/resource/images/logo.png"
        Navigation = ["首页","/", "GO语言","/golang", "归档","/pigeonhole", "关于","/about"]
        Bilibili = "https://space.bilibili.com/473844125"
        Zhihu = "https://www.zhihu.com/people/ma-shen-zhi-lu"
        Avatar = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F13147603927%2F1000.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1647242040&t=c6108010ed46b4acebe18955acdd2d24"
        UserName = "码神之路"
        UserDesc = "长得非常帅的程序员"
    [system]
        CdnURL = "https://static.mszlu.com/goblog/es6/md-assets"
        QiniuAccessKey = "替换自己的"
        QiniuSecretKey = "替换自己的"
        Valine = true
        ValineAppid = "替换自己的"
        ValineAppkey = "替换自己的"
        ValineServerURL = "替换自己的"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    package config
    
    import (
    	"github.com/BurntSushi/toml"
    	"os"
    )
    
    type TomlConfig struct {
    	Viewer Viewer
    	System SystemConfig
    }
    type Viewer struct {
    	Title string
    	Description  string
    	Logo  string
    	Navigation  []string
    	Bilibili 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)
    	var err error
    	Cfg.System.CurrentDir, err = os.Getwd()
    	if err != nil {
    		panic(err)
    	}
    	Cfg.System.AppName = "mszlu-go-blog"
    	Cfg.System.Version = 1.0
    	_,err = toml.DecodeFile("config/config.toml",&Cfg)
    	if err != nil {
    		panic(err)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    5. 假数据-显示首页内容

    package main
    
    import (
    	"html/template"
    	"log"
    	"ms-go-blog/config"
    	"ms-go-blog/models"
    	"net/http"
    	"time"
    )
    
    type IndexData struct {
    	Title string `json:"title"`
    	Desc string `json:"desc"`
    }
    
    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 := template.New("index.html")
    	//1. 拿到当前的路径
    	path := config.Cfg.System.CurrentDir
    	//访问博客首页模板的时候,因为有多个模板的嵌套,解析文件的时候,需要将其涉及到的所有模板都进行解析
    	home := path + "/template/home.html"
    	header := 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.Funcs(template.FuncMap{"isODD":IsODD,"getNextName":GetNextName,"date":Date})
    	t,err := t.ParseFiles(path + "/template/index.html",home,header,footer,personal,post,pagination)
    	if err != nil {
    		log.Println(err)
    	}
    	//页面上涉及到的所有的数据,必须有定义
    	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 hr = &models.HomeResponse{
    		config.Cfg.Viewer,
    		categorys,
    		posts,
    		1,
    		1,
    		[]int{1},
    		true,
    	}
    	t.Execute(w,hr)
    }
    
    func main()  {
    	//程序入口,一个项目 只能有一个入口
    	//web程序,http协议 ip port
    	server := http.Server{
    		Addr: "127.0.0.1:8080",
    	}
    	http.HandleFunc("/",index)
    	http.Handle("/resource/",http.StripPrefix("/resource/",http.FileServer(http.Dir("public/resource/"))))
    	if err := server.ListenAndServe();err != nil{
    		log.Println(err)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    后续内容在gitee上面: 传送门

    记得给一个start

    使用 : 直接克隆地址到自己的go项目中,浏览器访问 127.0.0.1:8080可访问

  • 相关阅读:
    基于Java实现的设备模拟器
    为什么只会编程的程序员无法成为优秀的开发者?
    在组件中显示tuku的照片
    微服务性能分析|Pyroscope 集合 Spring Cloud Pig 的实践分享
    C- ssize_t & size_t
    javaweb中的转发与重定向
    RedisInsight——redis的桌面UI工具使用实践
    tcpdump使用方法
    分布式电源接入对配电网的影响matlab程序(IEEE9节点系统算例)
    机器学习笔记 - 基于pytorch、grad-cam的计算机视觉的高级可解释人工智能
  • 原文地址:https://blog.csdn.net/qq_44139121/article/details/136337255