Golang Gin瀹炶返 杩炶浇鍗佷簲 鐢熸垚浜岀淮鐮併€佸悎骞舵捣鎶?/a>
有志者,事竟成!如果你在学习数据库,那么本文《Golang Gin瀹炶返 杩炶浇鍗佷簲 鐢熸垚浜岀淮鐮併€佸悎骞舵捣鎶?/a>》,就很适合你!文章讲解的知识点主要包括MySQL、go、PHP,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~
鍘熸枃鍦板潃锛?a href="https://link.segmentfault.com/?enc=M0c3He0Nk7euMaqAYCPc4Q%3D%3D.lqTqI9PKx7DWU8v%2FMV4ySD0VEvsazCV4k5vKv1nYlZmcUBIt4A35Uvj2Z8AuinW8" rel="nofollow">Golang Gin瀹炶返 杩炶浇鍗佷簲 鐢熸垚浜岀淮鐮併€佸悎骞舵捣鎶?/a>
椤圭洰鍦板潃锛?a href="https://link.segmentfault.com/?enc=0PvtIiLk2pNc8vA%2FboF6%2BA%3D%3D.HgHyyzRrO2GgU6bSv02%2BRySHjrvoZsS%2BhKwaHBps695Icigk3gkPuWWuyY8xCaVd" rel="nofollow">https://github.com/EDDYCJY/go...
濡傛灉瀵逛綘鏈夋墍甯姪锛屾杩庣偣涓?Star 馃憤
鍓嶈█
鍦ㄦ湰绔犺妭锛屽皢瀹炵幇濡備笅鍔熻兘缁嗛」锛?/p>
1銆佺敓鎴愪簩缁寸爜
2銆佸悎骞舵捣鎶ワ紙鑳屾櫙鍥?+ 浜岀淮鐮侊級
瀹炵幇
棣栧厛锛屼綘闇€瑕佸湪 App 閰嶇疆椤逛腑澧炲姞浜岀淮鐮佸強鍏舵捣鎶ョ殑瀛樺偍璺緞锛屾垜浠害瀹氶厤缃」鍚嶇О涓?
QrCodeSavePath锛屽€间负
qrcode/
缁忚繃澶氳妭杩炶浇鐨勪綘搴旇鑳藉瀹屾垚锛岃嫢鏈変笉鎳傚彲鍙傜収 go-gin-example
鐢熸垚浜岀淮鐮?/h2>
瀹夎
$ go get -u github.com/boombuler/barcode
宸ュ叿鍖?/h3>
鑰冭檻鐢熸垚浜岀淮鐮佽繖涓€鍔ㄤ綔璐村悎宸ュ叿鍖呯殑瀹氫箟锛屼笖鏈夊叕鐢ㄧ殑鍙兘鎬э紝鏂板缓 pkg/qrcode/qrcode.go 鏂囦欢锛屽啓鍏ュ唴瀹癸細
package qrcode import ( "image/jpeg" "github.com/boombuler/barcode" "github.com/boombuler/barcode/qr" "github.com/EDDYCJY/go-gin-example/pkg/file" "github.com/EDDYCJY/go-gin-example/pkg/setting" "github.com/EDDYCJY/go-gin-example/pkg/util" ) type QrCode struct { URL string Width int Height int Ext string Level qr.ErrorCorrectionLevel Mode qr.Encoding } const ( EXT_JPG = ".jpg" ) func NewQrCode(url string, width, height int, level qr.ErrorCorrectionLevel, mode qr.Encoding) *QrCode { return &QrCode{ URL: url, Width: width, Height: height, Level: level, Mode: mode, Ext: EXT_JPG, } } func GetQrCodePath() string { return setting.AppSetting.QrCodeSavePath } func GetQrCodeFullPath() string { return setting.AppSetting.RuntimeRootPath + setting.AppSetting.QrCodeSavePath } func GetQrCodeFullUrl(name string) string { return setting.AppSetting.PrefixUrl + "/" + GetQrCodePath() + name } func GetQrCodeFileName(value string) string { return util.EncodeMD5(value) } func (q *QrCode) GetQrCodeExt() string { return q.Ext } func (q *QrCode) CheckEncode(path string) bool { src := path + GetQrCodeFileName(q.URL) + q.GetQrCodeExt() if file.CheckNotExist(src) == true { return false } return true } func (q *QrCode) Encode(path string) (string, string, error) { name := GetQrCodeFileName(q.URL) + q.GetQrCodeExt() src := path + name if file.CheckNotExist(src) == true { code, err := qr.Encode(q.URL, q.Level, q.Mode) if err != nil { return "", "", err } code, err = barcode.Scale(code, q.Width, q.Height) if err != nil { return "", "", err } f, err := file.MustOpen(name, path) if err != nil { return "", "", err } defer f.Close() err = jpeg.Encode(f, code, nil) if err != nil { return "", "", err } } return name, path, nil }
杩欓噷涓昏鑱氱劍
func (q *QrCode) Encode鏂规硶锛屽仛浜嗗涓嬩簨鎯咃細
- 鑾峰彇浜岀淮鐮佺敓鎴愯矾寰?/li>
- 鍒涘缓浜岀淮鐮?/li>
- 缂╂斁浜岀淮鐮佸埌鎸囧畾澶у皬
- 鏂板缓瀛樻斁浜岀淮鐮佸浘鐗囩殑鏂囦欢
- 灏嗗浘鍍忥紙浜岀淮鐮侊級浠?JPEG 4锛?锛? 鍩虹嚎鏍煎紡鍐欏叆鏂囦欢
鍙﹀鍦?
jpeg.Encode(f, code, nil)涓紝绗笁涓弬鏁板彲璁剧疆鍏跺浘鍍忚川閲忥紝榛樿鍊间负 75
// DefaultQuality is the default quality encoding parameter. const DefaultQuality = 75 // Options are the encoding parameters. // Quality ranges from 1 to 100 inclusive, higher is better. type Options struct { Quality int }
璺敱鏂规硶
1銆佺涓€姝?/p>
鍦?routers/api/v1/article.go 鏂板 GenerateArticlePoster 鏂规硶鐢ㄤ簬鎺ュ彛寮€鍙?/p>
2銆佺浜屾
鍦?routers/router.go 鐨?apiv1 涓柊澧?
apiv1.POST("/articles/poster/generate", v1.GenerateArticlePoster)璺敱
3銆佺涓夋
淇敼 GenerateArticlePoster 鏂规硶锛岀紪鍐欏搴旂殑鐢熸垚閫昏緫锛屽涓嬶細
const ( QRCODE_URL = "https://github.com/EDDYCJY/blog#gin%E7%B3%BB%E5%88%97%E7%9B%AE%E5%BD%95" ) func GenerateArticlePoster(c *gin.Context) { appG := app.Gin{c} qrc := qrcode.NewQrCode(QRCODE_URL, 300, 300, qr.M, qr.Auto) path := qrcode.GetQrCodeFullPath() _, _, err := qrc.Encode(path) if err != nil { appG.Response(http.StatusOK, e.ERROR, nil) return } appG.Response(http.StatusOK, e.SUCCESS, nil) }
楠岃瘉
閫氳繃 POST 鏂规硶璁块棶
http://127.0.0.1:8000/api/v1/articles/poster/generate?token=$token锛堟敞鎰?$token锛?/p>

閫氳繃妫€鏌ヤ袱涓偣纭畾鍔熻兘鏄惁姝e父锛屽涓嬶細
1銆佽闂粨鏋滄槸鍚?200
2銆佹湰鍦扮洰褰曟槸鍚︽垚鍔熺敓鎴愪簩缁寸爜鍥剧墖

鍚堝苟娴锋姤
鍦ㄨ繖涓€鑺傦紝灏嗗疄鐜颁簩缁寸爜鍥剧墖涓庤儗鏅浘鍚堝苟鎴愭柊鐨勪竴寮犲浘锛屽彲鐢ㄤ簬甯歌鐨勫浼犳捣鎶ョ瓑涓氬姟鍦烘櫙
鑳屾櫙鍥?/h3>

灏嗚儗鏅浘鍙﹀瓨涓?runtime/qrcode/bg.jpg锛堝疄闄呭簲鐢紝鍙瓨鍦?OSS 鎴栧叾浠栧湴鏂癸級
service 鏂规硶
鎵撳紑 service/article_service 鐩綍锛屾柊寤?article_poster.go 鏂囦欢锛屽啓鍏ュ唴瀹癸細
package article_service import ( "image" "image/draw" "image/jpeg" "os" "github.com/EDDYCJY/go-gin-example/pkg/file" "github.com/EDDYCJY/go-gin-example/pkg/qrcode" ) type ArticlePoster struct { PosterName string *Article Qr *qrcode.QrCode } func NewArticlePoster(posterName string, article *Article, qr *qrcode.QrCode) *ArticlePoster { return &ArticlePoster{ PosterName: posterName, Article: article, Qr: qr, } } func GetPosterFlag() string { return "poster" } func (a *ArticlePoster) CheckMergedImage(path string) bool { if file.CheckNotExist(path+a.PosterName) == true { return false } return true } func (a *ArticlePoster) OpenMergedImage(path string) (*os.File, error) { f, err := file.MustOpen(a.PosterName, path) if err != nil { return nil, err } return f, nil } type ArticlePosterBg struct { Name string *ArticlePoster *Rect *Pt } type Rect struct { Name string X0 int Y0 int X1 int Y1 int } type Pt struct { X int Y int } func NewArticlePosterBg(name string, ap *ArticlePoster, rect *Rect, pt *Pt) *ArticlePosterBg { return &ArticlePosterBg{ Name: name, ArticlePoster: ap, Rect: rect, Pt: pt, } } func (a *ArticlePosterBg) Generate() (string, string, error) { fullPath := qrcode.GetQrCodeFullPath() fileName, path, err := a.Qr.Encode(fullPath) if err != nil { return "", "", err } if !a.CheckMergedImage(path) { mergedF, err := a.OpenMergedImage(path) if err != nil { return "", "", err } defer mergedF.Close() bgF, err := file.MustOpen(a.Name, path) if err != nil { return "", "", err } defer bgF.Close() qrF, err := file.MustOpen(fileName, path) if err != nil { return "", "", err } defer qrF.Close() bgImage, err := jpeg.Decode(bgF) if err != nil { return "", "", err } qrImage, err := jpeg.Decode(qrF) if err != nil { return "", "", err } jpg := image.NewRGBA(image.Rect(a.Rect.X0, a.Rect.Y0, a.Rect.X1, a.Rect.Y1)) draw.Draw(jpg, jpg.Bounds(), bgImage, bgImage.Bounds().Min, draw.Over) draw.Draw(jpg, jpg.Bounds(), qrImage, qrImage.Bounds().Min.Sub(image.Pt(a.Pt.X, a.Pt.Y)), draw.Over) jpeg.Encode(mergedF, jpg, nil) } return fileName, path, nil }
杩欓噷閲嶇偣鐣欐剰
func (a *ArticlePosterBg) Generate()鏂规硶锛屽仛浜嗗涓嬩簨鎯咃細
- 鑾峰彇浜岀淮鐮佸瓨鍌ㄨ矾寰?/li>
- 鐢熸垚浜岀淮鐮佸浘鍍?/li>
- 妫€鏌ュ悎骞跺悗鍥惧儚锛堟寚鐨勬槸瀛樻斁鍚堝苟鍚庣殑娴锋姤锛夋槸鍚﹀瓨鍦?/li>
- 鑻ヤ笉瀛樺湪锛屽垯鐢熸垚寰呭悎骞剁殑鍥惧儚 mergedF
- 鎵撳紑浜嬪厛瀛樻斁鐨勮儗鏅浘 bgF
- 鎵撳紑鐢熸垚鐨勪簩缁寸爜鍥惧儚 qrF
- 瑙g爜 bgF 鍜?qrF 杩斿洖 image.Image
- 鍒涘缓涓€涓柊鐨?RGBA 鍥惧儚
- 鍦?RGBA 鍥惧儚涓婄粯鍒?鑳屾櫙鍥撅紙bgF锛?/li>
- 鍦ㄥ凡缁樺埗鑳屾櫙鍥剧殑 RGBA 鍥惧儚涓婏紝鍦ㄦ寚瀹?Point 涓婄粯鍒朵簩缁寸爜鍥惧儚锛坬rF锛?/li>
- 灏嗙粯鍒跺ソ鐨?RGBA 鍥惧儚浠?JPEG 4锛?锛? 鍩虹嚎鏍煎紡鍐欏叆鍚堝苟鍚庣殑鍥惧儚鏂囦欢锛坢ergedF锛?/li>
閿欒鐮?/h3>
璺敱鏂规硶
鎵撳紑 routers/api/v1/article.go 鏂囦欢锛屼慨鏀?GenerateArticlePoster 鏂规硶锛岀紪鍐欐渶缁堢殑涓氬姟閫昏緫锛堝惈鐢熸垚浜岀淮鐮佸強鍚堝苟娴锋姤锛夛紝濡備笅锛?/p>
const ( QRCODE_URL = "https://github.com/EDDYCJY/blog#gin%E7%B3%BB%E5%88%97%E7%9B%AE%E5%BD%95" ) func GenerateArticlePoster(c *gin.Context) { appG := app.Gin{c} article := &article_service.Article{} qr := qrcode.NewQrCode(QRCODE_URL, 300, 300, qr.M, qr.Auto) // 鐩墠鍐欐 gin 绯诲垪璺緞锛屽彲鑷澧炲姞涓氬姟閫昏緫 posterName := article_service.GetPosterFlag() + "-" + qrcode.GetQrCodeFileName(qr.URL) + qr.GetQrCodeExt() articlePoster := article_service.NewArticlePoster(posterName, article, qr) articlePosterBgService := article_service.NewArticlePosterBg( "bg.jpg", articlePoster, &article_service.Rect{ X0: 0, Y0: 0, X1: 550, Y1: 700, }, &article_service.Pt{ X: 125, Y: 298, }, ) _, filePath, err := articlePosterBgService.Generate() if err != nil { appG.Response(http.StatusOK, e.ERROR_GEN_ARTICLE_POSTER_FAIL, nil) return } appG.Response(http.StatusOK, e.SUCCESS, map[string]string{ "poster_url": qrcode.GetQrCodeFullUrl(posterName), "poster_save_url": filePath + posterName, }) }
杩欏潡娑夊強鍒板ぇ閲忕煡璇嗭紝寮虹儓寤鸿闃呰涓嬶紝濡備笅锛?/p>
鍏舵墍娑夊強銆佸叧鑱旂殑搴撻兘寤鸿鐮旂┒涓€涓?/p>
StaticFS
鍦?routers/router.go 鏂囦欢锛屽鍔犲涓嬩唬鐮?
r.StaticFS("/qrcode", http.Dir(qrcode.GetQrCodeFullPath()))
楠岃瘉

璁块棶瀹屾暣鐨?URL 璺緞锛岃繑鍥炲悎鎴愬悗鐨勬捣鎶ュ苟鎵櫎浜岀淮鐮佹垚鍔熷垯姝g‘ 馃

鎬荤粨
鍦ㄦ湰绔犺妭瀹炵幇浜嗕袱涓緢甯歌鐨勪笟鍔″姛鑳斤紝鍒嗗埆鏄敓鎴愪簩缁寸爜鍜屽悎骞舵捣鎶ャ€傚笇鏈涗綘鑳藉浠旂粏闃呰鎴戠粰鍑虹殑閾炬帴锛岃繖鍧楃殑鐭ヨ瘑閲忎笉灏戯紝鎯宠鐢ㄥソ鍥惧儚澶勭悊鐨勫姛鑳斤紝蹇呴』鐞嗚В瀵瑰簲鐨勬€濊矾锛屼妇涓€鍙嶄笁
鏈€鍚庡笇鏈涘浣犳湁鎵€甯姪 馃憣
鍙傝€?/h2>
鏈郴鍒楃ず渚嬩唬鐮?/h3>
鏈郴鍒楃洰褰?/h3>
- 杩炶浇涓€ Golang浠嬬粛涓庣幆澧冨畨瑁?/a>
- 杩炶浇浜?鎼缓Blog API's锛堜竴锛?/a>
- 杩炶浇涓?鎼缓Blog API's锛堜簩锛?/a>
- 杩炶浇鍥?鎼缓Blog API's锛堜笁锛?/a>
- 杩炶浇浜?浣跨敤JWT杩涜韬唤鏍¢獙
- 杩炶浇鍏?缂栧啓涓€涓畝鍗曠殑鏂囦欢鏃ュ織
- 杩炶浇涓?Golang浼橀泤閲嶅惎HTTP鏈嶅姟
- 杩炶浇鍏?涓哄畠鍔犱笂Swagger
- 杩炶浇涔?灏咷olang搴旂敤閮ㄧ讲鍒癉ocker
- 杩炶浇鍗?瀹氬埗 GORM Callbacks
- 杩炶浇鍗佷竴 Cron瀹氭椂浠诲姟
- 杩炶浇鍗佷簩 浼樺寲閰嶇疆缁撴瀯鍙婂疄鐜板浘鐗囦笂浼?/a>
- 杩炶浇鍗佷笁 浼樺寲浣犵殑搴旂敤缁撴瀯鍜屽疄鐜癛edis缂撳瓨
- 杩炶浇鍗佸洓 瀹炵幇瀵煎嚭銆佸鍏?Excel
- 杩炶浇鍗佷簲 鐢熸垚浜岀淮鐮併€佸悎骞舵捣鎶?/a>
- 杩炶浇鍗佸叚 鍦ㄥ浘鐗囦笂缁樺埗鏂囧瓧
- 杩炶浇鍗佷竷 鐢?Nginx 閮ㄧ讲 Go 搴旂敤
- 鐣 Golang浜ゅ弶缂栬瘧
- 鐣 璇峰叆闂?Makefile
鏈郴鍒楃洰褰?/h3>
- 杩炶浇涓€ Golang浠嬬粛涓庣幆澧冨畨瑁?/a>
- 杩炶浇浜?鎼缓Blog API's锛堜竴锛?/a>
- 杩炶浇涓?鎼缓Blog API's锛堜簩锛?/a>
- 杩炶浇鍥?鎼缓Blog API's锛堜笁锛?/a>
- 杩炶浇浜?浣跨敤JWT杩涜韬唤鏍¢獙
- 杩炶浇鍏?缂栧啓涓€涓畝鍗曠殑鏂囦欢鏃ュ織
- 杩炶浇涓?Golang浼橀泤閲嶅惎HTTP鏈嶅姟
- 杩炶浇鍏?涓哄畠鍔犱笂Swagger
- 杩炶浇涔?灏咷olang搴旂敤閮ㄧ讲鍒癉ocker
- 杩炶浇鍗?瀹氬埗 GORM Callbacks
- 杩炶浇鍗佷竴 Cron瀹氭椂浠诲姟
- 杩炶浇鍗佷簩 浼樺寲閰嶇疆缁撴瀯鍙婂疄鐜板浘鐗囦笂浼?/a>
- 杩炶浇鍗佷笁 浼樺寲浣犵殑搴旂敤缁撴瀯鍜屽疄鐜癛edis缂撳瓨
- 杩炶浇鍗佸洓 瀹炵幇瀵煎嚭銆佸鍏?Excel
- 杩炶浇鍗佷簲 鐢熸垚浜岀淮鐮併€佸悎骞舵捣鎶?/a>
- 杩炶浇鍗佸叚 鍦ㄥ浘鐗囦笂缁樺埗鏂囧瓧
- 杩炶浇鍗佷竷 鐢?Nginx 閮ㄧ讲 Go 搴旂敤
- 鐣 Golang浜ゅ弶缂栬瘧
- 鐣 璇峰叆闂?Makefile
到这里,我们也就讲完了《Golang Gin瀹炶返 杩炶浇鍗佷簲 鐢熸垚浜岀淮鐮併€佸悎骞舵捣鎶?/a>》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于mysql的知识点!

- 上一篇
- groupBy和orderBy的替代方案

- 下一篇
- 新手填坑:windows下初次使用MySQL数据库
-
- 数据库 · MySQL | 6小时前 |
- MySQL数据归档没那么难,手把手教你制定归档策略
- 128浏览 收藏
-
- 数据库 · MySQL | 6小时前 |
- MySQL数据库入门:深度解读特点+优势,小白也能懂!
- 352浏览 收藏
-
- 数据库 · MySQL | 7小时前 |
- MySQL查询优化or索引这样用,性能直接起飞!
- 299浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- MySQL缓存怎么配?查询缓存到底香不香?
- 156浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- MySQL装在D盘?手把手教你从自定义安装到配置一条龙!
- 486浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- MySQL主键是什么?主键的定义+作用超详细解读
- 485浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- MySQL出现中文乱码?超详细解决方案教程
- 158浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- MySQL性能监控这样搞,监控指标全都有!
- 327浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 42次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 62次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 72次使用
-
- 稿定PPT
- 告别PPT制作难题!稿定PPT提供海量模板、AI智能生成、在线协作,助您轻松制作专业演示文稿。职场办公、教育学习、企业服务全覆盖,降本增效,释放创意!
- 67次使用
-
- Suno苏诺中文版
- 探索Suno苏诺中文版,一款颠覆传统音乐创作的AI平台。无需专业技能,轻松创作个性化音乐。智能词曲生成、风格迁移、海量音效,释放您的音乐灵感!
- 70次使用
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览