- 内置渲染:Gin 为 JSON,XML 和 HTML 渲染提供了易于使用的 API。
- 可扩展性:新建一个中间件非常简单。
1.2.2 Gin的使用
其他文档1:Golang gin框架
2 Gin面试问题
2.1 Gin里的路由转发都用到什么功能了
参考1:Gin路由
Gin中的路由系统的用于接收请求,并将请求转发给注册的中间件或请求处理器来处理。核心功能如下:
- 路由系统可根据请求方法,请求路径,和路径参数来识别转发。
- 可设置一个或多个中间件用于在请求处理器前后,处理特殊的事件。
- 可以分组设置,将一个或多个中间件作用在一组多个路由上。
2.2 鉴权的中间件是在Gin里写的还是怎么处理的
可以使用 gin-jwt:gin框架学习-JWT认证
2.3 Gin里面的中间件
Gin中的中间件实际上还是一个Gin中的 gin.HandlerFunc。中间都是需要注册后才能启用的。
中间件分类
:
全局中间件:全局中间件设置之后对全局的路由都起作用。
路由组中间件:路由组中间件仅对该路由组下面的路由起作用。
单个路由中间件:单个路由中间件仅对一个路由起作用。
2.4 Gin怎么对某些接口做日志记录
同 2.1 Gin里的路由转发都用到什么功能了?
参考1:Gin路由
核心功能:
- 路由系统可根据请求方法,请求路径,和路径参数来识别转发。
- 可设置一个或多个中间件用于在请求处理器前后,处理特殊的事件。
- 可以分组设置,将一个或多个中间件作用在一组多个路由上。
可以使用Gin路由的中间件功能,把要记录的接口封装到一个接口组中,然后注册中间件【方法】来处理。
2.5 为什么选择使用Gin框架
参考1:Gin框架介绍与基本使用
- Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点;
- 对于golang而言,web框架的依赖要远比Python,Java之类的要小。自身的net/http足够简单,性能也非常不错;
- 借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范;
- 由于使用了http router,速度提高了近40倍。 如果你是性能和高效的追求者, 你会爱上Gin;
2.6 Gin都有哪些包,这些包分别能处理哪些内容
参考1:golang入门笔记——Gin
参考2:浅谈Gin框架中bind
参考3:浅谈go语言renderer包代码分析
- binding包
Gin框架中的binding包,有bind函数可以非常方便的将url的查询参数query parameter、http的Header,body中提交上来的数据格式,如form,json,xml等,绑定到go中的结构体中去。 - render包
renderer是Go语言的一个简单的、轻量的、快速响应的呈现包,它可以支持JSON、JSONP、XML、HYAML、HTML、File等类型的响应。在开发web应用或RESTFul API的时候,这个包是非常方便的工具包。
2.7 实现了Gin里的哪些方法,往Gin里注册的是路由还是回调
注册的是路由。
2.8 Gin里对goroutine的处理模式有了解吗,或者说goroutine的处理是在Gin还是在外面的程序里?
Gin里,因为一个请求过来后,是可以再开一个协程来处理请求的,这个需要在Gin里才能启用协程。
2.9 Gin框架实现请求地址映射到方法的过程
- 创建Gin引擎
router := gin.Default()
- 定义路由和处理程序方法:在Gin中,路由定义使用HTTP请求方法(GET、POST、PUT、DELETE等)和URL模式来匹配请求的URL。每个路由都映射到一个处理程序方法(通常是一个闭包函数)。
- 启动Gin服务。
- 请求映射到处理程序方法:当收到HTTP请求时,Gin会根据请求的HTTP方法和URL路径来查找匹配的路由定义,并将请求映射到相应的处理程序方法。处理程序方法接收一个*gin.Context参数,该参数包含有关请求和响应的信息,可以用来读取请求参数、设置响应头、返回JSON数据等。
2.10 Gin是如何解决跨域的
可以在gin.Context.Writer.Header()
配置。
- Access-Control-Allow-Origin:必填,它的值要么是请求时
Origin
字段的值,要么是一个*
,表示接受任意域名的请求。 - Access-Control-Allow-Methods:必填,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。
- Access-Control-Allow-Headers:如果浏览器请求包括
Access-Control-Request-Headers
字段,则Access-Control-Allow-Headers
字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。 - Access-Control-Expose-Headers:可选,
CORS
请求时,XMLHttpRequest
对象的getResponseHeader()
方法只能拿到6个基本字段:Cache-Control
、Content-Language
、Content-Type
、Expires
、Last-Modified
、Pragma
。如果想拿到其他字段,就必须在Access-Control-Expose-Headers
里面指定。 - Access-Control-Allow-Credentials:可选,它的值是一个布尔值,表示是否允许发送
Cookie
。默认情况下,Cookie
不包括在CORS
请求之中。设为true
,即表示服务器明确许可,Cookie
可以包含在请求中,一起发给服务器。这个值也只能设为true
,如果服务器不要浏览器发送Cookie
,删除该字段即可。 - Access-Control-Max-Age:可选,用来指定本次预检请求的有效期,单位为秒,在此期间,不用发出另一条预检请求。
func CORS() gin.HandlerFunc {
return func(context *gin.Context) {
// 允许 Origin 字段中的域发送请求
context.Writer.Header().Add(“Access-Control-Allow-Origin”, *)
// 设置预验请求有效期为 86400 秒
context.Writer.Header().Set(“Access-Control-Max-Age”, “86400”)
// 设置允许请求的方法
context.Writer.Header().Set(“Access-Control-Allow-Methods”, “POST, GET, OPTIONS, PUT, DELETE, UPDATE, PATCH”)
// 设置允许请求的 Header
context.Writer.Header().Set(“Access-Control-Allow-Headers”, “Content-Type, Content-Length,Apitoken”)
// 设置拿到除基本字段外的其他字段,如上面的Apitoken, 这里通过引用Access-Control-Expose-Headers,进行配置,效果是一样的。
context.Writer.Header().Set(“Access-Control-Expose-Headers”, “Content-Length, Access-Control-Allow-Headers”)
// 配置是否可以带认证信息
context.Writer.Header().Set(“Access-Control-Allow-Credentials”, “true”)
// OPTIONS请求返回200
if context.Request.Method == “OPTIONS” {
fmt.Println(context.Request.Header)
context.AbortWithStatus(200)
} else {
context.Next()
}
}
}
3 个人笔记
3.1 加入网站图标ICON
下载依赖:github.com/thinkerou/favicon
图标位置:templates/favicon.ico
代码配置:
router := gin.Default()
router.Use(favicon.New(“templates/favicon.ico”))
3.2 文件上传功能
多文件上传:
put_file.html:
后端代码:
package main
import (
“fmt”
“github.com/gin-gonic/gin”
“github.com/satori/go.uuid”
“net/http”
“path”
“strings”
)
func Upload(c *gin.Context) {
单文件
//file, _ := c.FormFile(“file”)
//log.Println(file.Filename)
//
上传文件到项目根目录,使用原文件名
//c.SaveUploadedFile(file, file.Filename)
//
//c.String(http.StatusOK, fmt.Sprintf(“‘%s’ upload!”, file.Filename))
//多个文件
form, err := c.MultipartForm()
if err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf(“get err %s”, err.Error()))
}
// 获取所有图片
files := form.File[“files”]
// 遍历所有图片
for _, file := range files {
//获取文件名称带后缀
fileNameWithSuffix := path.Base(file.Filename)
//获取文件的后缀(文件类型)
fileType := path.Ext(fileNameWithSuffix)
//获取文件名称(不带后缀)
fileNameOnly := strings.TrimSuffix(fileNameWithSuffix, fileType)
fmt.Printf(“fileNameWithSuffix==%s\n fileType==%s;\n fileNameOnly==%s;”,
fileNameWithSuffix, fileType, fileNameOnly)
//生成UUID防止文件被覆盖
fileUUID := uuid.NewV4().String()
uuidName := strings.Replace(fileUUID, “-”, “”, -1)
dst := “F:\project\files\” + uuidName + fileType
// 逐个存
if err := c.SaveUploadedFile(file, dst); err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf(“upload err %s”, err.Error()))
return
}
}
c.String(http.StatusOK, fmt.Sprintf(“upload ok %d files”, len(files)))
}
func GoUpload(c *gin.Context) {
c.HTML(200, “put_file.html”, nil)
}
func main() {
r := gin.Default()
r.MaxMultipartMemory = 1024 << 20 //设置上传文件的最大内存1024MB
r.LoadHTMLGlob(“templates/*”)
r.GET(“/upload”, GoUpload)
r.POST(“/upload”, Upload)
r.Run()
}
文件的上传地址:直接复制WINDOWS
或LIUNX
下的文件路径即可。
示例:
- WINDOWS系统路径
F:\project\files
,代码中的路径F:\\project\\files\\
,注意在最后也要加\\
。 - LINUX系统路径:待操作。
3.3 文件下载
注意:在测试下载功能时,浏览器需要清缓存,否则会异常!!!!
视频、图片、音频,这三种既可以实现在浏览器端直接播放(预览),也可以改为直接下载。其他的文件类型都只能下载。
文件的本地路径和 1.5.2
一致。
代码:
package main
import (
“github.com/gin-gonic/gin”
)
//注意:在测试下载功能时,浏览器需要清缓存,否则会异常!!!!
func main() {
router := gin.Default()
//1、视频在线查看及下载
router.GET(“/video”, func(c *gin.Context) {
//1、如果是下载,则需要在Header中设置这两个参数
//c.Header(“Content-Type”, “application/octet-stream”)
//c.Header(“Content-Disposition”, “attachment; filename=Gin框架一小时上手.mp4”)
c.File(“F:\project\files\Gin框架一小时上手.mp4”)
})
//2、图片在线查看及下载
router.GET(“/image”, func(c *gin.Context) {
//1、如果是下载,则需要在Header中设置这两个参数
//c.Header(“Content-Type”, “application/octet-stream”)
//c.Header(“Content-Disposition”, “attachment; filename=IMG_20211004_113834.jpg”)
c.File(“F:\project\files\IMG_20211004_113834.jpg”)
})
//3、音频在线查看及下载
router.GET(“/mp3”, func(c *gin.Context) {
//1、如果是下载,则需要在Header中设置这两个参数
//c.Header(“Content-Type”, “application/octet-stream”)
//c.Header(“Content-Disposition”, “attachment; filename=吴景军 - 午后 (纯音乐) [mqms2].mp3”)
c.File(“F:\project\files\吴景军 - 午后 (纯音乐) [mqms2].mp3”)
})
//4、压缩包只能下载
router.GET(“/zip”, func(c *gin.Context) {
//1、如果是下载,则需要在Header中设置这两个参数
c.Header(“Content-Type”, “application/octet-stream”)
c.Header(“Content-Disposition”, “attachment; filename=nginx-1.19.2.zip”)
c.File(“F:\project\files\nginx-1.19.2.zip”)
})
//5、office文档下载(xlsx)
router.GET(“/xlsx”, func(c *gin.Context) {
//1、如果是下载,则需要在Header中设置这两个参数
c.Header(“Content-Type”, “application/octet-stream”)
c.Header(“Content-Disposition”, “attachment; filename=更新记录.xlsx”)
c.File(“F:\project\files\更新记录.xlsx”)
})
router.Run(“:8080”)
}
4 Gorm
4.1 Gorm文档
对于Gorm的学习,推荐看官网 https://gorm.io 文档。
4.2 Gorm版本区别
目前网上有两个地址在提供Gorm,分别是 github.com/jinzhu/gorm
和 gorm.io/gorm
。这两个有什么区别呢?
省流解释:
gorm.io/gorm
:是GORM 2.0
版本库的地址;github.com/jinzhu/gorm
:GORM 1.0
版本库的地址;gorm.io/gorm
使用的数据库驱动被拆分为独立的项目,例如:github.com/go-gorm/mysql
,且它的 import 路径也变更为gorm.io/driver/mysql
。
具体解释:
访问 Gorm官网:https://gorm.io(语言可以更换成中文),可以看到官方推荐的拉取Gorm的命令是:go get -u gorm.io/gorm
,同时注意到在下放的推介中出现了JINZHU
标签(红圈中),但此时我们仍然没有讲解两者的区别。
上图中,可以看到除了红圈,我还标注了V2 RELEASE NOTE
(黄圈),它是 Gorm 2.0
版本的文档,点进去查看GORM 2.0 发布说明
(语言切换成中文)。
在如何升级这一部分终于看到两者的区别了:
gorm.io/gorm
:是GORM 2.0
版本库的地址;github.com/jinzhu/gorm
:GORM 1.0
版本库的地址;gorm.io/gorm
使用的数据库驱动被拆分为独立的项目,例如:github.com/go-gorm/mysql
,且它的 import 路径也变更为gorm.io/driver/mysql
。
4.3 Gorm使用示例
package main
import (
“fmt”
“gorm.io/driver/mysql”
“gorm.io/gorm”
“gorm.io/gorm/schema”
“time”
)
type USocial struct {
ID string
SocialName string
SocialUrl string
IconUrl string
CreateUser string
CreateTime time.Time
UpdateUser string
UpdateTime time.Time
DelFlag string
}
func main() {
db, err := gorm.Open(mysql.Open(“root:root@tcp(localhost:3306)/blog?parseTime=true&loc=Asia%2FShanghai”), &gorm.Config{
//解决Gorm结构体和数据表映射时加 ”s”的问题
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
})
if err != nil {
panic(“failed to connect database”)
}
sqlDb, _ := db.DB()
sqlDb.SetMaxOpenConns(5)
sqlDb.SetMaxIdleConns(2)
sqlDb.SetConnMaxIdleTime(time.Minute)
// 迁移 schema
db.AutoMigrate(&USocial{})
// Read
var user USocial
db.First(&user, “id = ?”, “77a1daa8e26b49329c02c12bd3502edd”) // 查找 social_name 字段值为 微博 的记录
fmt.Println(user)
}
4.3.1 Gorm结构体和数据表映射时出现复数 “s”的问题
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Go语言工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Go语言全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
-1712868916004)]
[外链图片转存中…(img-4oLSdVbU-1712868916004)]
[外链图片转存中…(img-NoobEoN4-1712868916005)]
[外链图片转存中…(img-PdxHKZY5-1712868916005)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Golang知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-3AzWVy2l-1712868916006)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!