多服务器程序运行
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"golang.org/x/sync/errgroup"
"net/http"
"time"
)
var g errgroup.Group // 使用 errgroup.Group 来并发启动这两个服务器
func main() {
// 服务器1
server01 := &http.Server{
Addr: ":9090",
Handler: router01(),
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
// 服务器2
server02 := &http.Server{
Addr: ":9092", // 别问为啥不用 91,问就是被占用了
Handler: router02(),
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
// 分别启动监听
g.Go(func() error {
return server01.ListenAndServe()
})
g.Go(func() error {
return server02.ListenAndServe()
})
// 通过 g.Wait() 来等待它们的执行结果
if err := g.Wait(); err != nil {
fmt.Println("执行失败", err)
}
}
func router01() http.Handler {
r1 := gin.Default()
r1.GET("/MyServer01", func(context *gin.Context) {
context.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": "服务器程序1启动成功",
})
})
return r1
}
func router02() http.Handler {
r1 := gin.Default()
r1.GET("/MyServer02", func(context *gin.Context) {
context.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"msg": "服务器程序2启动成功",
})
})
return r1
}
路由组
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type ResGroup struct {
Data string
Path string
}
func main() {
router := gin.Default()
// 路由分组1
v1 := router.Group("/v1") // /v1
{
// 路由分组1.1
r := v1.Group("/user") // /v1/user
r.GET("/login", login) // /v1/user/login
// // 路由分组1.1.1
r2 := r.Group("showInfo") // /v1/user/showInfo
r2.GET("/abstract", abstract) // /v1/user/showInfo/abstract
r2.GET("/detail", detail) // /v1/user/showInfo/detail
}
// 路由分组2
v2 := router.Group("/v2") // v2
{
v2.GET("/other", other) // /v2/other
}
router.Run(":9090")
}
func other(context *gin.Context) {
context.JSON(http.StatusOK, ResGroup{"detail", context.Request.URL.Path})
}
func detail(context *gin.Context) {
context.JSON(http.StatusOK, ResGroup{"detail", context.Request.URL.Path})
}
func abstract(context *gin.Context) {
context.JSON(http.StatusOK, ResGroup{"abstract", context.Request.URL.Path})
}
func login(context *gin.Context) {
context.JSON(http.StatusOK, ResGroup{"login", context.Request.URL.Path})
}
路由结构
- v1
- user
- login
- showInfo
- abstract
- detail
- user
- v2
- other
gin框架 bind
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Login struct {
UserName string `json:"user_name" binding:"required"` // 后端字段 UserName → 前端参数 user_name,必需
Password string `json:"password" binding:"required"`
Remark string `json:"remark" binding:"required"`
}
func main() {
r := gin.Default()
r.POST("/login", func(context *gin.Context) {
var login Login
err := context.Bind(&login) // 执行绑定,注意参数是地址(引用),绑定的是前端传入的数据
if err != nil {
context.JSON(http.StatusBadRequest, gin.H{
"msg": "绑定失败,参数错误",
"data": err.Error(),
})
return
}
if login.UserName == "user" && login.Password == "123456" {
context.JSON(http.StatusBadRequest, gin.H{
"msg": "登陆成功",
"data": "OK",
})
return
}
context.JSON(http.StatusBadRequest, gin.H{
"msg": "登陆失败",
"data": "error",
})
return
})
r.Run(":9090")
}
调用 restful 接口
ps:将上一模块的代码打包成exe文件,并执行起来,注意端口冲突问题(命令:go build 文件名)
- 逻辑顺序:
- 客户端(真实) → 服务端
- 服务端(模拟客户端) →第三方接口
- 第三方接口→服务端(模拟客户端)
- 服务端→客户端(真实)
package main
import (
"bytes"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"io/ioutil"
"net/http"
"time"
)
// 第三方接口字段
type UserAPI struct {
UserName string `json:"user_name"`
Password string `json:"password"`
Remark string `json:"remark"`
}
// 第三方接口返回字段封装
type TempData struct {
Msg string `json:"msg"`
Data string `json:"data"`
}
// 客户端请求字段
type ClientRequest struct {
UserName string `json:"user_name"`
Password string `json:"password"`
Remark string `json:"remark"`
Other interface{} `json:"other"`
}
// 服务端返回字段
type ClientResponse struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
func main() {
//testAPI()
r := gin.Default()
r.POST("/getOtherAPI", getOtherAPI)
r.Run(":9092")
}
func getOtherAPI(context *gin.Context) {
var requestData ClientRequest
var response ClientResponse
err := context.Bind(&requestData) // 绑定请求数据
if err != nil {
response.Code = http.StatusBadRequest
response.Msg = "请求的参数错误"
response.Data = err
context.JSON(http.StatusBadRequest, response)
return
}
url := "http://127.0.0.1:9090/login"
user := UserAPI{requestData.UserName, requestData.Password, requestData.Remark}
data, err := getRestfulAPI(url, user, "application/json")
var temp TempData
json.Unmarshal(data, &temp) // 反序列化
response.Code = http.StatusOK
response.Msg = "请求数据成功"
response.Data = temp
context.JSON(http.StatusOK, response)
}
//func testAPI() {
// url := "http://127.0.0.1:9090/login"
// user := UserAPI{"user", "123456", "说明"}
// data, err := getRestfulAPI(url, user, "application/json")
// fmt.Println(data, err)
// var temp TempData
// json.Unmarshal(data, &temp)
// fmt.Println(temp)
//}
func getRestfulAPI(url string, data interface{}, contentType string) ([]byte, error) {
client := &http.Client{Timeout: 5 * time.Second} // 创建一个http客户端示例,去请求第三方
jsonStr, _ := json.Marshal(data) // 序列化数据
resp, err := client.Post(url, contentType, bytes.NewBuffer(jsonStr)) // 发起post请求
if err != nil {
fmt.Println("调用API接口出现了错误")
return nil, err
}
res, err := ioutil.ReadAll(resp.Body)
return res, err
}