分类 技术 下的文章

1、安装swag
go get -u github.com/swaggo/swag/cmd/swag
2、安装gin-swagger
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
3、代码例子

package main

import (
   "github.com/gin-gonic/gin"
   docs "github.com/go-project-name/docs"
   swaggerfiles "github.com/swaggo/files"
   ginSwagger "github.com/swaggo/gin-swagger"
   "net/http"
)
// @BasePath /api/v1

// PingExample godoc
// @Summary ping example
// @Schemes
// @Description do ping
// @Tags example
// @Accept json
// @Produce json
// @Success 200 {string} Helloworld
// @Router /example/helloworld [get]
func Helloworld(g *gin.Context)  {
   g.JSON(http.StatusOK,"helloworld")
}

func main()  {
   r := gin.Default()
   docs.SwaggerInfo.BasePath = "/api/v1"
   v1 := r.Group("/api/v1")
   {
      eg := v1.Group("/example")
      {
         eg.GET("/helloworld",Helloworld)
      }
   }
   r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
   r.Run(":8080")

}

4、访问地址
http://localhost:8080/swagger/index.html


生成doc文档用法(官方说明文档): 运行swag init, 默认会在main.go目录下生成docs文件夹.

swag init -h
NAME:
   swag init - Create docs.go

USAGE:
   swag init [command options] [arguments...]

OPTIONS:
   --generalInfo value, -g value          API通用信息所在的go源文件路径,如果是相对路径则基于API解析目录 (默认: "main.go")
   --dir value, -d value                  API解析目录 (默认: "./")
   --exclude value                        解析扫描时排除的目录,多个目录可用逗号分隔(默认:空)
   --propertyStrategy value, -p value     结构体字段命名规则,三种:snakecase,camelcase,pascalcase (默认: "camelcase")
   --output value, -o value               文件(swagger.json, swagger.yaml and doc.go)输出目录 (默认: "./docs")
   --parseVendor                          是否解析vendor目录里的go源文件,默认不
   --parseDependency                      是否解析依赖目录中的go源文件,默认不
   --parseDependencyLevel, --pdl          对'--parseDependency'参数进行增强, 是否解析依赖目录中的go源文件, 0 不解析, 1 只解析对象模型, 2 只解析API, 3 对象模型和API都解析 (default: 0)
   --markdownFiles value, --md value      指定API的描述信息所使用的markdown文件所在的目录
   --generatedTime                        是否输出时间到输出文件docs.go的顶部,默认是
   --codeExampleFiles value, --cef value  解析包含用于 x-codeSamples 扩展的代码示例文件的文件夹,默认禁用
   --parseInternal                        解析 internal 包中的go文件,默认禁用
   --parseDepth value                     依赖解析深度 (默认: 100)
   --instanceName value                   设置文档实例名 (默认: "swagger")

模型定义:

type TestModel struct {
    // 名称
    Name int `json:"name" example:"名称"`
}

方法定义:

// test
// @Tags test
// @Summary test
// @Description test
// @Accept application/json
// @Produce application/json
// @Param  params body TestModel true "name参数"
// @Success 200 {object} response.Response{requestId=string,code=int,data=TestModel,msg=string} "错误码10101: 系统繁忙,请稍后再试(数据处理失败); 错误码20102: 请求参数错误"
// @Router /test [post]
func (t *Test) Test(c *gin.Context) {
   // 逻辑实现...
}

下载 MySQL 8.0 官方仓库包

wget https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm

或者使用 curl

curl -O https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm

安装仓库包

sudo rpm -ivh mysql80-community-release-el7-7.noarch.rpm

导入所有可能的 MySQL GPG 密钥

sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023

安装 MySQL 服务器

sudo yum install mysql-community-server

安装后:

1. 启动 MySQL/MariaDB

sudo systemctl start mysqld # MySQL

sudo systemctl start mariadb # MariaDB

2. 设置开机自启

sudo systemctl enable mysqld

sudo systemctl enable mariadb

3. 获取临时密码(仅 MySQL)

sudo grep 'temporary password' /var/log/mysqld.log

4. 安全配置

sudo mysql_secure_installation

用临时密码登录后修改密码:

1. 使用临时密码登录 MySQL

mysql -u root -p

输入临时密码

2. 设置新密码(MySQL 8.0)

ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewPassword123!';

或者 MySQL 5.7

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('YourNewPassword123!');

3. 刷新权限

FLUSH PRIVILEGES;

1、下载protobuf编译器,并配置到环境变量中
https://github.com/protocolbuffers/protobuf/releases/download/v35.0/protoc-35.0-win64.zip

2、验证是否安装成功:
protoc --version

3、写proto测试文件test.proto:

syntax = "proto3";
package api;     // 指定默认包名

// 指定golang包名
option go_package = "./";

message Test {
  string msg = 1;
}

4、生成proto的go代码文件:
protoc --go_out=.\proto\api --go-grpc_out=.\proto\api test.proto (其中--go_out=<指定生成数据层代码路径> --go-grpc_out=<指定生成服务层代码路径>)

5、调用例子
服务端代码:

lis, err := net.Listen("tcp", "0.0.0.0:8002"))
if err != nil {
    log.Fatalf("failed to listen: %v", err)
}
// s := grpc.NewServer(grpc.Creds(insecure.NewCredentials()))
s := grpc.NewServer()
pb.RegisterApiServer(s, api.APIService)
pb.RegisterGreeterServer(s, api.NewTestApiService())
if err := s.Serve(lis); err != nil {
    log.Fatalf("failed to serve: %v", err)
}

func NewTestApiService() *testApiService {
return &testApiService{}
} 

type testApiService struct {
pb.UnimplementedGreeterServer
}

func (h *testApiService) SayHello(context context.Context, req *pb.HelloRequest) (*pb.HelloResponse,   error) {
log.Printf("Received: %v", req.Name)

return &pb.HelloResponse{
    Message:   fmt.Sprintf("Hello %s (age: %d)", req.Name, req.Age),
    Timestamp: time.Now().Format(time.RFC3339),
}, nil
}


客户端代码:

var conn *grpc.ClientConn
conn, err := grpc.Dial("localhost:8002",
    grpc.WithTransportCredentials(insecure.NewCredentials()),
    grpc.WithKeepaliveParams(keepalive.ClientParameters{
        Time: 5 * time.Second,
    }),
)
defer conn.Close()
if err != nil {
    fmt.Println("rpc连接错误", err.Error())
}

client := pb.NewGreeterClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

fmt.Println("已经链接rpc服务器成功")

resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "World", Age: 35})
if err != nil {
    fmt.Println("rpc测试请求报错", err.Error())
}
fmt.Println("rpc测试请求返回", resp)

log.Printf("Response: %s", resp.Message)









原理图:
deepseek_mermaid_20250825_b2d79a.png

流程图:
deepseek_mermaid_20250825_c8512c.png

其详细步骤分解如下:
1、用户点击登录按钮:
用户在一个第三方应用(客户端)上点击“使用微信登录”。

2、重定向到授权服务器:
客户端将用户重定向到微信的授权服务器(Authorization Server),并携带以下关键信息:
response_type=code(表明使用授权码模式)
client_id(第三方应用的标识ID,提前在微信开放平台注册的)
redirect_uri(授权成功后用户被重定向回客户端的地址)
scope(申请的权限范围,如 read_contacts)
state(一个随机生成的字符串,用于防止CSRF攻击)

3、用户认证与授权:
用户在微信的页面上输入用户名和密码进行登录(确保密码不会泄露给第三方应用)。
登录成功后,微信会向用户展示一个授权页面,列出第三方应用申请的权限(如“获取你的好友列表”)。
用户选择是否同意授权。

4、颁发授权码(Authorization Code):
如果用户同意授权,授权服务器会将用户重定向回第一步提供的 redirect_uri,并在URL中附带一个授权码(Code) 和之前传来的 state。
https://client.example.com/callback?code=AUTH_CODE_HERE&state=xyz

5、换取访问令牌(Access Token):
关键步骤:第三方应用的后端服务器(而不是浏览器前端)收到授权码后,会向授权服务器的令牌端点(Token Endpoint)发起一个后台的、服务器到服务器的请求。这个请求包含:
grant_type=authorization_code(声明授权类型)
code(上一步收到的授权码)
redirect_uri(必须与第一步的完全一致)
client_id 和 client_secret(应用密钥,用于证明自己的身份,必须保密!)
这个请求是后端发起的,避免了 client_secret 暴露给前端。

6、颁发访问令牌:
授权服务器验证所有信息:client_id/client_secret 是否匹配、授权码是否有效、重定向URI是否正确。
验证通过后,授权服务器会返回一个 JSON 数据,里面包含:
access_token: 期盼已久的访问令牌。
refresh_token: (可选)刷新令牌。
expires_in: 访问令牌的过期时间(例如 7200 秒)。
token_type: 令牌类型,通常是 Bearer。

7、访问受保护资源:
现在,第三方应用的后端或前端(取决于场景)就可以使用这个 access_token 去向微信的资源服务器请求数据了。
通常在 API 请求的 Authorization 头中加入:Authorization: Bearer <access_token>。
资源服务器会验证这个令牌的有效性(签名、有效期、范围),然后返回请求的数据(如好友列表)。

8、刷新访问令牌(可选):
当 access_token 过期后,客户端可以使用 refresh_token 再次向授权服务器请求一个新的 access_token,而无需用户再次手动授权。