日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

gin 怎么通过 post 发送结构体_Go Web 框架 Gin 实践12—优化配置结构及实现图片上传...

發(fā)布時(shí)間:2024/7/23 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 gin 怎么通过 post 发送结构体_Go Web 框架 Gin 实践12—优化配置结构及实现图片上传... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Go語言中文網(wǎng),致力于每日分享編碼、開源等知識(shí),歡迎關(guān)注我,會(huì)有意想不到的收獲!

項(xiàng)目地址:https://github.com/EDDYCJY/go-gin-example

如果對(duì)你有所幫助,歡迎點(diǎn)個(gè) Star

前言

一天,產(chǎn)品經(jīng)理突然跟你說文章列表,沒有封面圖,不夠美觀,!)&¥*!&)#&¥*!加一個(gè)吧,幾分鐘的事

你打開你的程序,分析了一波寫了個(gè)清單:

  • 優(yōu)化配置結(jié)構(gòu)(因?yàn)榕渲庙?xiàng)越來越多)
  • 抽離 原 logging 的 File 便于公用(logging、upload 各保有一份并不合適)
  • 實(shí)現(xiàn)上傳圖片接口(需限制文件格式、大小)
  • 修改文章接口(需支持封面地址參數(shù))
  • 增加 blog_article (文章)的數(shù)據(jù)庫字段
  • 實(shí)現(xiàn) http.FileServer

嗯,你發(fā)現(xiàn)要較優(yōu)的話,需要調(diào)整部分的應(yīng)用程序結(jié)構(gòu),因?yàn)楣δ茉絹碓蕉?#xff0c;原本的設(shè)計(jì)也要跟上節(jié)奏

也就是在適當(dāng)?shù)臅r(shí)候,及時(shí)優(yōu)化

優(yōu)化配置結(jié)構(gòu)

一、講解

在先前章節(jié)中,采用了直接讀取 KEY 的方式去存儲(chǔ)配置項(xiàng),而本次需求中,需要增加圖片的配置項(xiàng),總體就有些冗余了

我們采用以下解決方法:

  • 映射結(jié)構(gòu)體:使用 MapTo 來設(shè)置配置參數(shù)
  • 配置統(tǒng)管:所有的配置項(xiàng)統(tǒng)管到 setting 中

映射結(jié)構(gòu)體(示例)

在 go-ini 中可以采用 MapTo 的方式來映射結(jié)構(gòu)體,例如:

在這段代碼中,可以注意 ServerSetting 取了地址,為什么 MapTo 必須地址入?yún)⒛?#xff1f;

在 MapTo 中 typ.Kind() == reflect.Ptr 約束了必須使用指針,否則會(huì)返回 cannot map to non-pointer struct 的錯(cuò)誤。這個(gè)是表面原因

更往內(nèi)探究,可以認(rèn)為是 field.Set 的原因,當(dāng)執(zhí)行 val := reflect.ValueOf(v) ,函數(shù)通過傳遞 v 拷貝創(chuàng)建了 val,但是 val 的改變并不能更改原始的 v,要想 val 的更改能作用到 v,則必須傳遞 v 的地址

顯然 go-ini 里也是包含修改原始值這一項(xiàng)功能的,你覺得是什么原因呢?

配置統(tǒng)管

在先前的版本中,models 和 file 的配置是在自己的文件中解析的,而其他在 setting.go 中,因此我們需要將其在 setting 中統(tǒng)一接管

你可能會(huì)想,直接把兩者的配置項(xiàng)復(fù)制粘貼到 setting.go 的 init 中,一下子就完事了,搞那么麻煩?

但你在想想,先前的代碼中存在多個(gè) init 函數(shù),執(zhí)行順序存在問題,無法達(dá)到我們的要求,你可以試試

(此處是一個(gè)基礎(chǔ)知識(shí)點(diǎn))

在 Go 中,當(dāng)存在多個(gè) init 函數(shù)時(shí),執(zhí)行順序?yàn)?#xff1a;

  • 相同包下的 init 函數(shù):按照源文件編譯順序決定執(zhí)行順序(默認(rèn)按文件名排序)
  • 不同包下的 init 函數(shù):按照包導(dǎo)入的依賴關(guān)系決定先后順序

所以要避免多 init 的情況,盡量由程序把控初始化的先后順序

二、落實(shí)

修改配置文件

打開 conf/app.ini 將配置文件修改為大駝峰命名,另外我們?cè)黾恿?5 個(gè)配置項(xiàng)用于上傳圖片的功能,4 個(gè)文件日志方面的配置項(xiàng)

[app]PageSize = 10JwtSecret = 233RuntimeRootPath = runtime/ImagePrefixUrl = http://127.0.0.1:8000ImageSavePath = upload/images/# MBImageMaxSize = 5ImageAllowExts = .jpg,.jpeg,.pngLogSavePath = logs/LogSaveName = logLogFileExt = logTimeFormat = 20060102[server]#debug or releaseRunMode = debugHttpPort = 8000ReadTimeout = 60WriteTimeout = 60[database]Type = mysqlUser = rootPassword = rootrootHost = 127.0.0.1:3306Name = blogTablePrefix = blog_

優(yōu)化配置讀取及設(shè)置初始化順序

第一步

將散落在其他文件里的配置都刪掉,統(tǒng)一在 setting 中處理以及修改 init 函數(shù)為 Setup 方法

打開 pkg/setting/setting.go 文件,修改如下:

在這里,我們做了如下幾件事:

  • 編寫與配置項(xiàng)保持一致的結(jié)構(gòu)體(App、Server、Database)
  • 使用 MapTo 將配置項(xiàng)映射到結(jié)構(gòu)體上
  • 對(duì)一些需特殊設(shè)置的配置項(xiàng)進(jìn)行再賦值

需要你去做的事:

  • 將 models.go、setting.go、pkg/logging/log.go 的 init 函數(shù)修改為 Setup 方法
  • 將 models/models.go 獨(dú)立讀取的 DB 配置項(xiàng)刪除,改為統(tǒng)一讀取 setting
  • 將 pkg/logging/file 獨(dú)立的 LOG 配置項(xiàng)刪除,改為統(tǒng)一讀取 setting

這幾項(xiàng)比較基礎(chǔ),并沒有貼出來,我希望你可以自己動(dòng)手,有問題的話可右拐 項(xiàng)目地址 https://github.com/EDDYCJY/go-gin-example

第二步

在這一步我們要設(shè)置初始化的流程,打開 main.go 文件,修改內(nèi)容:

修改完畢后,就成功將多模塊的初始化函數(shù)放到啟動(dòng)流程中了(先后順序也可以控制)

驗(yàn)證

在這里為止,針對(duì)本需求的配置優(yōu)化就完畢了,你需要執(zhí)行 go run main.go 驗(yàn)證一下你的功能是否正常哦

順帶留個(gè)基礎(chǔ)問題,大家可以思考下

ServerSetting.ReadTimeout = ServerSetting.ReadTimeout * time.SecondServerSetting.WriteTimeout = ServerSetting.ReadTimeout * time.Second

若將 setting.go 文件中的這兩行刪除,會(huì)出現(xiàn)什么問題,為什么呢?

抽離 File

在先前版本中,在 logging/file.go 中使用到了 os 的一些方法,我們通過前期規(guī)劃發(fā)現(xiàn),這部分在上傳圖片功能中可以復(fù)用

第一步

在 pkg 目錄下新建 file/file.go ,寫入文件內(nèi)容如下:

在這里我們一共封裝了 7個(gè) 方法

  • GetSize:獲取文件大小
  • GetExt:獲取文件后綴
  • CheckExist:檢查文件是否存在
  • CheckPermission:檢查文件權(quán)限
  • IsNotExistMkDir:如果不存在則新建文件夾
  • MkDir:新建文件夾
  • Open:打開文件

在這里我們用到了 mime/multipart 包,它主要實(shí)現(xiàn)了 MIME 的 multipart 解析,主要適用于 HTTP 和常見瀏覽器生成的 multipart 主體

multipart 又是什么,rfc2388 的 multipart/form-data 了解一下 https://tools.ietf.org/html/rfc2388

第二步

我們?cè)诘谝徊揭呀?jīng)將 file 重新封裝了一層,在這一步我們將原先 logging 包的方法都修改掉

1、打開 pkg/logging/file.go 文件,修改文件內(nèi)容:

我們將引用都改為了 file/file.go 包里的方法

2、打開 pkg/logging/log.go 文件,修改文件內(nèi)容:

由于原方法形參改變了,因此 openLogFile 也需要調(diào)整

實(shí)現(xiàn)上傳圖片接口

這一小節(jié),我們開始實(shí)現(xiàn)上次圖片相關(guān)的一些方法和功能

首先需要在 blog_article 中增加字段 cover_image_url,格式為 varchar(255) DEFAULT '' COMMENT '封面圖片地址'

第零步

一般不會(huì)直接將上傳的圖片名暴露出來,因此我們對(duì)圖片名進(jìn)行 MD5 來達(dá)到這個(gè)效果

在 util 目錄下新建 md5.go,寫入文件內(nèi)容:

第一步

在先前我們已經(jīng)把底層方法給封裝好了,實(shí)質(zhì)這一步為封裝 image 的處理邏輯

在 pkg 目錄下新建 upload/image.go 文件,寫入文件內(nèi)容:

在這里我們實(shí)現(xiàn)了 7 個(gè)方法,如下:

  • GetImageFullUrl:獲取圖片完整訪問URL
  • GetImageName:獲取圖片名稱
  • GetImagePath:獲取圖片路徑
  • GetImageFullPath:獲取圖片完整路徑
  • CheckImageExt:檢查圖片后綴
  • CheckImageSize:檢查圖片大小
  • CheckImage:檢查圖片

這里基本是對(duì)底層代碼的二次封裝,為了更靈活的處理一些圖片特有的邏輯,并且方便修改,不直接對(duì)外暴露下層

第二步

這一步將編寫上傳圖片的業(yè)務(wù)邏輯,在 routers/api 目錄下 新建 upload.go 文件,寫入文件內(nèi)容:

所涉及的錯(cuò)誤碼(需在 pkg/e/code.go、msg.go 添加):

// 保存圖片失敗ERROR_UPLOAD_SAVE_IMAGE_FAIL = 30001// 檢查圖片失敗ERROR_UPLOAD_CHECK_IMAGE_FAIL = 30002// 校驗(yàn)圖片錯(cuò)誤,圖片格式或大小有問題ERROR_UPLOAD_CHECK_IMAGE_FORMAT = 30003

在這一大段的業(yè)務(wù)邏輯中,我們做了如下事情:

  • c.Request.FormFile:獲取上傳的圖片(返回提供的表單鍵的第一個(gè)文件)
  • CheckImageExt、CheckImageSize檢查圖片大小,檢查圖片后綴
  • CheckImage:檢查上傳圖片所需(權(quán)限、文件夾)
  • SaveUploadedFile:保存圖片

總的來說,就是 入?yún)?-> 檢查 -》 保存 的應(yīng)用流程

第三步

打開 routers/router.go 文件,增加路由 r.POST("/upload

總結(jié)

以上是生活随笔為你收集整理的gin 怎么通过 post 发送结构体_Go Web 框架 Gin 实践12—优化配置结构及实现图片上传...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。