{"id":99,"date":"2024-06-20T11:46:41","date_gmt":"2024-06-20T03:46:41","guid":{"rendered":"https:\/\/www.nightying.com\/?p=99"},"modified":"2024-06-26T11:26:13","modified_gmt":"2024-06-26T03:26:13","slug":"gin_frame","status":"publish","type":"post","link":"https:\/\/www.nightying.com\/index.php\/2024\/06\/20\/gin_frame\/","title":{"rendered":"Gin\u6846\u67b6\u7b14\u8bb0"},"content":{"rendered":"\n<p>\u5b89\u88c5gin\u6846\u67b6<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>go get -u github.com\/gin-gonic\/gin<\/strong><\/code><\/pre>\n\n\n\n<p>\u8fd9\u4e00\u6b65\u5982\u679c\u5b89\u88c5\u4e0d\u4e86\uff0c\u9700\u8981\u5728goland\u4e2d\u8bbe\u7f6e\u4ee3\u7406\uff0c\u542f\u7528Go\u6a21\u5757\u96c6\u6210\uff0c\u5e76\u628a\u73af\u5883\u8bbe\u7f6e\u4e3a\uff1aGOPROXY=https:\/\/goproxy.io<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"760\" height=\"352\" src=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-13.png\" alt=\"\" class=\"wp-image-101\" srcset=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-13.png 760w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-13-300x139.png 300w\" sizes=\"auto, (max-width: 760px) 100vw, 760px\" \/><\/figure>\n\n\n\n<p>\u5e76\u4e14\u8bbe\u7f6eGOPATH\uff0c\u52fe\u9009\u4e3a\u6574\u4e2aGOPATH\u7f16\u5236\u7d22\u5f15\u548c\u4f7f\u7528\u7cfb\u7edf\u73af\u5883\u4e2d\u5b9a\u4e49\u7684GOPATH<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"952\" height=\"709\" src=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-14.png\" alt=\"\" class=\"wp-image-102\" srcset=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-14.png 952w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-14-300x223.png 300w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-14-768x572.png 768w\" sizes=\"auto, (max-width: 952px) 100vw, 952px\" \/><\/figure>\n\n\n\n<p>\u8bbe\u7f6e\u5b8c\u6210\u540e\uff0c\u91cd\u542fgoland<\/p>\n\n\n\n<p>\u5bfc\u5165gin<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>import(\"github.com\/gin-gonic\/gin\")<\/strong><\/code><\/pre>\n\n\n\n<p>\u5b9e\u4f8b\u4ee3\u7801\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"<strong>github.com\/gin-gonic\/gin<\/strong>\"\n\/\/web\u56fe\u6807\nimport \"github.com\/thinkerou\/favicon\"\nfunc main(){\n    \/\/\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\n    ginServer := gin.Default()\n    \/\/\u4f7f\u7528\u56fe\u6807\uff0c\u56fe\u6807\u53ef\u4ee5\u662f\u4efb\u4f55\u56fe\u7247\n    ginServer.Use(favicon.New(\".\/favicon.ico\"))\n    \/\/\u8fde\u63a5\u6570\u636e\u5e93\u7684\u4ee3\u7801\n\n    \/\/\u8bbf\u95ee\u5730\u5740\uff0c\u5904\u7406\u8bf7\u6c42   Request Response\n    \/\/func(context *gin.Context)  \u5b9a\u4e49\u533f\u540d\u51fd\u6570\u5904\u7406\u8bf7\u6c42\uff0c\u53c2\u6570\u201ccontext\u201d\u662fGin\u6846\u67b6\u4e2d\u5c01\u88c5\u4e86HTTP\u8bf7\u6c42\u548c\u54cd\u5e94\u7684\u4e0a\u4e0b\u6587\u5bf9\u8c61\u3002\n    ginServer.GET(\"\/hello\",func(context *gin.Context){\n           context.JSON(200,gin.H{\"msg\": \"hello.world\"})\n    })\n\n    \/\/\u670d\u52a1\u5668\u7aef\u53e3\n    ginServer.Run(\":8080\")\n}<\/code><\/pre>\n\n\n\n<p>\u5b9e\u4f8b\u9875\u9762\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"357\" height=\"150\" src=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-15.png\" alt=\"\" class=\"wp-image-105\" srcset=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-15.png 357w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-15-300x126.png 300w\" sizes=\"auto, (max-width: 357px) 100vw, 357px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>RESTful API<\/strong><\/h2>\n\n\n\n<p>\u4ee5\u524d\u5199\u7f51\u7ad9<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>get \/user\npost \/create_user\npost \/update_user\npost \/delete_user<\/strong><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u4f7f\u7528RESTful API\u5199\u7f51\u7ad9<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>get \/user\npost \/user\nput \/user\ndelete \/user<\/strong><\/code><\/pre>\n\n\n\n<p>gin\u6846\u67b6\u652f\u6301RESTful API\u7684\u5f00\u53d1\u3002<\/p>\n\n\n\n<p>\u5b9e\u4f8b\u4ee3\u7801\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"github.com\/gin-gonic\/gin\"\n\/\/web\u56fe\u6807\nimport \"github.com\/thinkerou\/favicon\"\nfunc main() {\n\t\/\/\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\n\tginServer := gin.Default()\n\t\/\/\u4f7f\u7528\u56fe\u6807\uff0c\u56fe\u6807\u53ef\u4ee5\u662f\u4efb\u4f55\u56fe\u7247\n\tginServer.Use(favicon.New(\".\/favicon.ico\"))\n\t\/\/\u8fde\u63a5\u6570\u636e\u5e93\u7684\u4ee3\u7801\n\n\t\/\/\u8bbf\u95ee\u5730\u5740\uff0c\u5904\u7406\u8bf7\u6c42   Request Response\n\t\/\/func(context *gin.Context)  \u5b9a\u4e49\u533f\u540d\u51fd\u6570\u5904\u7406\u8bf7\u6c42\uff0c\u53c2\u6570\u201ccontext\u201d\u662fGin\u6846\u67b6\u4e2d\u5c01\u88c5\u4e86HTTP\u8bf7\u6c42\u548c\u54cd\u5e94\u7684\u4e0a\u4e0b\u6587\u5bf9\u8c61\u3002\n\tginServer.GET(\"\/hello\", func(context *gin.Context) {\n\t\tcontext.JSON(200, gin.H{\"msg\": \"hello.world\"})\n\t})\n\t\/\/Gin RestFul\u7684\u7f16\u5199\u65b9\u5f0f\n\tginServer.POST(\"\/user\", func(c *gin.Context) {\n\t\tc.JSON(200, gin.H{\"msg\": \"post,user\"})\n\t})\n\tginServer.PUT(\"\/user\")\n\tginServer.DELETE(\"\/user\")\n\t\/\/\u670d\u52a1\u5668\u7aef\u53e3\n\tginServer.Run(\":8080\")\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"852\" height=\"548\" src=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-16.png\" alt=\"\" class=\"wp-image-114\" srcset=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-16.png 852w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-16-300x193.png 300w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-16-768x494.png 768w\" sizes=\"auto, (max-width: 852px) 100vw, 852px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u52a0\u8f7d\u9759\u6001\u9875\u9762<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport (\n\t\"github.com\/gin-gonic\/gin\"\n\t\"net\/http\"\n)\n\/\/web\u56fe\u6807\nimport \"github.com\/thinkerou\/favicon\"\nfunc main() {\n\t\/\/\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\n\tginServer := gin.Default()\n\t\/\/\u4f7f\u7528\u56fe\u6807\uff0c\u56fe\u6807\u53ef\u4ee5\u662f\u4efb\u4f55\u56fe\u7247\n\tginServer.Use(favicon.New(\".\/favicon.ico\"))\n        \n        \/\/ \u52a0\u8f7d\u8d44\u6e90\u6587\u4ef6\n        ginServer.Static(\"\/static\",\".\/static\")\n \n\t\/\/\u52a0\u8f7d\u9759\u6001\u9875\u9762\n\tginServer.LoadHTMLGlob(\"templates\/*\")\n\n\t\/\/\u54cd\u5e94\u4e00\u4e2a\u9875\u9762\u7ed9\u524d\u7aef\n\tginServer.GET(\"\/user\",func(context *gin.Context){\n\t\t\/\/context.JSON()\n\t\tcontext.HTML(http.StatusOK,\"index.html\",gin.H{\"msg\": \"\u6d4b\u8bd5\"})\n\t})\n\n\t\/\/\u8fde\u63a5\u6570\u636e\u5e93\u7684\u4ee3\u7801\n\n\t\/\/\u8bbf\u95ee\u5730\u5740\uff0c\u5904\u7406\u8bf7\u6c42   Request Response\n\t\/\/func(context *gin.Context)  \u5b9a\u4e49\u533f\u540d\u51fd\u6570\u5904\u7406\u8bf7\u6c42\uff0c\u53c2\u6570\u201ccontext\u201d\u662fGin\u6846\u67b6\u4e2d\u5c01\u88c5\u4e86HTTP\u8bf7\u6c42\u548c\u54cd\u5e94\u7684\u4e0a\u4e0b\u6587\u5bf9\u8c61\u3002\n\tginServer.GET(\"\/hello\", func(context *gin.Context) {\n\t\tcontext.JSON(200, gin.H{\"msg\": \"hello.world\"})\n\t})\n\t\/\/Gin RestFul\u7684\u7f16\u5199\u65b9\u5f0f\n\tginServer.POST(\"\/user\", func(c *gin.Context) {\n\t\tc.JSON(200, gin.H{\"msg\": \"post,user\"})\n\t})\n\tginServer.PUT(\"\/user\")\n\tginServer.DELETE(\"\/user\")\n\t\/\/\u670d\u52a1\u5668\u7aef\u53e3\n\tginServer.Run(\":8080\")\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"421\" height=\"233\" src=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-17.png\" alt=\"\" class=\"wp-image-117\" srcset=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-17.png 421w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-17-300x166.png 300w\" sizes=\"auto, (max-width: 421px) 100vw, 421px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u83b7\u53d6\u524d\u7aef\u4f20\u5165\u7684\u6570\u636e<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>package main\n\nimport (\n\t\"encoding\/json\"\n\t\"github.com\/gin-gonic\/gin\"\n\t\"net\/http\"\n)\n\n\/\/web\u56fe\u6807\nimport \"github.com\/thinkerou\/favicon\"\n\nfunc main() {\n\t\/\/\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\n\tginServer := gin.Default()\n\t\/\/\u4f7f\u7528\u56fe\u6807\uff0c\u56fe\u6807\u53ef\u4ee5\u662f\u4efb\u4f55\u56fe\u7247\n\tginServer.Use(favicon.New(\".\/8.png\"))\n\n\t\/\/ \u52a0\u8f7d\u8d44\u6e90\u6587\u4ef6\n\tginServer.Static(\"\/static\", \".\/static\")\n\n\t\/\/\u52a0\u8f7d\u9759\u6001\u9875\u9762\n\tginServer.LoadHTMLGlob(\"templates\/*\")\n\n\t\/\/\u54cd\u5e94\u4e00\u4e2a\u9875\u9762\u7ed9\u524d\u7aef\n\tginServer.GET(\"\/user\", func(context *gin.Context) {\n\t\t\/\/context.JSON()\n\t\tcontext.HTML(http.StatusOK, \"index.html\", gin.H{\"msg\": \"\u6d4b\u8bd5\"})\n\t})\n\n\t\/\/\u8fde\u63a5\u6570\u636e\u5e93\u7684\u4ee3\u7801\n\n\t\/\/\u8bbf\u95ee\u5730\u5740\uff0c\u5904\u7406\u8bf7\u6c42   Request Response\n\t\/\/func(context *gin.Context)  \u5b9a\u4e49\u533f\u540d\u51fd\u6570\u5904\u7406\u8bf7\u6c42\uff0c\u53c2\u6570\u201ccontext\u201d\u662fGin\u6846\u67b6\u4e2d\u5c01\u88c5\u4e86HTTP\u8bf7\u6c42\u548c\u54cd\u5e94\u7684\u4e0a\u4e0b\u6587\u5bf9\u8c61\u3002\n\tginServer.GET(\"\/hello\", func(context *gin.Context) {\n\t\tcontext.JSON(200, gin.H{\"msg\": \"hello.world\"})\n\t})\n\t\/\/Gin RestFul\u7684\u7f16\u5199\u65b9\u5f0f\n\tginServer.POST(\"\/user\", func(c *gin.Context) {\n\t\tc.JSON(200, gin.H{\"msg\": \"post,user\"})\n\t})\n\tginServer.PUT(\"\/user\")\n\tginServer.DELETE(\"\/user\")\n\n\t\/\/\u83b7\u53d6\u524d\u7aef\u6765\u81ea\u7684\u6570\u636e\n\tginServer.GET(\"user\/info\", func(context *gin.Context) {\n\t\tuserid := context.Query(\"userid\")\n\t\tusername := context.Query(\"username\")\n\t\tcontext.JSON(http.StatusOK, gin.H{\n\t\t\t\"userid\":   userid,\n\t\t\t\"username\": username,\n\t\t})\n\t})\n\t\/\/\u53e6\u4e00\u79cd\u65b9\u5f0f\n\tginServer.GET(\"user\/info\/:userid\/:username\", func(context *gin.Context) {\n\t\tuserid := context.Param(\"userid\")\n\t\tusername := context.Param(\"username\")\n\t\tcontext.JSON(http.StatusOK, gin.H{\n\t\t\t\"userid\":   userid,\n\t\t\t\"username\": username,\n\t\t})\n\t})\n\t\/\/POST\u4f20\u53c2json\n\tginServer.POST(\"\/json\", func(context *gin.Context) {\n\t\t\/\/request.body\n\t\t\/\/&#91;]byte\n\t\tdata, _ := context.GetRawData()\n\n\t\tvar m map&#91;string]interface{}\n\t\t\/\/ \u5305\u88c5\u4e3ajson\u6570\u636e &#91;]byte\n\t\t_ = json.Unmarshal(data, &amp;m)\n\t\tcontext.JSON(http.StatusOK, m)\n\n\t})\n\t\/\/POST\u4f20\u53c2form\n\tginServer.POST(\"\/form\/login\", func(context *gin.Context) {\n\t\tusername := context.PostForm(\"username\")\n\t\tpassword := context.PostForm(\"password\")\n\t\tcontext.JSON(http.StatusOK, gin.H{\n\t\t\t\"msg\":      \"\u767b\u5f55\u6210\u529f\",\n\t\t\t\"username\": username,\n\t\t\t\"password\": password,\n\t\t})\n\t})\n\n\t\/\/\u670d\u52a1\u5668\u7aef\u53e3\n\tginServer.Run(\":8080\")\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"527\" height=\"132\" src=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-18.png\" alt=\"\" class=\"wp-image-119\" srcset=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-18.png 527w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-18-300x75.png 300w\" sizes=\"auto, (max-width: 527px) 100vw, 527px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"496\" height=\"159\" src=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-19.png\" alt=\"\" class=\"wp-image-122\" srcset=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-19.png 496w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-19-300x96.png 300w\" sizes=\"auto, (max-width: 496px) 100vw, 496px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"413\" height=\"362\" src=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-20.png\" alt=\"\" class=\"wp-image-128\" srcset=\"https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-20.png 413w, https:\/\/www.nightying.com\/wp-content\/uploads\/2024\/06\/image-20-300x263.png 300w\" sizes=\"auto, (max-width: 413px) 100vw, 413px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u91cd\u5b9a\u5411<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>gitServer.GET(\"\/test123\",func(context *gin.Context){\n     context.Redirect(http.StatusMovedPermanently,\"https:\/\/www.nightying.com\")\n}<\/strong><\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u9519\u8bef\u9875\u9762<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>ginServer.NoRoute(func(context *gin.Context){\n   context.HTML(http.StatusNotFound,\"404.html\",nil)\n})<\/strong><\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u8def\u7531\u7ec4(\u84dd\u56fe\uff09<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>userGroup := ginServer.Group(\"\/user\")\n{\n      userGroup.GET(\"\/add\")\n      userGroup.GET(\"\/login\")\n      userGroup.GET(\"\/logout\")\n}\norder := ginServer.Group(\"\/order\")\n{\n      orderGroup.GET(\"\/add\")\n      orderGroup.DELETE(\"\/delte\")\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u62e6\u622a\u5668 &#8211; \u4e2d\u95f4\u4ef6<\/strong><\/h2>\n\n\n\n<p>(\u4e00\u822c\u7528\u4e8e\u9884\u5904\u7406\u6570\u636e\uff0c\u6bd4\u5982\u767b\u5f55\uff0c\u5206\u9875\uff0c<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>\/\/\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6 \u62e6\u622a\u5668\nfunc myHandler()(gin.HandlerFunc){\n    return func(context *gin.Context){\n       \/\/\u901a\u8fc7\u81ea\u5b9a\u4e49\u7684\u4e2d\u95f4\u4ef6\uff0c\u8bbe\u7f6e\u7684\u503c\uff0c\u5728\u540e\u7eed\u5904\u7406\u53ea\u8981\u8c03\u7528\u4e86\u8fd9\u4e2a\u4e2d\u95f4\u4ef6\u7684\u90fd\u53ef\u4ee5\u62ff\u5230\u8fd9\u91cc\u7684\u53c2\u6570\n       context.Set(\"usersesion\",\"userid-1\")\n      \n\n       context.Next()  \/\/\u653e\u884c\n       context.Abort()  \/\/\u963b\u6b62\n  }\n}\n\n\u4f7f\u7528\u65b9\u5f0f\uff1a\ngitServer.GET(\"\/user\/add\",<strong>myHandler()<\/strong>,func(context *gin.Context){\n      \/\/\u53d6\u51fa\u4e2d\u95f4\u4ef6\u7684\u503c\n      usersesion := context.MustGet(\"usersesion\").(string)\n      log.Println(userSession)\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>go\u8bed\u8a00\u591a\u7ebf\u7a0b<\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport \"fmt\"\nfunc hhh(){\n  fmt.Println(\"\u6d4b\")\n}\n\nfunc main(){\n go hhh()\n fmt.Println(\"main\")\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u9879\u76ee\u5b9e\u4f8b<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">(\u8be5\u9879\u76ee\u662fGDX_helium\u96cf\u5f62\uff09<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u9879\u76ee\u7ed3\u6784\uff1a<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>C:.\n\u2502  .gitignore    \/\/github\u4e0a\u4f20\u9650\u5236\n\u2502  buildsql.go   \/\/\u65b0\u5efa\u6570\u636e\u5e93\n\u2502  go.mod        \/\/\u5305\u5bfc\u5165\n\u2502  go.sum\n\u2502  main.go       \/\/\u4e3b\u51fd\u6570\n\u2502  README.md\n\u2502  setsql.go     \/\/\u6d4b\u8bd5\u6570\u636e\n\u2502  \u7ed3\u6784.txt\n\u2502\n\u251c\u2500.idea\n\u2502      .gitignore\n\u2502      .name\n\u2502      GDX_helium.iml\n\u2502      modules.xml\n\u2502      vcs.xml\n\u2502      workspace.xml\n\u2502\n\u251c\u2500api             \/\/api\u6587\u6863\n\u2502  \u2514\u2500v1\n\u2502      \u251c\u2500admin\n\u2502      \u2502      admin.go    \n\u2502      \u2502\n\u2502      \u251c\u2500client\n\u2502      \u251c\u2500login\n\u2502      \u2502      login.go\n\u2502      \u2502\n\u2502      \u251c\u2500quest\n\u2502      \u2514\u2500template\n\u251c\u2500conf       \/\/web\u76f8\u5173\u914d\u7f6e\u6587\u4ef6\n\u2502      config.go\n\u2502      config.yaml\n\u2502\n\u251c\u2500const      \/\/\u5e38\u91cf\n\u2502      enum.go    \/\/\u679a\u4e3e\u6587\u4ef6\n\u2502\n\u251c\u2500db\n\u2502      db.go    \/\/\u6570\u636e\u5e93\n\u2502\n\u251c\u2500log\n\u2502      logger.go   \/\/\u65e5\u5fd7\n\u2502\n\u251c\u2500models      \/\/gorm\u6a21\u578b\n\u2502      user.go \n\u2502\n\u251c\u2500static      \/\/\u9759\u6001\u6587\u4ef6\n\u251c\u2500system      \/\/\u7cfb\u7edf\u76f8\u5173\n\u2502      init.go \/\/\u8bbe\u7f6e\n\u2502\n\u251c\u2500templates   \/\/\u6a21\u677f\n\u2514\u2500utils       \/\/\u590d\u7528\u6587\u4ef6\n        file.go<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u4e3b\u6846\u67b6main.go\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>package main\n\nimport (\n\t\"GDX_helium\/api\/v1\/admin\"\n\t\"GDX_helium\/conf\"\n\t\"GDX_helium\/db\"\n\t\"GDX_helium\/log\"\n\t\"GDX_helium\/system\"\n\t\"github.com\/gin-gonic\/gin\"\n)\n\nfunc main() {\n\t\/\/ \u521d\u59cb\u5316\u914d\u7f6e\n\tconf.Init()\n\n\t\/\/ \u521d\u59cb\u5316\u65e5\u5fd7\n\tlog.Init()\n\n\t\/\/ \u521d\u59cb\u5316\u7cfb\u7edf\n\tsystem.Init()\n\n\t\/\/ \u521d\u59cb\u5316\u6570\u636e\u5e93\n\tdb.Init()\n\n\t\/\/ \u521b\u5efaGin\u5f15\u64ce\n\tr := gin.Default()\n\n\t\/\/ \u6ce8\u518c\u8def\u7531\n\tv1 := r.Group(\"\/api\/v1\")\n\t{\n\t\tadmin.RegisterRoutes(v1)\n\t}\n\n\t\/\/ \u542f\u52a8\u670d\u52a1\u5668\n\tr.Run(\":8080\")\n}<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u6570\u636e\u5e93\u6587\u4ef6db.go<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>package db\n\nimport (\n\t\"GDX_helium\/conf\"\n\tuser \"GDX_helium\/models\"\n\t\"fmt\"\n\t\"gorm.io\/driver\/mysql\"\n\t\"gorm.io\/gorm\"\n\t\"log\"\n)\n\nvar DB *gorm.DB\n\nfunc Buildsql() { \/\/\u751f\u6210\u6570\u636e\u5e93\n\terr := DB.AutoMigrate(&amp;user.User{}) \/\/ \u4f7f\u7528 user.User\u65b0\u5efauser\u8868\n\tif err != nil {\n\t\tlog.Fatalf(\"\u8fc1\u79fb\u6570\u636e\u5e93\u51fa\u9519: %v\", err)\n\t}\n}\n\nfunc Init() {\n\tdbConfig := conf.GetDatabaseConfig() \/\/\u5bfc\u5165\u6570\u636e\u5e93\u914d\u7f6e\u4fe1\u606f\n\tdsn := fmt.Sprintf(\"%s:%s@tcp(%s:%s)\/%s?charset=utf8mb4&amp;parseTime=True&amp;loc=Local\",\n\t\tdbConfig&#91;\"user\"], dbConfig&#91;\"password\"], dbConfig&#91;\"host\"], dbConfig&#91;\"port\"], dbConfig&#91;\"name\"])\n\n\tvar err error\n\tDB, err = gorm.Open(mysql.Open(dsn), &amp;gorm.Config{}) \/\/\u8fde\u63a5\u6570\u636e\u5e93\n\tif err != nil {\n\t\tlog.Fatalf(\"\u8fde\u63a5\u6570\u636e\u5e93\u9519\u8bef: %v\", err)\n\t}\n}<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u914d\u7f6e\u6587\u4ef6config.go<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>package conf\n\nimport (\n\t\"github.com\/spf13\/viper\"\n\t\"log\"\n)\n\nfunc Init() {\n\t\/\/ \u8bbe\u7f6e\u914d\u7f6e\u6587\u4ef6\u540d (\u4e0d\u5305\u62ec\u6269\u5c55\u540d)\n\tviper.SetConfigName(\"config\")\n\t\/\/ \u8bbe\u7f6e\u914d\u7f6e\u6587\u4ef6\u7c7b\u578b\n\tviper.SetConfigType(\"yaml\")\n\t\/\/ \u8bbe\u7f6e\u914d\u7f6e\u6587\u4ef6\u8def\u5f84\uff0c\u53ef\u4ee5\u8bbe\u7f6e\u591a\u4e2a\u8def\u5f84\n\tviper.AddConfigPath(\".\/conf\")\n\t\/\/ \u8bfb\u53d6\u914d\u7f6e\u6587\u4ef6\n\terr := viper.ReadInConfig()\n\tif err != nil {\n\t\tlog.Fatalf(\"Error reading config file, %s\", err)\n\t}\n}\n\n\/\/ \u83b7\u53d6\u914d\u7f6e\u9879\nfunc GetServerPort() string {\t\t\t\t\/\/\u7aef\u53e3\n\treturn viper.GetString(\"server.port\")\n}\n\nfunc GetDatabaseConfig() map&#91;string]string {\t\t\/\/\u83b7\u53d6\u6570\u636e\u5e93\u76f8\u5173\u914d\u7f6e\n\treturn map&#91;string]string{\n\t\t\"type\":     viper.GetString(\"database.type\"),\n\t\t\"host\":     viper.GetString(\"database.host\"),\n\t\t\"port\":     viper.GetString(\"database.port\"),\n\t\t\"user\":     viper.GetString(\"database.user\"),\n\t\t\"password\": viper.GetString(\"database.password\"),\n\t\t\"name\":     viper.GetString(\"database.name\"),\n\t}\n}<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u914d\u7f6e\u6587\u4ef6config.yaml<\/strong>\uff08\u4e3b\u8981\u662f\u53c2\u8003\u683c\u5f0f\uff09<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong># \u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\napp:\n  name: GDX_helium\n  mode: debug # release\n\n# \u670d\u52a1\u5668\u7aef\u53e3\nserver:\n  port: 8080\n\n# \u6570\u636e\u5e93\ndatabase:\n  type: mysql\n  host: localhost\n  port: 3306\n  user: root\n  password: 123456\n  name: gdx_helium\n\n# \u65e5\u5fd7\nlog:\n  level: info\n  format: text # or json\n\n# JWT\u914d\u7f6e\njwt:\n  secret: key\n  expire: 3600 # in seconds\n\n# \u7f13\u5b58\ncache:\n  type: redis\n  host: localhost\n  port: 6379\n  password: \"\"\n\n# \u90ae\u7bb1\nemail:\n  smtp_host: smtp.example.com\n  smtp_port: 587\n  user: user@example.com\n  password: email_password<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u679a\u4e3e\u51fd\u6570enum.go<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>package enum\n\nimport (\n\t\"database\/sql\/driver\"\n\t\"errors\"\n)\n\ntype UserRole string \/\/\u7528\u6237\u89d2\u8272\n\nconst (\n\tAdmin UserRole = \"admin\" \/\/\u7ba1\u7406\u5458\n\tUser  UserRole = \"user\"  \/\/\u7528\u6237\n\tGuest UserRole = \"block\" \/\/\u51bb\u7ed3\n)\n\nfunc (u *UserRole) Scan(value interface{}) error { \/\/\u679a\u4e3e\u901a\u7528\n\tif value == nil {\n\t\t*u = \"\"\n\t\treturn nil\n\t}\n\tstr, ok := value.(&#91;]byte)\n\tif !ok {\n\t\treturn errors.New(\"UserRole\u7684\u6570\u636e\u65e0\u6548\")\n\t}\n\t*u = UserRole(str)\n\treturn nil\n}\n\nfunc (u UserRole) Value() (driver.Value, error) { \/\/\u679a\u4e3e\u901a\u7528\n\treturn string(u), nil\n}\n\ntype OrderStatus string\n\nconst (\n\tPending   OrderStatus = \"pending\"\n\tCompleted OrderStatus = \"completed\"\n\tCanceled  OrderStatus = \"canceled\"\n)\n\nfunc (o *OrderStatus) Scan(value interface{}) error {\n\tif value == nil {\n\t\t*o = \"\"\n\t\treturn nil\n\t}\n\tstr, ok := value.(&#91;]byte)\n\tif !ok {\n\t\treturn errors.New(\"OrderStatus\u7684\u65e0\u6548\u6570\u636e\")\n\t}\n\t*o = OrderStatus(str)\n\treturn nil\n}\n\nfunc (o OrderStatus) Value() (driver.Value, error) {\n\treturn string(o), nil\n}<\/strong>\n\n<strong>\/\/ IsValid \u68c0\u67e5\u72b6\u6001\u662f\u5426\u6709\u6548\nfunc (s <strong>OrderStatus<\/strong>) IsValid() bool {\n    switch s {\n    case pending, running, ended, block:\n        return true\n    default:\n        return false\n    }\n}<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u6570\u636e\u5e93ORM\u6a21\u578b-user.go<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>package user\n\nimport (\n\tenum \"GDX_helium\/const\"\n\t\"golang.org\/x\/crypto\/bcrypt\"\n\t\"gorm.io\/gorm\"\n)\n\ntype User struct {\n\tID        uint          `gorm:\"primaryKey\"`                                                     \/\/\u7528\u6237ID\n\tName      string        `gorm:\"size:100;not null\" json:\"name\"`                                  \/\/\u7528\u6237\u6635\u79f0\n\tEmail     string        `gorm:\"size:100;uniqueIndex;null\" json:\"email\"`                         \/\/\u7528\u6237\u90ae\u7bb1\n\tLoginName string        `gorm:\"size:100;not null\" json:\"login_name\"`                            \/\/\u767b\u9646\u8d26\u53f7\n\tPassword  string        `gorm:\"size:100;not null\" json:\"password\"`                              \/\/\u5bc6\u7801\n\tPhone     string        `gorm:\"size:20;null\" json:\"phone\"`                                      \/\/\u624b\u673a\u53f7\n\tRole      enum.UserRole `gorm:\"type:enum('admin', 'user', 'block');default:'user'\" json:\"role\"` \/\/\u6743\u9650\n}\n\n\/\/ \u5bf9\u6bd4\u5bc6\u7801\nfunc (u *User) CheckPassword(password string) bool {\n\terr := bcrypt.CompareHashAndPassword(&#91;]byte(u.Password), &#91;]byte(password))\n\treturn err == nil\n}\n\n\/\/ \u5bfb\u627e\u7528\u6237\nfunc GetUserByLoginName(loginName string, db *gorm.DB) (*User, error) {\n\tvar user User\n\tif err := db.Where(\"login_name = ?\", loginName).First(&amp;user).Error; err != nil {\n\t\treturn nil, err\n\t}\n\treturn &amp;user, nil\n}<\/strong><\/code><\/pre>\n\n\n\n<p><strong>GORM\u6a21\u578b\u5173\u8054<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>type TaskUser struct {\n    TaskID uint `gorm:\"not null\"  json:\"task_id\"`\n    Task   Task `gorm:\"foreignKey:TaskID;references:TaskID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;\" json:\"task\"`\n    UserID uint `gorm:\"not null\"  json:\"user_id\"`\n    User   User `gorm:\"foreignKey:UserID;references:UserID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;\" json:\"user\"`\n}<\/strong>\n<strong>\n\/\/foreignKey\uff1a\u8bbe\u7f6e\u5916\u952e\uff0creferences\uff1a\u4e0e\u5bf9\u5e94\u7684\u8868\u4e2d\u7684\u5b57\u6bb5\u5173\u8054<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u767b\u5f55login.go<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>package admin\n\nimport (\n\t\"GDX_helium\/db\"\n\tuser \"GDX_helium\/models\"\n\t\"github.com\/gin-gonic\/gin\"\n\t\"net\/http\"\n)\n\ntype LoginRequest struct {\n\tLoginName string `json:\"login_name\" binding:\"required\"`\n\tPassword  string `json:\"password\" binding:\"required\"`\n}\n\nfunc RegisterRoutes(r *gin.RouterGroup) {\n\tr.GET(\"\/admin\", GetActivity)\n\tr.POST(\"\/login\", Login)\n}\n\nfunc GetActivity(c *gin.Context) {\n\tc.JSON(http.StatusOK, gin.H{\n\t\t\"message\": \"Activity endpoint\",\n\t})\n}\n\nfunc Login(c *gin.Context) {\n\tvar req LoginRequest\n\tif err := c.ShouldBindJSON(&amp;req); err != nil {\n\t\tc.JSON(http.StatusBadRequest, gin.H{\"error\": \"\u65e0\u6548\u7684\u8bf7\u6c42\"})\n\t\treturn\n\t}\n\n\tuser, err := user.GetUserByLoginName(req.LoginName, db.DB)   \/\/\u67e5\u8be2\n\tif err != nil {\t\t\t\/\/\u5982\u679cerr\u4e0d\u4e3anil\n\t\tc.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u65e0\u6548\u7684\u767b\u5f55\u540d\u6216\u5bc6\u7801\"})\n\t\treturn\n\t}\n\tif !user.CheckPassword(req.Password) {   \/\/\u5982\u679c\u5bc6\u7801\u4e0d\u4e00\u81f4\n\t\tc.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u65e0\u6548\u7684\u767b\u5f55\u540d\u6216\u5bc6\u7801\"})\n\t\treturn\n\t}\n\t\/\/ \u751f\u6210\u5e76\u8fd4\u56de JWT \u6216\u5176\u4ed6\u4f1a\u8bdd\u7ba1\u7406\u65b9\u6848\n\tc.JSON(http.StatusOK, gin.H{\n\t\t\"message\":   \"Login\u6210\u529f\",\n\t\t\"user_id\":   user.ID,\n\t\t\"user_name\": user.Name,\n\t\t\"role\":      user.Role.Value,\n\t})\n}<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u5411\u6570\u636e\u5e93\u6dfb\u52a0\u6570\u636e<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>func add_task(c *gin.Context) {\n    var req task_add\n    if err := c.ShouldBind(&amp;req); err != nil {\n        c.JSON(http.StatusBadRequest, gin.H{\"error\": \"\u65e0\u6548\u7684\u8bf7\u6c42\"})\n        return\n    }\n    userID := c.MustGet(\"userID\").(uint)\n    task := models.Task{\n        Introduce: req.Introduce,\n        CreatorID: userID,\n        BuildTime: time.Now().Unix(),\n    }\n\n    if err := db.DB.Create(&amp;task).Error; err != nil {\n        c.JSON(http.StatusInternalServerError, gin.H{\"error\": \"\u65e0\u6cd5\u521b\u5efa\u4efb\u52a1\"})\n        return\n    }\n\n    c.JSON(http.StatusOK, gin.H{\"message\": \"\u4efb\u52a1\u521b\u5efa\u6210\u529f\", \"task\": task})\n}<\/strong>\n<\/code><\/pre>\n\n\n\n<p><strong>\u4fee\u6539\u6570\u636e<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>var task models.Task<\/strong>\n<strong>\/\/ \u67e5\u627e\u4efb\u52a1\n    if err := db.DB.First(&amp;task, taskID).Error; err != nil {\n        if gorm.ErrRecordNotFound == err {\n            c.JSON(http.StatusNotFound, gin.H{\"error\": \"\u4efb\u52a1\u672a\u627e\u5230\"})\n        } else {\n            c.JSON(http.StatusInternalServerError, gin.H{\"error\": \"\u65e0\u6cd5\u67e5\u627e\u4efb\u52a1\"})\n        }\n        return\n    }<\/strong>\n\n<strong>\/\/ \u66f4\u65b0\u4efb\u52a1\u5b57\u6bb5\n    task.Introduce = req.Introduce\n    task.Frequency = req.Frequency\n    task.Status = req.Status\n\n    \/\/ \u4fdd\u5b58\u66f4\u65b0\n    if err := db.DB.Save(&amp;task).Error; err != nil {\n        c.JSON(http.StatusInternalServerError, gin.H{\"error\": \"\u65e0\u6cd5\u66f4\u65b0\u4efb\u52a1\"})\n        return\n    }<\/strong><\/code><\/pre>\n\n\n\n<p><strong>\u67e5\u8be2\u6570\u636e\u5e93<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>\/\/ GetTaskList \u67e5\u8be2\u6240\u6709\u4efb\u52a1\u5217\u8868    Find\u67e5\u8be2\u6240\u6709\u5217\u8868\nfunc AdminGetTaskList(db *gorm.DB) (&#91;]Task, error) {\n    var tasks &#91;]Task\n    if err := db.Find(&amp;tasks).Error; err != nil {\n        return nil, err\n    }\n    return tasks, nil\n}<\/strong>\n\n<strong>\/\/\u67e5\u8be2\u5355\u4e2a\u6570\u636e    Where().First()\n\/\/ GetUserByLoginName\u901a\u8fc7\u767b\u5f55\u540d\u68c0\u7d22\u7528\u6237\nfunc GetUserByLoginName(loginName string, db *gorm.DB) (*User, error) {\n    var user User\n    if err := db.Where(\"login_name = ?\", loginName).First(&amp;user).Error; err != nil {\n        return nil, err\n    }\n    return &amp;user, nil\n}<\/strong>\n\n<strong>\/\/\u8054\u8868\u67e5\u8be2     Joins().Where().Find()\n\/\/Joins\u8054\u5408\u67e5\u8be2<\/strong>\n<strong>\/\/JOIN task_users ON task_users.task_id = tasks.task_id\n\/\/\u8054\u5408task_users\u8868\uff0c\u83b7\u53d6\u6761\u4ef6\u4e3atask_users\u8868\u7684task_id\u9884tasks\u8868\u5355task_id\u76f8\u7b49\u7684\u6570\u636e\n\/\/Where\u7b5b\u9009\u6570\u636e\n\/\/\"task_users.user_id = ?\",userID\n\/\/\u7b5b\u9009\u51fatask_users.user_id\u7b49\u4e8e\u4f20\u5165\u53c2\u6570\u7684userID\u7684\u6570\u636e\n\/\/Find(&amp;tasks)\n\/\/\u5c06\u6570\u636e\u5b58\u50a8\u81f3tasks\u4e2d<\/strong>\n\n<strong>\nfunc UserGetTaskList(db *gorm.DB, userID uint) (&#91;]Task, error) {\n    var tasks &#91;]Task\n\n    \/\/ \u901a\u8fc7\u4e2d\u95f4\u8868 task_user \u67e5\u8be2\u6307\u5b9a\u7528\u6237\u7684\u4efb\u52a1\u5217\u8868\n    if err := db.Joins(\"JOIN task_users ON task_users.task_id = tasks.task_id\").\n        Where(\"task_users.user_id = ?\", userID).\n        Find(&amp;tasks).Error; err != nil {\n        return nil, err\n    }\n\n    return tasks, nil\n}<\/strong><\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>JWT\u7684\u4f7f\u7528<\/strong><\/h2>\n\n\n\n<p><strong>\u5148\u5b89\u88c5jwt\u7684\u5305\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>go get github.com\/dgrijalva\/jwt-go<\/strong><\/code><\/pre>\n\n\n\n<p><strong>JWT\u521b\u5efa\u3001\u751f\u6210\u3001\u9a8c\u8bc1\u4ee4\u724c\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>package common\n\nimport (\n\t\"GDX_helium\/conf\"\n\t\"errors\"\n\t\"github.com\/dgrijalva\/jwt-go\"\n\t\"github.com\/gin-gonic\/gin\"\n\t\"net\/http\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\ntype Claims struct { \/\/ JWT\u7ed3\u6784\n\tUserID             uint   `json:\"user_id\"` \/\/ \u7528\u6237ID\n\tRole               string `json:\"role\"`    \/\/ \u7528\u6237\u89d2\u8272\n\tjwt.StandardClaims        \/\/ \u65f6\u95f4\n}\n\n\/\/ \u751f\u6210JWT\u4ee4\u724c\nfunc GenerateJWT(userID uint, role string) (string, error) {\n\tJWTConfig := conf.GetJWTConfig() \/\/ \u5bfc\u5165JWT\u914d\u7f6e\u6587\u4ef6\n\tvar jwtKey = &#91;]byte(JWTConfig&#91;\"JWTkey\"])\n\texpire, err := strconv.Atoi(JWTConfig&#91;\"expire\"])\n\texpirationTime := time.Now().Add(time.Duration(expire) * time.Second)\n\tclaims := &amp;Claims{\n\t\tUserID: userID,\n\t\tRole:   role,\n\t\tStandardClaims: jwt.StandardClaims{\n\t\t\tExpiresAt: expirationTime.Unix(),\n\t\t},\n\t}\n\n\ttoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)\n\ttokenString, err := token.SignedString(jwtKey)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn tokenString, nil\n}\n\n\/\/ \u9a8c\u8bc1JWT\u4ee4\u724c\nfunc ValidateJWT(tokenString string) (*Claims, error) {\n\tJWTConfig := conf.GetJWTConfig() \/\/ \u5bfc\u5165JWT\u914d\u7f6e\u6587\u4ef6\n\tvar jwtKey = &#91;]byte(JWTConfig&#91;\"JWTkey\"])\n\tclaims := &amp;Claims{}\n\ttoken, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {\n\t\treturn jwtKey, nil\n\t})\n\n\tif err != nil {\n\t\tif ve, ok := err.(*jwt.ValidationError); ok {\n\t\t\tif ve.Errors&amp;jwt.ValidationErrorExpired != 0 {\n\t\t\t\treturn nil, errors.New(\"\u4ee4\u724c\u5df2\u8fc7\u671f\")\n\t\t\t}\n\t\t}\n\t\treturn nil, err\n\t}\n\n\tif !token.Valid {\n\t\treturn nil, errors.New(\"\u4ee4\u724c\u65e0\u6548\")\n\t}\n\n\treturn claims, nil\n}<\/strong><\/code><\/pre>\n\n\n\n<p><strong>JWT\u62e6\u622a\u5668\uff08\u4e2d\u95f4\u4ef6\uff09\uff1a<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>func JWTAuthMiddleware() gin.HandlerFunc {\t\t\/\/JWT\u4e2d\u95f4\u4ef6\n\treturn func(c *gin.Context) {\n\t\tauthHeader := c.GetHeader(\"Authorization\")\n\t\tif authHeader == \"\" {\n\t\t\tc.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u8ba4\u8bc1\u5931\u8d25\"})\n\t\t\tc.Abort()\n\t\t\treturn\n\t\t}\n\n\t\tparts := strings.SplitN(authHeader, \" \", 2)\n\t\tif !(len(parts) == 2 &amp;&amp; parts&#91;0] == \"Bearer\") {\n\t\t\tc.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u8ba4\u8bc1\u5931\u8d25\"})\n\t\t\tc.Abort()\n\t\t\treturn\n\t\t}\n\n\t\tclaims, err := ValidateJWT(parts&#91;1])\n\t\tif err != nil {\n\t\t\tc.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u65e0\u6548\u7684\u4ee4\u724c\"})\n\t\t\tc.Abort()\n\t\t\treturn\n\t\t}\n\n\t\tc.Set(\"userID\", claims.UserID)\n                c.Set(\"userRole\", claims.Role)\n\t\tc.Next()\n\t}<\/strong><\/code><\/pre>\n\n\n\n<p><strong>JWT\u7684\u4f7f\u7528\uff1a<\/strong><\/p>\n\n\n\n<p>\u4fee\u6539main.go:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>package main\n\nimport (\n\t\"GDX_helium\/api\/v1\/admin\"\n\t\"GDX_helium\/common\"\n\t\"GDX_helium\/conf\"\n\t\"GDX_helium\/db\"\n\t\"GDX_helium\/log\"\n\t\"GDX_helium\/system\"\n\t\"github.com\/gin-gonic\/gin\"\n)\n\nfunc main() {\n\t\/\/ \u521d\u59cb\u5316\u914d\u7f6e\n\tconf.Init()\n\n\t\/\/ \u521d\u59cb\u5316\u65e5\u5fd7\n\tlog.Init()\n\n\t\/\/ \u521d\u59cb\u5316\u7cfb\u7edf\n\tsystem.Init()\n\n\t\/\/ \u521d\u59cb\u5316\u6570\u636e\u5e93\n\tdb.Init() \/\/ \u65b0\u589e\u6b64\u884c\n\n\t\/\/ \u521b\u5efaGin\u5f15\u64ce\n\tr := gin.Default()\n\n\t\/\/ \u6ce8\u518c\u516c\u5171\u8def\u7531\n\tpublic := r.Group(\"\/api\/v1\")\n\tadmin.RegisterPublicRoutes(public)\n\n\t\/\/ \u6ce8\u518c\u53d7\u4fdd\u62a4\u7684\u8def\u7531\n\tprotected := r.Group(\"\/api\/v1\")\n\tprotected.Use(common.JWTAuthMiddleware())\n\tadmin.RegisterProtectedRoutes(protected)\n\n\t\/\/ \u542f\u52a8\u670d\u52a1\u5668\n\tr.Run(\":8080\")\n}<\/strong><\/code><\/pre>\n\n\n\n<p>\u767b\u5f55login.go\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>func Login(c *gin.Context) {\n    var req LoginRequest\n    if err := c.ShouldBind(&amp;req); err != nil {\n        c.JSON(http.StatusBadRequest, gin.H{\"error\": \"\u65e0\u6548\u7684\u8bf7\u6c42\"})\n        return\n    }\n\n    user, err := models.GetUserByLoginName(req.LoginName, db.DB)\n    if err != nil {\n        c.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u65e0\u6548\u7684\u767b\u5f55\u540d\u6216\u5bc6\u7801\"})\n        return\n    }\n\n    if !user.CheckPassword(req.Password) {\n        c.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u65e0\u6548\u7684\u767b\u5f55\u540d\u6216\u5bc6\u7801\"})\n        return\n    }\n\n    \/\/ \u751f\u6210JWT\u4ee4\u724c\n    token, err := common.GenerateJWT(user.ID, string(user.Role))\n    if err != nil {\n        c.JSON(http.StatusInternalServerError, gin.H{\"error\": \"\u65e0\u6cd5\u751f\u6210\u4ee4\u724c\"})\n        return\n    }\n\n    \/\/ \u8bbe\u7f6eJWT\u4ee4\u724c\u5728Authorization\u5934\u4e2d\n    c.Header(\"Authorization\", \"Bearer \"+token)\n\n    \/\/ \u8fd4\u56deJWT\u4ee4\u724c\n    c.JSON(http.StatusOK, gin.H{\n        \"message\":   \"\u767b\u5f55\u6210\u529f\",\n        \"user_id\":   user.ID,\n        \"user_name\": user.Name,\n        \"role\":      user.Role,\n    })\n}<\/strong><\/code><\/pre>\n\n\n\n<p>\u5237\u65b0token:<\/p>\n\n\n\n<p>jwt.go:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>\/\/ \u68c0\u67e5\u4ee4\u724c\u662f\u5426\u5373\u5c06\u8fc7\u671f\u5e76\u751f\u6210\u65b0\u7684\u4ee4\u724c\nfunc RefreshJWT(tokenString string) (string, error) {\n\tclaims, err := ValidateJWT(tokenString)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\t\/\/ \u68c0\u67e5\u4ee4\u724c\u662f\u5426\u5373\u5c06\u8fc7\u671f\uff0c\u8bbe\u7f6e\u4e00\u4e2a\u5408\u7406\u7684\u65f6\u95f4\u7a97\u53e3\n\tif time.Until(time.Unix(claims.ExpiresAt, 0)) &gt; 30*time.Minute {\n\t\treturn \"\", errors.New(\"\u4ee4\u724c\u672a\u63a5\u8fd1\u8fc7\u671f\uff0c\u65e0\u9700\u5237\u65b0\")\n\t}\n\n\t\/\/ \u751f\u6210\u65b0\u7684\u4ee4\u724c\n\treturn GenerateJWT(claims.UserID, claims.Role)\n}<\/strong><\/code><\/pre>\n\n\n\n<p>login.go:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>func RefreshToken(c *gin.Context) {\n\tauthHeader := c.GetHeader(\"Authorization\")\n\tif authHeader == \"\" {\n\t\tc.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u8bf7\u6c42\u5934\u4e2d\u7f3a\u5c11Authorization\u5b57\u6bb5\"})\n\t\treturn\n\t}\n\n\tparts := strings.SplitN(authHeader, \" \", 2)\n\tif !(len(parts) == 2 &amp;&amp; parts&#91;0] == \"Bearer\") {\n\t\tc.JSON(http.StatusUnauthorized, gin.H{\"error\": \"\u8bf7\u6c42\u5934\u4e2d\u7684Authorization\u683c\u5f0f\u6709\u8bef\"})\n\t\treturn\n\t}\n\n\tnewToken, err := common.RefreshJWT(parts&#91;1])\n\tif err != nil {\n\t\tc.JSON(http.StatusUnauthorized, gin.H{\"error\": err.Error()})\n\t\treturn\n\t}\n\n\tc.JSON(http.StatusOK, gin.H{\n\t\t\"message\": \"\u4ee4\u724c\u5237\u65b0\u6210\u529f\",\n\t\t\"token\":   newToken,\n\t})\n}<\/strong><\/code><\/pre>\n\n\n\n<p>\u5728\u8def\u7531\u4e2d\u4f7f\u7528\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>func RegisterPublicRoutes(r *gin.RouterGroup) {\n\tr.POST(\"\/login\", Login)\n}\n\nfunc RegisterProtectedRoutes(r *gin.RouterGroup) {\n\tr.GET(\"\/test\", test)\n}\n\n\/\/\u6d4b\u8bd5\nfunc test(c *gin.Context) {\n\tuserID := c.MustGet(\"userID\").(uint)   \/\/\u63d0\u53d6user_id\n\tuserRole := c.MustGet(\"userRole\").(string)  \/\/\u63d0\u53d6\u89d2\u8272\n\n\tc.JSON(http.StatusOK, gin.H{\n\t\t\"message\":   \"\u4f60\u5df2\u6210\u529f\u8bbf\u95ee\u53d7\u4fdd\u62a4\u7684\u8def\u7531\",\n\t\t\"user_id\":   userID,\n\t\t\"user_role\": userRole,\n\t})\n}<\/strong><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u7f13\u5b58\u7684\u4f7f\u7528<\/strong><\/h2>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>WebSocket<\/strong><\/h2>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u4f18\u5316<\/strong><\/h2>\n","protected":false},"excerpt":{"rendered":"<p>\u5b89\u88c5gin\u6846\u67b6 \u8fd9\u4e00\u6b65\u5982\u679c\u5b89\u88c5\u4e0d\u4e86\uff0c\u9700\u8981\u5728goland\u4e2d\u8bbe\u7f6e\u4ee3\u7406\uff0c\u542f\u7528Go\u6a21\u5757\u96c6\u6210\uff0c\u5e76\u628a\u73af\u5883\u8bbe\u7f6e\u4e3a\uff1aGOPRO [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-99","post","type-post","status-publish","format-standard","hentry","category-golangbook"],"_links":{"self":[{"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/posts\/99","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/comments?post=99"}],"version-history":[{"count":60,"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/posts\/99\/revisions"}],"predecessor-version":[{"id":169,"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/posts\/99\/revisions\/169"}],"wp:attachment":[{"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/media?parent=99"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/categories?post=99"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nightying.com\/index.php\/wp-json\/wp\/v2\/tags?post=99"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}