Go语言进行Web开发(Gin)、配置文件

创建项目

创建项目 z-wiki

新建main.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"github.com/gin-gonic/gin"
)

func helloHandler(c *gin.Context) {
c.JSON(200, gin.H{
"message": "hello world!",
})
}

func main() {
// 初始化gin对象
g := gin.Default()

// 设置一个get请求,其URL为/hello,并实现简单的响应
g.GET("/hello", helloHandler)

// 启动服务
g.Run()
}

目录下执行

1
2
go mod init z-wiki
go mod tidy

运行

1
go run main.go

访问:http://localhost:8080/hello

设置启动端口

1
2
port := "9999"
g.Run(":" + port)

允许跨域

下载

1
go get github.com/gin-contrib/cors

引用

1
import "github.com/gin-contrib/cors"

设置允许的域

1
2
3
4
5
6
7
8
9
func main() {
g := gin.Default()

corsConfig := cors.DefaultConfig()
corsConfig.AllowOrigins = []string{"http://www.psvmc.cn", "http://psvmc.cn"}
g.Use(cors.New(corsConfig))

g.Run()
}

允许所有

1
g.Use(cors.Default())

等效于

1
2
3
corsConfig := cors.DefaultConfig()
corsConfig.AllowOrigins = []string{"*"}
g.Use(cors.New(corsConfig))

允许Header

1
2
3
4
corsConfig := cors.DefaultConfig()
corsConfig.AllowOrigins = []string{"*"}
corsConfig.AllowHeaders = []string{"Content-Type", "Z-UserId"}
g.Use(cors.New(corsConfig))

路由拆分

main.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"z-wiki/routers"

"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)

func main() {
// 初始化gin对象
g := gin.Default()
g.Use(cors.Default())
routers.LoadUser(g)
// 启动服务
g.Run()
}

routers/user_router.go

1
2
3
4
5
6
7
8
9
10
11
12
13
package routers

import "github.com/gin-gonic/gin"

func LoadUser(e *gin.Engine) {
e.GET("/user/info", helloHandler)
}

func helloHandler(c *gin.Context) {
c.JSON(200, gin.H{
"name": "小明",
})
}

访问:http://localhost:8080/user/info

注意:

对其他包暴露的方法首字母要大写。

静态化与重定向

我们想项目的根路由重定向到项目的static/index.html

手相添加静态目录

1
2
// 设置静态文件目录
g.Static("/static", "./static")

添加路由重定向

routers/index_router.go

1
2
3
4
5
6
7
8
9
10
11
12
package routers

import (
"github.com/gin-gonic/gin"
)

func LoadIndex(e *gin.Engine) {
e.GET("/", func(c *gin.Context) {
// 重定向到新的路由
c.Redirect(301, "/static")
})
}

加载路由

1
routers.LoadIndex(g)

请求参数

URL中的参数

1
c.Query("userid")

Form参数

1
c.Param("userid")

JSON参数

在 Gin 框架中,你可以使用 ShouldBindJSON() 方法来获取 POST 请求中的 JSON 参数。

以下是一个示例代码,演示如何在 Go 中使用 Gin 框架获取请求的 JSON 参数:

假设有一个 POST 请求发送了一个 JSON 参数,如 {"name": "Alice", "age": 30}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

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

type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}

func main() {
r := gin.Default()

r.POST("/person", func(c *gin.Context) {
var person Person

if err := c.ShouldBindJSON(&person); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{
"name": person.Name,
"age": person.Age,
})
})

r.Run(":9999")
}

在上面的示例中,我们定义了一个 Person 结构体来表示 JSON 中的参数。在路由 /person 中,我们使用 ShouldBindJSON() 方法将请求的 JSON 参数绑定到 person 变量中。如果绑定成功,则返回 JSON 格式的姓名和年龄信息;如果绑定失败,则返回错误信息。

当发送 POST 请求到 http://localhost:9999/person 并携带 JSON 参数时,Gin 框架将解析请求中的 JSON 参数,并将其存储在 person 变量中。然后我们可以通过 person.Nameperson.Age 访问参数的值。

文件参数

1
2
file, err := c.FormFile("file")
userid := c.PostForm("userid")

请求Header

1
userId := c.Request.Header.Get("Z-UserId")

文件上传

file_router.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package routers

import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"os"
"path"
"path/filepath"
"strings"
"time"
"z-wiki/model"
)

func LoadFile(e *gin.Engine) {
e.POST("/file/upload", uploadHandler)
}

func uploadHandler(c *gin.Context) {
file, err := c.FormFile("file")
userid := c.PostForm("userid")
fmt.Println("userid:", userid)
if err != nil {
c.JSON(200, model.ResultVo[string]{Code: 1, Msg: "未找到文件", Obj: ""})
return
}
dateStr := time.Now().Format("200601")
pathStr := path.Join("static", "upload", dateStr)
err = os.MkdirAll(pathStr, os.ModePerm)
if err != nil {
c.JSON(200, model.ResultVo[string]{Code: 1, Msg: "上传失败", Obj: ""})
return
}

uuidStr := uuid.New().String()
fileExt := filepath.Ext(file.Filename)
filePathAll := path.Join(pathStr, uuidStr+strings.ToLower(fileExt))
fmt.Println("filePathAll", filePathAll)
err = c.SaveUploadedFile(file, filePathAll)
if err != nil {
c.JSON(200, model.ResultVo[string]{Code: 1, Msg: "上传失败", Obj: ""})
return
}
c.JSON(200, model.ResultVo[string]{Code: 0, Msg: "上传成功", Obj: filePathAll})
}

resultvo.go

1
2
3
4
5
6
7
package model

type ResultVo[T any] struct {
Code int `json:"code"`
Msg string `json:"msg"`
Obj T `json:"obj"`
}

配置读取

配置文件

config/config.json

1
2
3
4
5
6
{
"port":"8888",
"db_host": "dbtest.psvmc.cn",
"db_user": "zhangjian",
"db_pwd": "Test_123456"
}

工具类

utils/config_reader.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package utils

import (
"encoding/json"
"fmt"
"os"
)

type Config struct {
PORT string `json:"port"`
DBHost string `json:"db_host"`
DBUser string `json:"db_user"`
DBPwd string `json:"db_pwd"`
}

func ReadConfig() *Config {
file, err := os.Open("config/config.json")
if err != nil {
fmt.Println("Failed to open config file:", err)
return nil
}
defer file.Close()

decoder := json.NewDecoder(file)
config := Config{}
err = decoder.Decode(&config)
if err != nil {
fmt.Println("Failed to decode config file:", err)
return nil
}

return &config
}

调用

1
2
3
4
5
6
7
8
9
10
config := utils.ReadConfig()
if config == nil {
return
}
fmt.Println("-----------------------------")
fmt.Println("PORT:", config.PORT)
fmt.Println("DBHost:", config.DBHost)
fmt.Println("DBUser:", config.DBUser)
fmt.Println("DBPwd:", config.DBPwd)
fmt.Println("-----------------------------")

JSON序列化与反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
"encoding/json"
"fmt"
)

type Person struct {
Name string
Age int
}

func Json2Str() {
person := Person{Name: "Alice", Age: 30}
jsonData, err := json.Marshal(person)
if err != nil {
fmt.Println("转换失败:", err)
return
}
jsonString := string(jsonData)
fmt.Println("Json2Str:", jsonString)
}

func Str2Json() {
str := `{"Name": "Alice", "Age": 30}`
var person Person
err := json.Unmarshal([]byte(str), &person)
if err != nil {
fmt.Println("转换失败:", err)
return
}
fmt.Printf("Str2Json:%+v\n", person)
}