【go項目01_學習記錄15】

重構MVC

  • 1 Article 模型
    • 1.1 首先創建 Article 模型文件
    • 1.2 接下來創建獲取文章的方法
    • 1.3 新增 types.StringToUint64()函數
    • 1.4 修改控制器的調用
    • 1.5 重構 route 包
    • 1.6 通過 SetRoute 來傳參對象變量
    • 1.7 新增方法:
    • 1.8 控制器將 Int64ToString 改為 Uint64ToString
    • 1.9 模板里修改 Int64ToString 為 Uint64ToString:
    • 1.10 修改logger:
    • 1.11 修改articles_controller.go的判斷:
  • 2 重構文章列表
    • 2.1 移動articles.index路由
    • 2.2 添加Index控制器方法
    • 2.3 獲取文章列表 GetAll
    • 2.4 調試程序
    • 2.5 代碼版本標記

1 Article 模型

解決undefined: getArticleByID 的報錯

config := mysql.New(mysql.Config{DSN: "root:secret@tcp(127.0.0.1:3306)/goblog?charset=utf8&parseTime=True&loc=Local",})

在提供的代碼中,用戶名是"root",密碼是"secret"。這段代碼中的DSN(Data Source Name)參數指定了數據庫連接的信息,其中"root"是用戶名,“secret"是密碼。所以,根據這段代碼,用戶是"root”,密碼是"secret"。

1.1 首先創建 Article 模型文件

app/models/article/article.go

// Package article 應用的文章模型
package article// Article 文章模型
type Article struct {ID    uint64 Title stringBody  string
}

1.2 接下來創建獲取文章的方法

app/models/article/crud.go

package articleimport ("goblog/pkg/model""goblog/pkg/types"
)// Get 通過 ID 獲取文章
func Get(idstr string) (Article, error) {var article Articleid := types.StringToUint64(idstr)if err := model.DB.First(&article, id).Error; err != nil {return article, err}return article, nil
}

First() 是 gorm.DB 提供的用以從結果集中獲取第一條數據的查詢方法,.Error 是 GORM 的錯誤處理機制。與常見的 Go 代碼不同,因 GORM 提供的是鏈式 API,如果遇到任何錯誤,GORM 會設置 *gorm.DB 的 Error 字段。

1.3 新增 types.StringToUint64()函數

pkg/types/converter.go

.
.
.// StringToUint64 將字符串轉換為 uint64
func StringToUint64(str string) uint64 {i, err := strconv.ParseUint(str, 10, 64)if err != nil {logger.LogError(err)}return i
}

1.4 修改控制器的調用

app/http/controllers/articles_controller.go

.
.
.// Show 文章詳情頁面
func (*ArticlesController) Show(w http.ResponseWriter, r *http.Request) {...// 2. 讀取對應的文章數據article, err := article.Get(id)...
}

1.5 重構 route 包

pkg/route/router.go

// Package route 路由相關
package routeimport ("goblog/pkg/logger""net/http""github.com/gorilla/mux"
)var route *mux.Router// SetRoute 設置路由實例,以供 Name2URL 等函數使用
func SetRoute(r *mux.Router) {route = r
}// Name2URL 通過路由名稱來獲取 URL
func Name2URL(routeName string, pairs ...string) string {url, err := route.Get(routeName).URL(pairs...)if err != nil {logger.LogError(err)return ""}return url.String()
}
.
.
.

1.6 通過 SetRoute 來傳參對象變量

bootstrap/route.go

.
.
.
// SetupRoute 路由初始化
func SetupRoute() *mux.Router {router := mux.NewRouter()routes.RegisterWebRoutes(router)route.SetRoute(router)return router
}

1.7 新增方法:

pkg/types/converter.go

.
.
.// Uint64ToString 將 uint64 轉換為 string
func Uint64ToString(num uint64) string {return strconv.FormatUint(num, 10)
}

1.8 控制器將 Int64ToString 改為 Uint64ToString

app/http/controllers/articles_controller.go

.
.
.
// Show 文章詳情頁面
func (*ArticlesController) Show(w http.ResponseWriter, r *http.Request) {...} else {// 4. 讀取成功,顯示文章tmpl, err := template.New("show.gohtml").Funcs(template.FuncMap{"RouteName2URL":  route.Name2URL,"Uint64ToString": types.Uint64ToString,}).

1.9 模板里修改 Int64ToString 為 Uint64ToString:

resources/views/articles/show.gohtml

    {{/* 構建刪除按鈕  */}}{{ $idString := Uint64ToString .ID  }}<form action="{{ RouteName2URL "articles.delete" "id" $idString }}" method="post"><button type="submit" onclick="return confirm('刪除動作不可逆,請確定是否繼續')">刪除</button></form>

瀏覽 localhost:3000/articles/3 ,顯示:
在這里插入圖片描述

訪問localhost:3000/articles/1000,顯示拒絕訪問

1.10 修改logger:

pkg/logger/logger.go

// Package logger 日志相關
package loggerimport "log"// LogError 當存在錯誤時記錄日志
func LogError(err error) {if err != nil {log.Println(err)}
}

1.11 修改articles_controller.go的判斷:

GORM 有單獨的錯誤類型 —— gorm.ErrRecordNotFound
app/http/controllers/articles_controller.go

.
.
.// Show 文章詳情頁面
func (*ArticlesController) Show(w http.ResponseWriter, r *http.Request) {...// 3. 如果出現錯誤if err != nil {if err == gorm.ErrRecordNotFound { // <---- 這一行// 3.1 數據未找到...} else {// 3.2 數據庫錯誤...}} else {// 4. 讀取成功,顯示文章...}
}

再次訪問localhost:3000/articles/521
在這里插入圖片描述

2 重構文章列表

2.1 移動articles.index路由

把 main.go 里的articles.index路由剪切到 web.go 中,并簡單修改
routes/web.go

.
.
.
func  RegisterWebRoutes(r *mux.Router) {...r.HandleFunc("/articles", ac.Index).Methods("GET").Name("articles.index")
}

2.2 添加Index控制器方法

將 main.go 中 articlesIndexHandler 函數剪切并修改名稱到控制器中:

app/http/controllers/articles_controller.go

// Index 文章列表頁
func (*ArticlesController) Index(w http.ResponseWriter, r *http.Request) {// 1. 獲取結果集articles, err := article.GetAll()if err != nil {// 數據庫錯誤logger.LogError(err)w.WriteHeader(http.StatusInternalServerError)fmt.Fprint(w, "500 服務器內部錯誤")} else {// 2. 加載模板tmpl, err := template.ParseFiles("resources/views/articles/index.gohtml")logger.LogError(err)// 3. 渲染模板,將所有文章的數據傳輸進去err = tmpl.Execute(w, articles)logger.LogError(err)}
}

2.3 獲取文章列表 GetAll

獲取文章列表封裝到模型的 GetAll 方法里:

app/models/article/crud.go

// GetAll 獲取全部文章
func GetAll() ([]Article, error) {var articles []Articleif err := model.DB.Find(&articles).Error; err != nil {return articles, err}return articles, nil
}

上面兩個步驟的代碼的功能與下面代碼一樣:

// 1. 執行查詢語句,返回一個結果集
rows, err := db.Query("SELECT * from articles")
logger.LogError(err)
defer rows.Close()var articles []Article
//2. 循環讀取結果
for rows.Next() {var article Article// 2.1 掃碼每一行的結果并賦值到一個 article 對象中err := rows.Scan(&article.ID, &article.Title, &article.Body)logger.LogError(err)// 2.2 將 article 追加到 articles 的這個數組中articles = append(articles, article)
}
// 2.3 檢測循環時是否發生錯誤
err = rows.Err()
logger.LogError(err)

GORM 的優勢之一:不需要時刻記住關閉連接
訪問 localhost:3000/articles :
在這里插入圖片描述
沒有顯示數據

2.4 調試程序

GORM 提供了一個調試功能,允許在命令行里查看請求的 SQL 信息,config里面設置:

pkg/model/model.go

// Package model 應用模型數據層
package modelimport ("goblog/pkg/logger""gorm.io/gorm"gormlogger "gorm.io/gorm/logger"// GORM 的 MSYQL 數據庫驅動導入"gorm.io/driver/mysql"
)// DB gorm.DB 對象
var DB *gorm.DB// ConnectDB 初始化模型
func ConnectDB() *gorm.DB {var err errorconfig := mysql.New(mysql.Config{DSN: "root:secret@tcp(127.0.0.1:3306)/goblog?charset=utf8&parseTime=True&loc=Local",})// 準備數據庫連接池DB, err = gorm.Open(config, &gorm.Config{Logger: gormlogger.Default.LogMode(gormlogger.Info),})logger.LogError(err)return DB
}

頂部的 import 語句,導入 gorm/logger 時,因 goblog/pkg/logger 名稱沖突,故為其指定名稱:
gormlogger “gorm.io/gorm/logger”
在這里插入圖片描述
刷新 localhost:3000/articles 頁面
在這里插入圖片描述
[rows:3] 意味著從數據庫了成功取出了三條數據。

試著在控制器里打印一下 articles 變量:
app/http/controllers/articles_controller.go

.
.
.
// Index 文章列表頁
func (*ArticlesController) Index(w http.ResponseWriter, r *http.Request) {// 1. 獲取結果集articles, err := article.GetAll()fmt.Println("文章數據", articles)...
}

刷新 localhost:3000/articles 頁面,觀察命令行:
在這里插入圖片描述
經調試,數據沒問題,模板index.gohtml的問題
resources/views/articles/index.gohtml查看模板

<!DOCTYPE html>
<html lang="en">
<head><title>所有文章 —— 我的技術博客</title><style type="text/css">.error {color: red;}</style>
</head>
<body><h1>所有文章</h1><ul>{{ range $key, $article := . }}<li><a href="{{ $article.Link }}"><strong>{{ $article.ID }}</strong>: {{ $article.Title }}</a></li>{{ end }}</ul>
</body>
</html>

$article.Link 這是一個對象方法,還未創建,將 main 里的對應方法移動到模型中,并簡單修改:
app/models/article/article.go

.
.
.
// Link 方法用來生成文章鏈接
func (article Article) Link() string {return route.Name2URL("articles.show", "id", strconv.FormatUint(article.ID, 10))
}

刷新 localhost:3000/articles 頁面
在這里插入圖片描述
問題解決,清理剛才調試的內容:

  1. 刪除 fmt.Println(“文章數據”, articles)
  2. 設置日志級別為Warn即可,pkg/model/model.go 中設置為Logger: gormlogger.Default.LogMode(gormlogger.Warn)
  3. 刪除main.go中的 articlesIndexHandler 和 Link 這兩個函數

2.5 代碼版本標記

git add .
git commit -m "重構文章列表頁面"
git push  //注釋,push到遠程github上

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/13796.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/13796.shtml
英文地址,請注明出處:http://en.pswp.cn/web/13796.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【數據結構】棧和隊列的相互實現

歡迎瀏覽高耳機的博客 希望我們彼此都有更好的收獲 感謝三連支持&#xff01; 1.用棧實現隊列 當隊列中進入這些元素時&#xff0c;相應的棧1中元素出棧順序與出隊列相反&#xff0c;因此我們可以使用兩個棧來使元素的出棧順序相同&#xff1b; 通過將棧1元素出棧&#xff0c;再…

Databend 倒排索引的設計與實現

倒排索引是一種用于全文搜索的數據結構。它的主要功能是將文檔中的單詞作為索引項&#xff0c;映射到包含該單詞的文檔列表。通過倒排索引&#xff0c;可以快速準確地定位到與查詢詞相匹配的文檔列表&#xff0c;從而大幅提高查詢性能。倒排索引在搜索引擎、數據庫和信息檢索系…

matlab實現繪制煙花代碼

下面是一個簡化的示例&#xff0c;它使用MATLAB的繪圖功能來模擬煙花爆炸的視覺效果。請注意&#xff0c;這個示例是概念性的&#xff0c;并且可能需要根據您的具體需求進行調整。 % 初始化參數 num_fireworks 5; % 煙花數量 num_particles_per_firework 200; % 每個煙花…

前端 CSS 經典:3D 漸變輪播圖

前言&#xff1a;無論什么樣式的輪播圖&#xff0c;核心 JS 實現原理都差不多。所以小伙伴們&#xff0c;還是需要了解一下核心 JS 實驗原理的。 效果圖&#xff1a; 實現代碼&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta chars…

MySQL —— 復合查詢

一、基本的查詢回顧練習 前面兩章節整理了許多關于查詢用到的語句和關鍵字&#xff0c;以及MySQL的內置函數&#xff0c;我們先用一些簡單的查詢練習去回顧之前的知識 1. 前提準備 同樣是前面用到的用于測試的表格和數據&#xff0c;一張學生表和三張關于雇員信息表 雇員信息…

優化數據查詢性能:StarRocks 與 Apache Iceberg 的強強聯合

Apache Iceberg 是一種開源的表格格式&#xff0c;專為在數據湖中存儲大規模分析數據而設計。它與多種大數據生態系統組件高度兼容&#xff0c;相較于傳統的 Hive 表格格式&#xff0c;Iceberg 在設計上提供了更高的性能和更好的可擴展性。它支持 ACID 事務、Schema 演化、數據…

leetcode-設計LRU緩存結構-112

題目要求 思路 雙鏈表哈希表 代碼實現 struct Node{int key, val;Node* next;Node* pre;Node(int _key, int _val): key(_key), val(_val), next(nullptr), pre(nullptr){} };class Solution { public: unordered_map<int, Node*> hash; Node* head; Node* tail; int …

普源DHO924示波器OFFSET設置

一、簡介 示波器是電子工程師常用的測量工具之一&#xff0c;能夠直觀地顯示電路信號的波形和參數。普源DHO924是一款優秀的數字示波器&#xff0c;具有優異的性能和易用性。其中OFFSET功能可以幫助用戶調整信號的垂直位置&#xff0c;使波形更清晰易讀。本文將詳細介紹DHO924…

專注于運動控制芯片、運動控制產品研發、生產與銷售為一體的技術型芯片代理商、方案商——青牛科技

深圳市青牛科技實業有限公司,是專注于運 動控制芯片、運動控制產品研發、生產與銷售為一體的技術型 芯片代理商、方案商。現今代理了國產品牌GLOBALCHIP&#xff0c;芯谷&#xff0c;矽普&#xff0c;TOPPOWER等品牌。其中代理品牌TOPPOWER為電源模塊&#xff0c;他們公司通過了…

cherry-pick的強大之處在于哪里

git cherry-pick 的強大之處在于它提供了一種靈活的方式來應用特定的提交到不同的分支上&#xff0c;而無需合并整個分支或拉取其他不需要的提交。以下是 git cherry-pick 的幾個主要優點和強大之處&#xff1a; 選擇性應用提交&#xff1a;你可以挑選一個或多個特定的提交&…

聲音轉文本(免費工具)

聲音轉文本&#xff1a;解鎖語音技術的無限可能 在當今這個數字化時代&#xff0c;信息的傳遞方式正以前所未有的速度進化。從手動輸入到觸控操作&#xff0c;再到如今的語音交互&#xff0c;技術的發展讓溝通變得更加自然與高效。聲音轉文本&#xff08;Speech-to-Text, STT&…

Plant Simulation驗證AGV算法

Plant Simulation驗證算法也是非常高效且直觀的&#xff0c;一直以來波哥在迭代算法的時候圖形顯示這塊都是使用Openframeworks去做&#xff0c;效果還是非常不錯的。 這里簡要介紹一下openFrameworks&#xff0c;openFrameworks是一個開源的、跨平臺的 C 工具包。旨在開發實時…

LeetCode hot100-49-N

236. 二叉樹的最近公共祖先 給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。百度百科中最近公共祖先的定義為&#xff1a;“對于有根樹 T 的兩個節點 p、q&#xff0c;最近公共祖先表示為一個節點 x&#xff0c;滿足 x 是 p、q 的祖先且 x 的深度盡可能大&#xff08;…

爬蟲學習--12.MySQL數據庫的基本操作(下)

MySQL查詢數據 MySQL 數據庫使用SQL SELECT語句來查詢數據。 語法&#xff1a;在MySQL數據庫中查詢數據通用的 SELECT 語法 SELECT 字段1&#xff0c;字段2&#xff0c;……&#xff0c;字段n FROM table_name [WHERE 條件] [LIMIT N] 查詢語句中你可以使用一個或者多個表&…

uni-app項目在微信開發者工具打開時報錯[ app.json 文件內容錯誤] app.json: 在項目根目錄未找到 app.json

uni-app項目在微信開發者工具打開時報錯[ app.json 文件內容錯誤] app.json: 在項目根目錄未找到 app.json 出現這個問題是因為打開的文件地址不對&#xff0c;解決這個問題首先我們要查看是否有unpackage文件夾&#xff0c;如果有&#xff0c;項目直接指向unpackage\dist\dev\…

vue3使用mitt.js進行各種組件間通信

我們在vue工程中&#xff0c;除開vue自帶的什么父子間&#xff0c;祖孫間通信&#xff0c;還有一個非常方便的通信方式&#xff0c;類似Vue2.x 使用 EventBus 進行組件通信&#xff0c;而 Vue3.x 推薦使用 mitt.js。可以實現各個組件間的通信 優點&#xff1a;首先它足夠小&…

【云原生】Kubeadm部署k8s

目錄 一、部署步驟 二、部署kubernetes 2.1、所有節點關閉防火墻 核心防護 iptables規則 swap交換 2.2、修改主機名并添加主機映射 2.3、調整內核參數 三、安裝Docker 3.1、所有節點安裝docker 3.2、所有接點添加鏡像加速器 3.3、開啟docker、并設置開機自啟、查看狀態…

ESP32學習筆記:WS2812B驅動

WS2812B是一款貼片RGB燈。由于采用了單總線通訊&#xff0c;所以需要特別關注下它的通訊時序。 調試細節&#xff1a; 本來以為會是一個比較簡單的調試&#xff0c;結果還是花了很長時間才調試完成。 首先是關于ESP32的納秒級延時確定&#xff0c;當時按照空指令始終調試不出來…

Linux中的計劃任務(crontab)詳解

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《Linux &#xff1a;從菜鳥到飛鳥的逆襲》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、前言 1、Linux的起源與發展 2、什么是計劃任務&#xf…

超詳細的前后端實戰項目(Spring系列加上vue3)(一步步實現+源碼)前端篇(一)

最近想著一步步搭建一個前后端項目&#xff0c;將每一步詳細的做出來。&#xff08;如果有不足或者建議&#xff0c;也希望大佬們指出哦&#xff09; 前端初始化 1.根據vue腳手架創建vue項目 這里可以用很多方法創建vue項目&#xff0c;大家看著創建吧&#xff0c;只要能創建…