初始化

This commit is contained in:
2025-11-25 11:51:16 +08:00
parent 252c98b149
commit f87bd9f52a
5 changed files with 325 additions and 0 deletions

24
consul/consul.go Normal file
View File

@@ -0,0 +1,24 @@
package consul
import (
"context"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/nosql/redis/v2"
"github.com/gogf/gf/contrib/registry/consul/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gsvc"
_ "go.mongodb.org/mongo-driver/mongo"
)
func init() {
consulCfg, err := g.Cfg().Get(context.Background(), "consul.address")
if err != nil {
panic(err)
}
consulAddr := consulCfg.String()
registry, err := consul.New(consul.WithAddress(consulAddr))
if err != nil {
panic(err)
}
gsvc.SetRegistry(registry)
}

77
http/http.go Normal file
View File

@@ -0,0 +1,77 @@
package http
import (
"context"
"errors"
"gitee.com/red-future---jilin-g/common/utils"
"github.com/gogf/gf/contrib/registry/consul/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gclient"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/net/gsel"
"github.com/gogf/gf/v2/net/gsvc"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/util/gconv"
"net/http"
)
type ResponseEmpty struct {
}
const PageSize = 20
type Page struct {
PageNum int `p:"pageNum"` //当前页码
PageSize int `p:"pageSize"` //每页数
Total int //总页数
}
func getHttpClient(ctx context.Context) (client *gclient.Client, err error) {
consulCfg, _ := g.Cfg().Get(context.Background(), "consul.address")
consulAddr := consulCfg.String()
registry, err := consul.New(consul.WithAddress(consulAddr))
if err != nil {
return
}
gsvc.SetRegistry(registry)
gsel.SetBuilder(gsel.NewBuilderRoundRobin())
client = g.Client()
client.SetHeader("Authorization", g.RequestFromCtx(ctx).GetHeader("Authorization"))
client.SetDiscovery(gsvc.GetRegistry())
return
}
func doRequest(ctx context.Context, method string, url string, target any, data ...any) (err error) {
err = utils.ValidStructPtr(target)
if err != nil {
return
}
client, err := getHttpClient(ctx)
if err != nil {
return
}
response, err := client.Get(ctx, method, url, data)
if err != nil {
return
}
defer func() {
if err = response.Close(); err != nil {
glog.Errorf(ctx, `%+v`, err)
}
}()
result := response.ReadAll()
resultStrut := &ghttp.DefaultHandlerResponse{}
if gconv.Struct(result, resultStrut); resultStrut.Code != 200 {
err = errors.New(resultStrut.Message)
} else {
gconv.Struct(resultStrut.Data, target)
}
return
}
func Get(ctx context.Context, url string, target any, data ...any) (err error) {
err = doRequest(ctx, http.MethodGet, url, target, data)
return
}
func Post(ctx context.Context, url string, target any, data ...any) (err error) {
err = doRequest(ctx, http.MethodPost, url, target, data)
return
}

75
jaeger/jaeger.go Normal file
View File

@@ -0,0 +1,75 @@
package jaeger
import (
"context"
"encoding/json"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/util/gconv"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
"strconv"
)
var Tp = new(trace.TracerProvider)
func init() {
jaegerAgent, err := g.Cfg().Get(context.Background(), "jaeger.addr")
if err != nil {
panic(err)
}
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(gconv.String(jaegerAgent))))
if err != nil {
panic(err)
}
serverName, err := g.Cfg().Get(context.Background(), "consul.Name")
if err != nil {
panic(err)
}
// 创建一个 TracerProvider并将 Jaeger exporter 设置为其处理器
Tp = trace.NewTracerProvider(
// 使用 BatchSpanProcessor 可以提高性能,它会批量发送 span
trace.WithBatcher(exp),
// 设置资源属性,这些属性会附加到所有导出的 span 上
trace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName(gconv.String(serverName)), // 服务名称,在 Jaeger UI 中会显示
)),
)
// 将 TracerProvider 设置为全局,方便在应用的任何地方通过 otel.Tracer() 获取
otel.SetTracerProvider(Tp)
}
func NewTracer(r *ghttp.Request) {
// 从传入的上下文中获取 Tracer或者直接使用全局的
tracer := otel.Tracer(r.GetServeHandler().GetMetaTag("summary"))
_, span := tracer.Start(r.Context(), r.GetServeHandler().GetMetaTag("summary"))
defer span.End() // 非常重要:确保 span 在函数结束时被关闭
span.SetAttributes(attribute.String("request", getParams(r)))
r.Middleware.Next()
span.SetAttributes(attribute.String("response", r.Response.BufferString()))
//span.AddEvent("Saying hello is done")
}
func getParams(r *ghttp.Request) string {
params := map[string]interface{}{}
if r.Method == "POST" {
json.Unmarshal(r.GetBody(), &params) //获取raw传参
}
if r.Method == "GET" {
r.Request.ParseForm()
form := r.Form
for k, v := range form {
if vl, e := strconv.Atoi(v[0]); e == nil {
params[k] = vl
} else {
params[k] = v[0]
}
}
}
rp, _ := json.Marshal(&params)
return string(rp)
}

96
mongo/mongo.go Normal file
View File

@@ -0,0 +1,96 @@
package mongo
import (
"context"
"gitee.com/red-future---jilin-g/common/utils"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/text/gstr"
"go.mongodb.org/mongo-driver/bson/primitive"
"strings"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var db = new(mongo.Database)
func init() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
link, _ := g.Cfg().Get(context.Background(), "mongo.address")
mongoAddr := link.String()
client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoAddr))
if err != nil {
glog.Error(ctx, "mongodb连接失败")
}
dbName := gstr.SubStr(mongoAddr, strings.LastIndex(mongoAddr, "/")+1, len(mongoAddr))
db = client.Database(dbName)
}
// Find 查询多条记录
func Find(ctx context.Context, filter *primitive.M, result interface{}, collection string, opts ...*options.FindOptions) (err error) {
if err = utils.ValidStructPtr(result); err != nil {
return
}
cur, err := db.Collection(collection).Find(ctx, filter, opts...)
if err != nil {
return
}
err = cur.All(ctx, result)
return
}
// FindOne 查询1条记录
func FindOne(ctx context.Context, filter *primitive.M, result interface{}, collection string, opts ...*options.FindOneOptions) (err error) {
if len(*filter) == 0 {
err = gerror.New("缺少查询条件")
return
}
if err = utils.ValidStructPtr(result); err != nil {
return
}
cur := db.Collection(collection).FindOne(ctx, filter, opts...)
if err != nil {
return
}
err = cur.Decode(result)
if err == mongo.ErrNoDocuments {
err = nil
}
return
}
// Delete 删除记录
func Delete(ctx context.Context, filter *primitive.M, collection string, opts ...*options.DeleteOptions) (count int64, err error) {
r, err := db.Collection(collection).DeleteMany(ctx, filter, opts...)
if err != nil {
return
}
count = r.DeletedCount
return
}
// Update 修改记录
func Update(ctx context.Context, filter *primitive.M, update interface{}, result *mongo.UpdateResult, collection string, opts ...*options.UpdateOptions) (err error) {
if err = utils.ValidStructPtr(result); err != nil {
return
}
result, err = db.Collection(collection).UpdateMany(ctx, filter, update, opts...)
if err != nil {
return
}
return
}
// Insert 修改记录
func Insert(ctx context.Context, documents []interface{}, collection string, opts ...*options.InsertManyOptions) (ids []interface{}, err error) {
r, err := db.Collection(collection).InsertMany(ctx, documents, opts...)
if err != nil {
return
}
ids = r.InsertedIDs
return
}

53
utils/utils.go Normal file
View File

@@ -0,0 +1,53 @@
package utils
import (
"fmt"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"reflect"
"time"
)
// ValidStructPtr 验证是否为结构体指针
func ValidStructPtr(req any) (err error) {
//验证请求参数必须为指针
var (
reflectValue reflect.Value
reflectKind reflect.Kind
)
if v, ok := req.(reflect.Value); ok {
reflectValue = v
} else {
reflectValue = reflect.ValueOf(req)
}
reflectKind = reflectValue.Kind()
if reflectKind != reflect.Ptr {
err = gerror.NewCode(gcode.CodeInvalidParameter, `the parameter "req" for function Find should type of *struct/*[]struct`)
}
return
}
// GetMonthToday 获取N个月前的某日
func GetMonthToday(t time.Time, month int) time.Time {
// today
fmt.Printf("today: [%s]\n", t)
// 判断天数范围 小于等于28天的计算,覆盖大多数情况
if t.Day() <= 28 {
return t.AddDate(0, -month, 0)
}
// 月份的天数数组
monthDay := [13]int{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
// 计算目标所在日期
target := t.AddDate(0, 0, 1-t.Day()).AddDate(0, -month, 0)
// 计算当月最大天数
targetDay := monthDay[target.Month()]
// 计算闰年
if target.Month() == time.February && (target.Year()%400 == 0 || (target.Year()%100 != 0 && target.Year()%4 == 0)) {
targetDay++
}
if t.Day() > targetDay {
return target.AddDate(0, 0, targetDay-1)
}
return target.AddDate(0, 0, t.Day()-1)
}