2024年Go最全【Go开源宝藏】Web框架 GIN 专场 (含思维导图) 持续更新(3),2024年最新十多家大厂Golang面试真题锦集干货整理

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

import (
“github.com/gin-gonic/gin”
“net/http”
)

func main() {
r := gin.Default()
r.GET(“/user/:name/:action”, func(c *gin.Context) {
name := c.Param(“name”) // 使用Param可以获取路由URL里面的数据
action := c.Param(“action”)
c.String(http.StatusOK, name+" rush “+action)
})
_ = r.Run(”:8000")
}


* 获取表单参数,一般用于`POST`,`PUT`请求。


Gin提供了`.PostForm`方法获取Form表单的值。



package main

import (
“fmt”
“github.com/gin-gonic/gin”
“net/http”
)

func main() {
r := gin.Default()
r.POST(“/form”, func(c *gin.Context) {
username := c.PostForm(“username”)
password := c.PostForm(“password”)
c.String(http.StatusOK, fmt.Sprintf(“username:%s,password:%s”, username, password))
})
_ = r.Run(“:8000”)
}


### 1.4 文件上传与下载


#### 1.4.1 上传


* 提供了`.FormFile`来获取文件



package main

import (
“github.com/gin-gonic/gin”
)

func main() {
r := gin.Default()
r.POST(“/upload”, func(c *gin.Context) {
file, err := c.FormFile(“file”) // file是参数名称
if err != nil {
c.String(500, “上传图片出错”) //出错就会返回这个
}
c.SaveUploadedFile(file, file.Filename) // 保存文件
c.String(http.StatusOK, file.Filename) // 返回状态码
})
_ = r.Run(“:8000”)
}


#### 1.4.2 下载


### 1.5 路由拆分


我们一般来说,会把这个路由拆分成`URL`和`处理函数`。这样能高效管理我们的框架逻辑。



import (
“github.com/gin-gonic/gin”
“net/http”
)

func helloHandler(c *gin.Context) { // 把处理函数放在这里,可以处理一些复杂的业务
c.JSON(http.StatusOK, gin.H {
“message”: “Hello World!”, // 通过这个 gin.H{} 进行json格式的返回
})
}

// Router 配置路由信息
func Router() *gin.Engine {
r := gin.Default()
r.GET(“/hello”, helloHandler) // 这样这个路由就比较简洁了。
return r
}


## 2. 数据绑定


### 2.1 json数据格式


* 定义接收数据的结构体


`binding:"required"`修饰的字段,是必须有的,没有是会报错的。后面可以跟着限制,`满足限制`才不会报错。



type Product struct {
Name string form:"name" json:"name"
CategoryID int form:"category\_id" json:"category\_id"
Title string form:"title" json:"title" binding:"required,min=2,max=100"
Info string form:"info" json:"info" binding:"max=1000"
ImgPath string form:"img\_path" json:"img\_path"
Price string form:"price" json:"price"
DiscountPrice string form:"discount\_price" json:"discount\_price"
OnSale string form:"on\_sale" json:"on\_sale"
Num string form:"num" json:"num"
}


`gin`框架中提供了一个`ShouldBindJSON`方法,这样就能可以把`json格式`解析到`结构体`中。



func helloHandler(c *gin.Context) { // 把处理函数放在这里,可以处理一些复杂的业务
var data Product
if err := c.ShouldBindJSON(&data); err != nil {
// 进行数据的绑定,这样传过来的数据就会传入这个data当中
// gin.H封装了生成json数据的工具
c.JSON(http.StatusBadRequest, gin.H{“error”: err.Error()}) // 返回错误信息
return
}
c.JSON(http.StatusOK, gin.H{“status”: “200”})
}

// Router 配置路由信息
func Router() *gin.Engine {
r := gin.Default()
r.GET(“/hello”, helloHandler) // 这样这个路由就比较简洁了。
return r
}


### 2.2 form表单数据


同样的我们使用`2.1`中的`Product结构体`,注意一定要在结构体中,用`tags`标志`form`格式


上面的那个Product结构体是用tags标志了form格式和json格式的,所以两个都能用。



func helloHandler(c *gin.Context) { // 把处理函数放在这里,可以处理一些复杂的业务
var data Product
if err := c.Bind(&data); err != nil {
// Bind()默认解析并绑定form格式,这样传过来的数据就会传入这个data当中
c.JSON(http.StatusBadRequest, gin.H{“error”: err.Error()}) // 返回错误信息
return
}
c.JSON(http.StatusOK, gin.H{“status”: “200”})
}


### 2.3 URI



type Product struct {
Name string form:"name" json:"name" uri:"name”
CategoryID int form:"category\_id" json:"category\_id" uri:"category\_id"
Title string form:"title" json:"title" uri:“title binding:"required,min=2,max=100"
Info string form:"info" json:"info" uri:“info binding:"max=1000"
ImgPath string form:"img\_path" json:"img\_path" uri:"img\_path"
Price string form:"price" json:"price" uri:“price
DiscountPrice string form:"discount\_price" json:"discount\_price" uri:"discount\_price"
OnSale string form:"on\_sale" json:"on\_sale" uri:"on\_sale"
Num string form:"num" json:"num" uri:"num"
}


gin中提供了`ShouldBindUri`方法进行绑定



func helloHandler(c *gin.Context) { // 把处理函数放在这里,可以处理一些复杂的业务
var data Product
if err := c.ShouldBindUri(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{“error”: err.Error()}) // 返回错误信息
return
}
c.JSON(http.StatusOK, gin.H{“status”: “200”})
}



> 
> 无论是`ShouldBindJSON`还是`Bind`还是`ShouldBindUri`  
>  不过我个人比较喜欢用`c.ShouldBind()`这种,看个人喜欢吧~
> 
> 
> 


## 3. 参数验证


### 3.1 普通情况



type User struct {
Phone string form:"phone" binding:"required,gt=10" //不能为空并且大于10
Name string form:"name" binding:"required"
Birthday time.Time form:"birthday" time\_format:"2006-01-02"
// 满足格式才能接收,减少了if-else的判断
}


### 3.2 自定义情况


使用 `gopkg.in/go-playground/validator.v8` 包


* 在结构体上,绑定这个`NotNullAndAdmin`。



type User struct {
Phone string form:"phone" binding:"required,gt=10" //不能为空并且大于10
Name string form:"name" binding:"NotNullAndAdmin" // 自定义一个验证
Birthday time.Time form:"birthday" time\_format:"2006-01-02"
// 满足格式才能接收,减少了if-else的判断
}


* 编写自定义方法



func nameNotNullAndAdmin(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
if value, ok := field.Interface().(string); ok {
return value != “” && !(“admin” == value)// 字段不能为空,并且不等于 admin
}
return true
}


* 把我们的自定义注册到`validator`中就好了



if v, ok := binding.Validator.Engine().(\*validator.Validate); ok {
	\_ = v.RegisterValidation("NotNullAndAdmin", nameNotNullAndAdmin)  //注册定义的验证方法
}

## 4. 渲染


### 4.1 数据的响应


* Json 前后端主流的交互数据格式,我自己也是经常用这个。



func main() {
r := gin.Default()
r.GET(“/json”,JsonHandler)
_ = r.Run(“:8000”)
}

func JsonHandler(c *gin.Context) {
c.JSON(200, gin.H{“message”: “HelloJson”, “status”: 200})
}


* Struct



func main() {
r := gin.Default()
r.GET(“/struct”, StructHandler)
_ = r.Run(“:8000”)
}

func StructHandler(c *gin.Context) {
var msg struct {
Name string
Message string
Number int
}
msg.Name = “FanOne”
msg.Message = “Golang”
msg.Number = 10001
c.JSON(200, msg)
}


* XML



func main() {
r := gin.Default()
r.GET(“/xml”, XMLHandler)
_ = r.Run(“:8000”)
}

func XMLHandler(c *gin.Context) {
c.XML(200, gin.H{“message”: “HelloXml”})
}


* YAML



func main() {
r := gin.Default()
r.GET(“/yaml”, YAMLHandler)
_ = r.Run(“:8000”)
}

func YAMLHandler(c *gin.Context) {
c.YAML(200, gin.H{“message”: “HelloYaml”})
}


* ProtoBuf 这几年很火的数据格式



func main() {
r := gin.Default()
r.GET(“/protobuf”, ProtoBufHandler)
_ = r.Run(“:8000”)
}

func ProtoBufHandler(c *gin.Context) {
reps := []int64{int64(1), int64(2)}
// 定义数据
label := “label”
// 传protobuf格式数据
data := &protoexample.Test{
Label: &label,
Reps: reps,
}
c.ProtoBuf(200, data)
}


### 4.2 模板渲染



> 
> * gin支持加载HTML模板, 然后根据模板参数进行配置并返回相应的数据,本质上就是字符串替换
> * `LoadHTMLGlob()`方法可以加载模板文件
> * `Static`方法可以加载静态文件
> 
> 
> 


* 加载HTML模板



func main() {
r := gin.Default()
r.LoadHTMLGlob(“tempate/*”) // 加载你的模板文件 就是html文件嗷
r.GET(“/index”, func(c *gin.Context) {
c.HTML(http.StatusOK, “index.html”, gin.H{“msg”: “HelloWorld”, “status”: “200”})
})
r.Run()
}



![img](https://img-blog.csdnimg.cn/img_convert/7ce28783f12c58dd96c36b09533bbf87.png)
![img](https://img-blog.csdnimg.cn/img_convert/e2f21e9dc31903da1f5c0b944e5c4341.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618658159)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

    c.HTML(http.StatusOK, "index.html", gin.H{"msg": "HelloWorld", "status": "200"})
    })
    r.Run()
}

[外链图片转存中…(img-o6emSw37-1715372745477)]
[外链图片转存中…(img-ouITbN5y-1715372745478)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值