go語言實戰--基于Vue3+gin框架的實戰Cetide網項目(講解開發過程中的各種踩坑)

最近被要求學習go語言開發,也就做一個項目實戰鞏固一下,也分享一下關于gin框架的實戰項目

(后續應該還是會繼續學習Java,這一期還是做一個go+vue的)

經過一段時間的開發過后,感覺現在的開發效率要快不少了,爭取一天半做出個大概吧,后續再加一些功能就完工

那么就開始go的后端初始化吧;

先創建一個項目:

注意點1:先創建go.mod(這里如果不創建mod就會報錯

\testProject> go get -u github.com/gin-gonic/gin?
go: go.mod file not found in current directory or any parent directory.
? ? ? ? 'go get' is no longer supported outside a module.
? ? ? ? To build and install a command, use 'go install' with a version,
? ? ? ? like 'go install example.com/cmd@latest'
? ? ? ? For more information, see https://golang.org/doc/go-get-install-deprecation
? ? ? ? or run 'go help get' or 'go help install'.)

創建go.mod文件并加上module 和go

這下再來安裝一下gin框架,終端輸入命令


go get -u github.com/gin-gonic/gin?

吶這樣就安裝成功了

注意點2:這里如果有人會出現壓縮包損壞的情況記得要改變一下GOPROXY

這里雖然安裝成功了,但沒有被識別到,這里需要設置一下

點擊setting

點開goModule,并啟動go模塊集成就可以了

吶,這樣就好了

注意點3:如果安裝了框架卻沒有被識別,點擊setting并啟動模塊集成

前置工作差不多了,現在來初始化一下

初始化的話,先定義一下統一相應結果吧;創建一個response包并在包下創建result.go文件

這里可以定義一個統一返回結果的函數,再定義一個成功返回函數和失敗返回函數

package responseimport ("github.com/gin-gonic/gin""net/http"
)func Result(context *gin.Context, httpStatus int, code int, msg string, data gin.H) {context.JSON(httpStatus, gin.H{"code": code,"msg":  msg,"data": data,})
}func Success(context *gin.Context, msg string, data gin.H) {Result(context, http.StatusOK, 0, msg, data)
}func Fail(context *gin.Context, msg string, data gin.H) {Result(context, http.StatusOK, 1, msg, data)
}

這里我是按照寫java的習慣來定義的,也不一定很規范

定義好統一相應結果之后就可以開始定義連接數據庫相關操作,這里專門創建一個go文件來連接

創建common包,并在包下創建database文件

這里用配置文件的方式吧,那就再創建一個config包,并在包下創建application.yml包

在config包下我們規定好開啟端口號和數據庫連接信息

server:port: 8082
datasource:driverName: mysqlhost: localhostport: 3306database: go_ginusername: rootpassword: 1234charset: utf8

注意點4:使用config組件來將配置文件統一管理,這需要我們下載viper

下載命令go get github.com/spf13/viper?

然后,這里使用grom來進行數據庫相關操作

注意點5:安裝gorm: go get -u github.com/jinzhu/gorm?

那么現在來編輯一下database.go文件吧

package commonimport ("fmt""github.com/jinzhu/gorm""github.com/spf13/viper""log"
)// 初始化數據庫
func InitDB() *gorm.DB {driverName := viper.GetString("datasource.driverName")host := viper.GetString("datasource.host")port := viper.GetString("datasource.port")database := viper.GetString("datasource.database")username := viper.GetString("datasource.username")password := viper.GetString("datasource.password")charset := viper.GetString("datasource.charset")args := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=true",username, password, host, port, database, charset)db, err := gorm.Open(driverName, args)if err != nil {panic("數據庫連接失敗,err:" + err.Error())}log.Println("數據庫連接成功")return db
}// 定義方法來和獲取數據庫實例
func GetDB() *gorm.DB {return InitDB()
}

這里我們定義了兩個函數,一個用來初始化數據庫,一個用來獲取數據庫實例。

然后就可以來定義main.go文件了,在最外層創建main.go文件作為啟動文件

注意點6:剛才使用了viper庫來處理配置文件,這里需要初始化一下,需要定義一個函數

func InitConfig() {workDir, _ := os.Getwd()viper.SetConfigName("application")viper.SetConfigType("yml")viper.AddConfigPath(workDir + "/config")err := viper.ReadInConfig()if err != nil {panic(err)}
}

這里來解釋一下吧,

1.workDir, _ := os.Getwd():獲取當前工作目錄,os.Getwd()返回當前進程的工作目錄路徑,下劃線_忽略可能的錯誤。
2.viper.SetConfigName("application"):設置配置文件的名稱為application,不包括文件擴展名。
3.viper.SetConfigType("yml"):設置配置文件的類型為yaml,意味著Viper將解析.yml或.yaml格式的配置文件。
4.viper.AddConfigPath(workDir + "/config"):添加配置文件的搜索路徑,這里是當前工作目錄下的config子目錄。
5.err := viper.ReadInConfig():嘗試讀取配置文件。如果找到并成功讀取,err將為nil;否則,err將包含錯誤信息。

這個函數確保了在當前工作目錄的config子目錄下查找名為application.yml或application.yaml的配置文件,并在遇到錯誤時停止程序執行。

這樣就初始化了,

再調用一下common包下初始化數據庫的方法即可完成連接

package mainimport ("github.com/jinzhu/gorm""github.com/spf13/viper""main/common""os"
)func main() {InitConfig()db := common.GetDB()defer func(db *gorm.DB) {err := db.Close()if err != nil {panic(err)}}(db)
}
func InitConfig() {workDir, _ := os.Getwd()viper.SetConfigName("application")viper.SetConfigType("yml")viper.AddConfigPath(workDir + "/config")err := viper.ReadInConfig()if err != nil {panic(err)}
}

啊忒,缺少導入數據庫驅動

注意點7:速速安裝一個go get -u github.com/go-sql-driver/mysql

ok,安裝之后放在main.go文件下吧

_ "github.com/go-sql-driver/mysql"

注意這里的下劃線_,它表示導入包僅用于注冊驅動,而不需要直接使用包內的任何函數或類型

這樣就行了,右擊啟動!

啟動成功!

那么,麻煩的一步也就解決了,

下面就可以開始麻煩的部分了,

先定義模塊所需結構體:

創建model包,其下三包,entity,dto,vo

然后在entity包下創建user.go

package entityimport "github.com/jinzhu/gorm"type User struct {gorm.ModelName     string `gorm:"size:20;not null;unique"`Password string `gorm:"size:255;not null"`Mobile   string `gorm:"size:11;not null;unique"`Email    string `gorm:"size:50;not null;unique"`
}

代碼如上

在main方法處添加方法AutoMigrate(檢查模型結構(這里是entity.User),并根據結構體字段創建或更新相應的數據庫表結構)

那么數據庫和表結構都已經完成了,就可以開始編寫接口了

編寫路由包router

并創建routes.go文件,在文件中定義函數

package routerimport "github.com/gin-gonic/gin"func CollectionRoute(r *gin.Engine) *gin.Engine {r.POST("/user/register",)r.POST("/user/login",)r.GET("/user/info",)return r
}

先不寫具體方法,定義下來

然后回到main.go函數

通過 gin.Default() 初始化了一個默認的 Gin 路由器實例。然后,調用了 router.CollectionRoute(r) 函數,集中定義一組相關的路由規則

然后獲取config文件下的服務斷開接著run開啟即可。

那么main.go文件中要寫的也就是這些了,

接下來開始定義接口

創建controller包,并創建UserController.go文件,就在其中編寫一個注冊功能吧

package controllerimport ("github.com/gin-gonic/gin""github.com/jinzhu/gorm""golang.org/x/crypto/bcrypt""log""main/common""main/model/entity""main/response""net/http""net/mail"
)func Register(context *gin.Context) {db := common.GetDB()//獲取參數username := context.PostForm("username")password := context.PostForm("password")mobile := context.PostForm("mobile")email := context.PostForm("email")if len(username) < 5 || len(username) > 16 {response.Fail(context, "用戶名長度在5-16之間", nil)return}if len(password) < 5 || len(password) > 16 {response.Fail(context, "密碼長度在5-16之間", nil)return}if len(mobile) != 11 {response.Fail(context, "手機號長度為11位", nil)return}_, err := mail.ParseAddress(email)if err != nil {response.Fail(context, "郵箱格式不正確", nil)return}//判斷手機號是否存在if isMobileExist(db, mobile) {response.Fail(context, "手機號已存在", nil)return}if isEmailExist(db, email) {response.Fail(context, "郵箱已存在", nil)return}if isUserNameExist(db, username) {response.Fail(context, "用戶名已存在", nil)return}//都不存在則創建用戶//密碼加密hashPwd, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)if err != nil {response.Result(context, http.StatusInternalServerError, 500, "密碼加密失敗", nil)return}//創建用戶user := entity.User{Name:     username,Password: string(hashPwd),Mobile:   mobile,Email:    email,}db.Create(&user)//返回結果if user.ID != 0 {response.Success(context, "注冊成功", nil)return} else {response.Fail(context, "注冊失敗", nil)return}}func isMobileExist(db *gorm.DB, mobile string) bool {var user entity.Userdb.Where("mobile = ?", mobile).First(&user)if user.ID != 0 {log.Println("手機號已存在")return true}return false
}func isEmailExist(db *gorm.DB, email string) bool {var user entity.Userdb.Where("email = ?", email).First(&user)if user.ID != 0 {log.Println("郵箱已存在")return true}return false
}func isUserNameExist(db *gorm.DB, username string) bool {var user entity.Userdb.Where("name = ?", username).First(&user)if user.ID != 0 {log.Println("用戶名已存在")return true}return false
}

這里的代碼不太難就不細說了,主要也就是從上下文獲取到前端傳來的表單信息

先對表單的格式進行校驗,然后查詢數據庫看關鍵字段是否已經被注冊,若沒有則執行注冊

寫好之后將其添加到routes中即可

那么來測試一下吧,在main.go處打開程序,并打開postman進行檢驗

這樣就注冊成功了

后端這塊差不多都是這個流程

這里我就先不往后crud了,

題外話:

講個前后端混合的,這里以我之前做的基于前端2048小游戲為例子吧

我們先在項目目錄下創建包templates和static,

這里static包下創建js包,css包,images包分別用來存放前端的資源,然后將現有的index.html文件,css文件,js文件和images文件放入對應的包中

就像這樣:

這樣就OK了,然后在main.go文件中加載一下

func main() {InitConfig()db := common.GetDB()defer func(db *gorm.DB) {err := db.Close()if err != nil {panic(err)}}(db)db.AutoMigrate(&entity.User{})r := gin.Default()r.Static("/static", "./static")r.LoadHTMLGlob("templates/*")r = router.CollectionRoute(r)port := viper.GetString("server.port")panic(r.Run(":" + port))
}
func InitConfig() {workDir, _ := os.Getwd()viper.SetConfigName("application")viper.SetConfigType("yml")viper.AddConfigPath(workDir + "/config")err := viper.ReadInConfig()if err != nil {panic(err)}
}

OK,此時回到routes.go文件中添加

r.GET("/user/game", controller.Game)

在UserController文件下添加方法:

func Game(context *gin.Context) {context.HTML(http.StatusOK, "index.html", gin.H{"msg": "這就是CeTide的游戲!",})
}

這樣就可以了,打開main.go!

瀏覽器訪問目標地址

那么基于js制作的2048小游戲就成功呈現在瀏覽器上了,(需要2048小游戲源碼的可以去資源處下載)

emmm,這一章就分享這些吧

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

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

相關文章

傳統工科碩士想轉嵌入式,時間夠嗎?

在開始前剛好我有一些資料&#xff0c;是我根據網友給的問題精心整理了一份「嵌入式的資料從專業入門到高級教程」&#xff0c; 點個關注在評論區回復“888”之后私信回復“888”&#xff0c;全部無償共享給大家&#xff01;&#xff01;&#xff01; 零基礎開始學&#xff0…

[NOVATEK] NT96580行車記錄儀功能學習筆記(持續更新~

一、u-Boot升級燈 運行u-Boot程序時LED燈閃爍,找到運行過程中一直在運行的函數在里面進行LED引腳電平的翻轉 宏定義 Z:\SunFan\AHD580\pip\na51055_PIP\BSP\u-boot\include\configs\nvt-na51055-evb.h Z:\SunFan\AHD580\pip\na51055_PIP\BSP\u-boot\drivers\mtd\nvt_flash_…

什么是JWT(Json-Web-Token)?JWT的用途和優勢是什么?

什么是JWT&#xff08;Json-Web-Token&#xff09;&#xff1f; JWT&#xff0c;全稱JSON Web Token&#xff0c;是一種開放標準&#xff08;RFC 7519&#xff09;。它定義了一種緊湊的、自包含的方式&#xff0c;用于在各方之間安全地傳輸信息。這種信息被設計成JSON對象格式…

簡介RESTful API和中間件Web API網關

從RESTful API開始 RESTful API(Representational State Transfer API)是一種設計Web服務的架構風格,它基于REST(Representational State Transfer)理論。REST是一種軟件架構風格,由Roy Fielding在其博士論文《Architectural Styles and the Design of Network-based So…

LeetCode 550, 380, 234

目錄 550. 游戲玩法分析 IV題目鏈接表要求知識點思路代碼 380. O(1) 時間插入、刪除和獲取隨機元素題目鏈接標簽思路代碼 234. 回文鏈表題目鏈接標簽思路代碼 550. 游戲玩法分析 IV 題目鏈接 550. 游戲玩法分析 IV 表 表Activity的字段為player_id&#xff0c;device_id&am…

Linux卸載殘留MySQL【帶圖文命令巨詳細】

Linux卸載殘留MySQL 1、檢查殘留mysql2、檢查并刪除殘留mysql依賴3、檢查是否自帶mariadb庫 1、檢查殘留mysql 如果殘留mysql組件&#xff0c;使用命令 rpm -e --nodeps 殘留組件名 按順序進行移除操作 #檢查系統是否殘留過mysql rpm -qa | grep mysql2、檢查并刪除殘留mysql…

k8s——Pod容器中的存儲方式及PV、PVC

一、Pod容器中的存儲方式 需要存儲方式前提&#xff1a;容器磁盤上的文件的生命周期是短暫的&#xff0c;這就使得在容器中運行重要應用時會出現一些問題。 首先&#xff0c;當容器崩潰時&#xff0c;kubelet 會重啟它&#xff0c;但是容器中的文件將丟失——容器以干凈的狀態&…

TensorRT 精度debug分析工具

tensorRT還提供了一套可用于engine生成過程中debug的工具&#xff0c;包括Polygraphy、ONNX GraphSurgeon和PyTorch-Quantization。這些小工具用處很大&#xff0c;值得花時間進一步研究。 Debug方法示例 polygraphy Polygraphy是TensorRT官方提供的一系列小工具合集&#x…

spring源碼解析-(1)關于Bean

什么是Bean&#xff1f; 是spring對所有注入到IoC容器中的類的統稱。 我們要注冊進入spirng的bean千奇百怪&#xff0c;所以spring必須需要使用一個統一的定義來標識bean&#xff0c;就有了接下來的BeandDefinition&#xff0c;通過名稱我們就可以知道&#xff0c;他是對bean…

美國演員工會SAG-AFTRA 要求人工智能在廣告中使用演員聲音需征得同意并付費

SAG-AFTRA 的新豁免允許在人工智能生成的廣告中使用演員的聲音&#xff0c;但需要同意、補償和安全措施 美國演員工會&#xff08;SAG-AFTRA&#xff09;推出了一項新的豁免&#xff0c;以保護會員免受未經授權的人工智能在廣告中使用其聲音的影響。動態人工智能音頻廣告豁免定…

C語言Kruskal算法求最小生成樹

Kruskal算法求出最小生成樹。 圖形 算法描述 先找最小權值邊為1的邊有&#xff08;V1&#xff0c;V4&#xff09;&#xff0c;&#xff08;V2&#xff0c;V9&#xff09;&#xff0c;保證不產生回路就可以成功選擇邊 除去上一次找的邊后&#xff0c;在找權值最小的邊為2的有&a…

制作AI問答機器人:從0到1的完整指南

在數字化轉型的浪潮中&#xff0c;企業正追求更高效、智能的客戶服務解決方案。AI問答機器人以其快速響應、全天候服務和持續學習的能力&#xff0c;成為了提升客戶滿意度和加速業務發展的關鍵工具。本文將深入探討如何制作一個企業級的AI問答機器人&#xff0c;并強調其功能體…

OpenAI發表研究論文 介紹了一種逆向工程AI模型工作原理的方法

ChatGPT 開發商 OpenAI 構建人工智能的方法本周遭到了前員工的抨擊&#xff0c;他們指責該公司利用可能有害的技術冒不必要的風險。今天&#xff0c;OpenAI 發布了一篇新的研究論文&#xff0c;目的顯然是為了表明它在通過提高模型的可解釋性來應對人工智能風險方面的認真態度。…

hot100 -- 二分查找

目錄 前言 &#x1f382;搜索插入位置 &#x1f33c;搜索二維矩陣 &#x1f33c;排序數組元素第一和最后一個位置 &#x1f33c;旋轉排序數組 &#x1f4aa;旋轉排序數組中的最小值 &#x1f4aa;兩個正序數組的中位數 前言 二分算法學習_時間超限ac:0%-CSDN博客 &#…

2024年【起重機械指揮】考試及起重機械指揮新版試題

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 起重機械指揮考試考前必練&#xff01;安全生產模擬考試一點通每個月更新起重機械指揮新版試題題目及答案&#xff01;多做幾遍&#xff0c;其實通過起重機械指揮試題及解析很簡單。 1、【多選題】《中華人民共和國特…

【Androi】安卓發展歷程詳解

人不走空 &#x1f308;個人主頁&#xff1a;人不走空 &#x1f496;系列專欄&#xff1a;算法專題 ?詩詞歌賦&#xff1a;斯是陋室&#xff0c;惟吾德馨 目錄 &#x1f308;個人主頁&#xff1a;人不走空 &#x1f496;系列專欄&#xff1a;算法專題 ?詩詞歌…

git推送代碼到github拒絕推送的解決方案

這里描述一下本地推送的場景&#xff0c;首先我在碼云上建立了一個前端項目&#xff0c;進行了自己的個性化開發&#xff0c;后期在github上創建了一個一樣的項目倉庫存放代碼。使用webstorm進行代碼開發。在下面這個位置可以選擇推送的代碼位置。 選擇推送github倉庫之后&…

Python深度學習基于Tensorflow(16)基于Tensorflow的對話實例

文章目錄 基礎數據清洗數據生成詞匯表定義分詞器并制作數據集構建Transformer模型并訓練模型推理 Tensorflow 的核心就是注意力機制&#xff0c;在之前詳細的介紹過&#xff0c;具體可以看這個&#xff1a;Python深度學習基于Tensorflow&#xff08;9&#xff09;注意力機制_te…

在Java中為什么對a賦值為10,在進行a++時還是等于10呢

首先我們看這樣一組代碼 public class demo1 {public static void main(String[] args) {int a10;aa;System.out.println(a);} } 結果&#xff1a;10不是在第二步有a操作嗎&#xff1f;為什么還是10呢&#xff1f; a的執行步驟如下&#xff1a; 保存當前a的值&#xff08;即10…

websocket鏈接攜帶參數

前端創建鏈接時官方提供的構造函數 var aWebSocket new WebSocket(url, [protocols]); url&#xff1a;要連接的URL&#xff1b;這應該是WebSocket服務器將響應的URL。 protocols&#xff1a;可選&#xff1b;一個協議字符串或者一個包含協議字符串的數組。這些字符串用于指定…