-
gorm 操作數據庫,類似java中的mybatis
查看全部 -
defer 延遲
讓程序其他邏輯先執行,defer定義的邏輯最后執行
recover? 恢復
只在defer函數中有效
panic? 恐慌
程序執行到panic的時候自動崩潰
示例:
defer func(){
????if err := recover(); err !=nil{
????????fmt.Println("捕獲異常:", err)
????}
}()
defer fmt.Println(1)
defer fmt.Println(2)
panic("程序異常,這里主動崩潰中斷")
查看全部 -
1、獲取url中的參數
在路由里修改路徑 /user/:id? ?,然后再controller里面 id := c.Param("id") ,最后就可以取到參數啦
2、獲取post請求中表單的參數
直接在controller里面獲取? cid := c.PostForm("cid")
還有一種是可以設置默認值的? name := c.DefaultPostForm("name", "no people")
3、獲取請求中以json封裝的參數
3.1 、直接獲取
param := make(map[string]interface{})
err := c.BindJSON(¶m)
if err== nil {
????Success(c, 200, param["name"], param["cid"], 1)
????return
}
Error(c, 500)
3.2、通過封裝結構體方式
type Search struct{
????Name string `json:"name"`
????Cid? ? ? int? ? ? `json:"cid"`
}
search := & Search{}
err := c.BindJSON(&search)
if err==nil {
????Success(c, 200, searche.Name, search.Cid, 1)
????return
}
Error(c, 500)
查看全部 -
用結構體 struct 定義返回的json格式
type JsonStruct struct{
????Code int 'json:"code"'
????Msg interface{} 'json:"msg"'? ? ? //類型不確定用interface
????Data interface{} 'json:"data"'
????Count int64 'json:"count"'
}
//成功返回的json結構
func Success(c *gin.Context, code int, msg interface{}, data interface{}, count int64){
????json := &JsonStruct{Code: code, Msg: msg, Data: data, Count: count}
????c.json(200, json)
}
查看全部 -
r.GET("/user/list", func(ctx *gin.Context){
? ? //這里的func是用來處理路由請求成功后的業務邏輯
? ? ctx.String(http.StatusOK, "查詢成功")
})
路由分組:將同一類路由放到一起
user := r.Group("/user")
{
????user.POST("/list", func(ctx *gin.Context){
????????ctx.String(http.StatusOK, "查到user? list")
????})
????user.PUT("/add", func(ctx *gin.Context){
????????ctx.String(http.StatusOK,? "添加用戶成功")
????})
}
查看全部 -
Gin里面管GET POST? 等叫路由??!
查看全部 -
main 入口包,一個系統只有一個main
go run hello.go
go build hello.go? ?//編譯成可執行文件,上線的時候只有執行該可執行文件就可以了
查看全部 -
這塊需要結合官方最新文檔寫。
和視頻中的版本略有差異
這里貼出我的
gorm.io/driver/mysql v1.5.7
gorm.io/gorm v1.25.12?package?dao import?( ????"go-ranking/config" ????"go-ranking/pkg/logger" ????"gorm.io/driver/mysql" ????"gorm.io/gorm" ????"time" ) var?( ????Db??*gorm.DB ????err?error ) func?init()?{ ????Db,?err?=?gorm.Open(mysql.Open(config.Mysqldb),?&gorm.Config{}) ????//?-----------------------?Connection?Pool?Settings?----------------------- ????//?SetMaxIdleConns?sets?the?maximum?number?of?connections?in?the?idle?connection?pool. ????sqlDB,?err?:=?Db.DB() ????if?err?!=?nil?{ ???????logger.Error(map[string]interface{}{"database?error":?err.Error()}) ???????return ????} ????sqlDB.SetMaxIdleConns(10) ????//?SetMaxOpenConns?sets?the?maximum?number?of?open?connections?to?the?database. ????sqlDB.SetMaxOpenConns(100) ????//?SetConnMaxLifetime?sets?the?maximum?amount?of?time?a?connection?may?be?reused. ????sqlDB.SetConnMaxLifetime(time.Hour) }
查看全部 -
安 gorm依賴?
go?get?-u?gorm.io/gorm
安裝 mysql驅動
go?get?-u?gorm.io/driver/mysql
查看全部 -
package?main import?( ????"fmt" ) func?main()?{ ????fmt.Println("程序開始") ????safeFunction() ????fmt.Println("程序繼續運行...") } func?safeFunction()?{ ????defer?func()?{ ????????if?r?:=?recover();?r?!=?nil?{?//?捕獲?panic ????????????fmt.Println("捕獲到異常:",?r) ????????} ????}() ???? ????fmt.Println("執行函數") ????panic("觸發異常")??//?觸發?panic,程序中斷 ????fmt.Println("這行代碼不會執行") }
查看全部 -
思考:這里?err?:=?context.BindJSON(&parms)?可以寫成?err?:=?context.BindJSON(parms)?嗎? /* ????答:不可以寫成?err?:=?context.BindJSON(parms),因為?BindJSON?需要一個指針類型的參數,即傳入的參數必須是指向接收數據的變量的指針。 ????在?err?:=?context.BindJSON(&parms)?中,&parms?是?parms?的指針,指向這個?map,所以?BindJSON?可以直接修改?parms?的內容,將請求中的?JSON?數據解析并賦值到?parms?中。如果寫成?context.BindJSON(parms),則傳入的是?map?值的副本,BindJSON?將無法正確解析并賦值給?parms。 ????為什么?BindJSON?需要指針? ????BindJSON?的參數類型是?interface{},在?Go?中,如果要通過一個函數修改參數的內容,必須傳遞指針,這樣函數才能直接操作參數的內存地址,進而修改參數的值。否則,如果傳遞的是值類型,Go?語言會復制該值,導致函數內對該副本的修改不會影響到原始變量。 ????示例對比 ????以下是對比: ????正確寫法 ????parms?:=?make(map[string]interface{}) ????err?:=?context.BindJSON(&parms)??//?傳入指針 ????//?解析后?parms?中將包含?JSON?數據 ????錯誤寫法 ????parms?:=?make(map[string]interface{}) ????err?:=?context.BindJSON(parms)??//?傳入值,解析無法修改?parms?內容 ????//?解析不會修改?parms?的內容 ????小結 ????總之,context.BindJSON?需要一個指針類型的參數,因此必須使用?&parms。 */ func?(o?OrderControllerStruct)?CreateOrder(context?*gin.Context)?{ ????//name?:=?context.PostForm("name") ????//price?:=?context.PostForm("price") ????//?使用map接受json?數據 ????parms?:=?make(map[string]interface{}) ????//使用?Gin?的?BindJSON?方法解析?JSON?數據并將其綁定到?parms ????//?思考?這里?err?:=?context.BindJSON(&parms)?可以寫成?err?:=?context.BindJSON(parms)?嗎? ????//?不可以。 ????err?:=?context.BindJSON(&parms) ????if?err?==?nil?{ ???????common.Succeed(1,?context,?parms,?10,?"訂單創建成功") ????} ????//common.Succeed(1,?context,?name,?10,?price) }
查看全部 -
簡單示例 func?(o?OrderControllerStruct)?CreateOrder(context?*gin.Context)?{ ????name?:=?context.PostForm("name") ????price?:=?context.PostForm("price") ????common.Succeed(1,?context,?name,?10,?price) }
curl?--location?'http://127.0.0.1:9999/order/create'?\ --form?'name="小蛋糕"'?\ --form?'price="100.00"'
查看全部 -
package?controller import?( ????"github.com/gin-gonic/gin" ????"go-ranking/common" ) type?UserControllerStruct?struct?{ } func?(u?UserControllerStruct)?GetUserInfo(c?*gin.Context)?{ ????common.Failed(4004,?c,?"沒有相關信息") } func?(u?UserControllerStruct)?CreateUser(context?*gin.Context)?{ ????common.Succeed(1,?context,?nil,?1,?"創建成功") } func?(u?UserControllerStruct)?DelUser(context?*gin.Context)?{ ????common.Succeed(1,?context,?nil,?1,?"刪除成功") } func?(u?UserControllerStruct)?UpdateUser(context?*gin.Context)?{ ????common.Failed(0,?context,?"刪除失敗") }
package?router import?( ????"github.com/gin-gonic/gin" ????"go-ranking/controller" ) //?Router?路由,這里方法名要大寫,因為要導出出去,在別的包里使用 func?Router()?*gin.Engine?{ ????r?:=?gin.Default() ????userGroup?:=?r.Group("/user") ????//?注意這里,他們不是一起的。 ????{ ???????userGroup.GET("/info",?controller.UserControllerStruct{}.GetUserInfo) ???????//userGroup.GET("/list",?func(c?*gin.Context)?{ ???????//?c.JSON(http.StatusOK,?gin.H{"message":?"list"}) ???????//}) ???????userGroup.GET("/create",?controller.UserControllerStruct{}.CreateUser) ???????//userGroup.DELETE("/delete",?controller.DelUser) ???????userGroup.GET("/delete",?controller.UserControllerStruct{}.DelUser) ???????userGroup.PUT("/put",?controller.UserControllerStruct{}.UpdateUser) ????} ????return?r }
package?common import?( ????"github.com/gin-gonic/gin" ????"net/http" ) //?json返回的數據結構 type?JsonStruct?struct?{ ????Code??int?????????`json:"code"` ????Data??interface{}?`json:"data"` ????Count?int64???????`json:"count"` ????Msg???interface{}?`json:"msg"` } type?ErrorStruct?struct?{ ????Code?int?????????`json:"code"` ????Msg??interface{}?`json:"msg"` } func?Succeed(code?int,?c?*gin.Context,?data?interface{},?count?int64,?msg?interface{})?{ ????json?:=?&JsonStruct{code,?data,?count,?msg} ????c.JSON(http.StatusOK,?json) } func?Failed(code?int,?c?*gin.Context,?msg?interface{})?{ ????json?:=?&ErrorStruct{code,?msg} ????c.JSON(http.StatusOK,?json) } //func?Demo(code?int,?c?*gin.Context,?msg?interface{})?{ //??json?:=?&JsonStruct{Code:?code,?Msg:?msg} //??c.JSON(http.StatusOK,?json) //} /** 補充一個?關于?類型的值實例?和?類型的指針實例?區別、 &JsonStruct{}?和?JsonStruct{}?在?Go?中的區別在于它們的內存分配和類型。 ????1.?JsonStruct{}:表示創建一個?JsonStruct?類型的值實例。 ???????直接使用?JsonStruct{}?會在棧上分配一個?JsonStruct?類型的值,表示這個結構體的值本身。 ???????當你使用?JsonStruct{}?時,得到的是一個結構體的副本。 ????2.?&JsonStruct{}:表示創建一個?JsonStruct?類型的指針實例。 ???????使用?&JsonStruct{}?會在堆上分配結構體值并返回一個指向該值的指針(類型為?*JsonStruct)。 ???????返回的指針允許你直接修改結構體字段,而不會產生副本。 示例 假設有以下?JsonStruct?結構體: type?JsonStruct?struct?{ ????Code?int ????Msg??string } 然后我們來對比兩種創建方式的不同: //?創建一個?JsonStruct?值實例 jsonValue?:=?JsonStruct{Code:?200,?Msg:?"Success"} //?創建一個?JsonStruct?指針實例 jsonPointer?:=?&JsonStruct{Code:?200,?Msg:?"Success"} 使用場景 ???????值實例?(JsonStruct{}): ???????適合在不需要對原始數據進行修改或傳遞副本時使用。 ???????不適合處理大量數據,因為每次傳遞時都會復制結構體的數據。 ???????指針實例?(&JsonStruct{}): ???????適合在需要修改結構體字段,或在函數中傳遞以節省內存時使用。 ???????對于較大結構體,指針實例更高效,因為不需要復制整個結構體。 示例:在函數中傳遞 func?modifyValue(js?JsonStruct)?{ ????js.Code?=?500?//?只會修改副本 } func?modifyPointer(js?*JsonStruct)?{ ????js.Code?=?500?//?修改指針所指向的原始數據 } func?main()?{ ????jsValue?:=?JsonStruct{Code:?200,?Msg:?"Original"} ????modifyValue(jsValue) ????fmt.Println(jsValue.Code)?//?輸出:?200?(未修改) ????jsPointer?:=?&JsonStruct{Code:?200,?Msg:?"Original"} ????modifyPointer(jsPointer) ????fmt.Println(jsPointer.Code)?//?輸出:?500?(已修改) } 總結 ???????JsonStruct{}:創建結構體的值實例,每次使用時生成一個副本。 ???????&JsonStruct{}:創建結構體的指針實例,直接操作原始數據,更節省內存。 */
查看全部 -
package?common import?( ????"github.com/gin-gonic/gin" ????"net/http" ) //?json返回的數據結構 type?JsonStruct?struct?{ ????Code??int?????????`json:"code"` ????Data??interface{}?`json:"data"` ????Count?int64???????`json:"count"` ????Msg???interface{}?`json:"msg"` } func?Succeed(code?int,?c?*gin.Context,?data?interface{},?count?int64,?msg?interface{})?{ ????json?:=?&JsonStruct{code,?data,?count,?msg} ????c.JSON(http.StatusOK,?json) } func?failed(code?int,?c?*gin.Context,?msg?interface{})?{ ????json?:=?&JsonStruct{Code:?code,?Msg:?msg} ????c.JSON(http.StatusOK,?json) } /** 補充一個?關于?類型的值實例?和?類型的指針實例?區別、 &JsonStruct{}?和?JsonStruct{}?在?Go?中的區別在于它們的內存分配和類型。 ????1.?JsonStruct{}:表示創建一個?JsonStruct?類型的值實例。 ???????直接使用?JsonStruct{}?會在棧上分配一個?JsonStruct?類型的值,表示這個結構體的值本身。 ???????當你使用?JsonStruct{}?時,得到的是一個結構體的副本。 ????2.?&JsonStruct{}:表示創建一個?JsonStruct?類型的指針實例。 ???????使用?&JsonStruct{}?會在堆上分配結構體值并返回一個指向該值的指針(類型為?*JsonStruct)。 ???????返回的指針允許你直接修改結構體字段,而不會產生副本。 示例 假設有以下?JsonStruct?結構體: type?JsonStruct?struct?{ ????Code?int ????Msg??string } 然后我們來對比兩種創建方式的不同: //?創建一個?JsonStruct?值實例 jsonValue?:=?JsonStruct{Code:?200,?Msg:?"Success"} //?創建一個?JsonStruct?指針實例 jsonPointer?:=?&JsonStruct{Code:?200,?Msg:?"Success"} 使用場景 ???????值實例?(JsonStruct{}): ???????適合在不需要對原始數據進行修改或傳遞副本時使用。 ???????不適合處理大量數據,因為每次傳遞時都會復制結構體的數據。 ???????指針實例?(&JsonStruct{}): ???????適合在需要修改結構體字段,或在函數中傳遞以節省內存時使用。 ???????對于較大結構體,指針實例更高效,因為不需要復制整個結構體。 示例:在函數中傳遞 func?modifyValue(js?JsonStruct)?{ ????js.Code?=?500?//?只會修改副本 } func?modifyPointer(js?*JsonStruct)?{ ????js.Code?=?500?//?修改指針所指向的原始數據 } func?main()?{ ????jsValue?:=?JsonStruct{Code:?200,?Msg:?"Original"} ????modifyValue(jsValue) ????fmt.Println(jsValue.Code)?//?輸出:?200?(未修改) ????jsPointer?:=?&JsonStruct{Code:?200,?Msg:?"Original"} ????modifyPointer(jsPointer) ????fmt.Println(jsPointer.Code)?//?輸出:?500?(已修改) } 總結 ???????JsonStruct{}:創建結構體的值實例,每次使用時生成一個副本。 ???????&JsonStruct{}:創建結構體的指針實例,直接操作原始數據,更節省內存。 */
查看全部 -
package?main import?( ????"go-ranking/router" ) func?main()?{ ????r?:=?router.Router() ???? ????r.Run(":9999") }
package?router import?( ????"github.com/gin-gonic/gin" ????"net/http" ) //?Router?路由,這里方法名要大寫,因為要導出出去,在別的包里使用 func?Router()?*gin.Engine?{ ????r?:=?gin.Default() ????userGroup?:=?r.Group("/user") ????//?注意這里,他們不是一起的。 ????{ ???????userGroup.GET("/list",?func(c?*gin.Context)?{ ??????????c.JSON(http.StatusOK,?gin.H{"message":?"list"}) ???????}) ???????userGroup.POST("/create",?func(c?*gin.Context)?{ ??????????c.JSON(http.StatusOK,?gin.H{"message":?"create"}) ???????}) ???????userGroup.DELETE("/delete",?func(c?*gin.Context)?{ ??????????c.JSON(http.StatusOK,?gin.H{"message":?"delete"}) ???????}) ???????userGroup.PATCH("/patch",?func(c?*gin.Context)?{ ??????????c.JSON(http.StatusOK,?gin.H{"message":?"patch?"}) ???????}) ???????userGroup.PUT("/put",?func(c?*gin.Context)?{ ??????????c.JSON(http.StatusOK,?gin.H{"message":?"put?"}) ???????}) ????} ????return?r }
對核心代碼做一些解釋
? 函數聲明:
? func Router() 表示定義一個名為 Router 的函數。
? 返回值 *gin.Engine 表示這個函數返回一個指向 gin.Engine 實例的指針,gin.Engine 是 Gin 框架的核心路由器。
? *gin.Engine:
? gin.Engine 是 Gin 的核心類型,代表整個 HTTP 路由器和中間件系統。
? 通過 gin.Engine 實例,可以定義應用的路由、請求處理邏輯、中間件等。
查看全部 -
還是比較有幫助的,點個贊
查看全部 -
defer:延遲執行,先defer的后執行
panic 程序直接終止
recover在defer中執行,讓程序恢復正常的狀態去執行
查看全部 -
3-4章節大綱課后復習大綱
如何獲取get方式xxx?id=xxx&name=xxx中的id和name
如何獲取post方式請求的body中的表單對象
如何獲取post方式請求的body中的json對象(map和結構體兩種方式獲取)
查看全部 -
記錄一下,很有幫助
查看全部 -
66666666666666
查看全部 -
產品經理不一定要有獨立編碼能力,但是適當了解一些技術原理,不至于提出“App的主題顏色根據手機外殼的顏色來自動調整”的這種需求了解一些常用的專業技術術語,可以更好的和程序員溝通協作,當程序員討論構建某個功能時,咱們至少要能聽懂他們在講什么,問題出在哪里。
一、懂技術的產品經理有三大優勢
1. 懂技術的產品經理,和開發的溝通更順暢
聽得懂技術專業術語,明白技術實現原理,在傳遞需求時更容易讓技術同學理解,達成共識。
撰寫PRD或需求評審時,知道技術關心什么,對技術細節的闡述更加到位全面。
線上有異常時,快速定位問題范圍,找到相應的技術同事,加速問題的修復。
查看全部 -
記錄下來
查看全部 -
還可以
查看全部 -
不錯
查看全部 -
1
查看全部
舉報