新建
This commit is contained in:
parent
5342989d8c
commit
394e3ba4b1
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[submodule "exhibition-register"]
|
||||||
|
path = exhibition-register
|
||||||
|
url = http://192.168.12.3:3000/exhibition/exhibition-register.git
|
||||||
|
branch = main
|
22
DockerfileProd
Normal file
22
DockerfileProd
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
FROM testhub.szjixun.cn:9043/public/golang:1.18-alpine AS builder
|
||||||
|
|
||||||
|
LABEL stage=gobuilder
|
||||||
|
ENV CGO_ENABLED 0
|
||||||
|
ENV GOPROXY https://goproxy.cn,direct
|
||||||
|
WORKDIR /build
|
||||||
|
COPY exhibition-register-server /app/exhibition-register-server
|
||||||
|
|
||||||
|
#FROM 172.16.100.99:9006/alpine
|
||||||
|
#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
#RUN apk update --no-cache
|
||||||
|
#RUN apk add --no-cache ca-certificates
|
||||||
|
#RUN apk add --no-cache tzdata
|
||||||
|
FROM testhub.szjixun.cn:9043/public/self-alpine
|
||||||
|
COPY ./conf /app/conf
|
||||||
|
|
||||||
|
ENV TZ Asia/Shanghai
|
||||||
|
ENV MODE_ENV prod
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/exhibition-register-server .
|
||||||
|
EXPOSE 20301
|
||||||
|
CMD ["/app/exhibition-register-server"]
|
16
DockerfileSlim
Normal file
16
DockerfileSlim
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
FROM busybox:glibc
|
||||||
|
|
||||||
|
COPY ./conf/Shanghai /usr/share/zoneinfo/Asia/Shanghai
|
||||||
|
COPY ./conf/certs /etc/ssl/certs
|
||||||
|
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
|
||||||
|
#ENV TZ Asia/Shanghai
|
||||||
|
|
||||||
|
WORKDIR /app/main-client
|
||||||
|
#通过名称引用
|
||||||
|
COPY ./build/app ./bin/mainServer
|
||||||
|
COPY ./conf/ /app/conf/
|
||||||
|
COPY ./conf/ ./conf/
|
||||||
|
COPY ./conf/ /app/main-client/bin/conf/
|
||||||
|
|
||||||
|
WORKDIR /app/main-client/bin
|
||||||
|
CMD ["./mainServer"]
|
22
DockerfileTest
Normal file
22
DockerfileTest
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
FROM testhub.szjixun.cn:9043/public/golang:1.18-alpine AS builder
|
||||||
|
|
||||||
|
LABEL stage=gobuilder
|
||||||
|
ENV CGO_ENABLED 0
|
||||||
|
ENV GOPROXY https://goproxy.cn,direct
|
||||||
|
WORKDIR /build
|
||||||
|
COPY exhibition-register-server /app/exhibition-register-server
|
||||||
|
|
||||||
|
#FROM 172.16.100.99:9006/alpine
|
||||||
|
#RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
|
#RUN apk update --no-cache
|
||||||
|
#RUN apk add --no-cache ca-certificates
|
||||||
|
#RUN apk add --no-cache tzdata
|
||||||
|
FROM testhub.szjixun.cn:9043/public/self-alpine
|
||||||
|
COPY ./conf /app/conf
|
||||||
|
|
||||||
|
ENV TZ Asia/Shanghai
|
||||||
|
ENV MODE_ENV k8stest
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/exhibition-register-server .
|
||||||
|
EXPOSE 20301
|
||||||
|
CMD ["/app/exhibition-register-server"]
|
2
clear.sh
Normal file
2
clear.sh
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
ls pb/exhibition/*.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}';
|
48
cmd/app.go
Normal file
48
cmd/app.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "dubbo.apache.org/dubbo-go/v3/filter/tps/strategy"
|
||||||
|
_ "dubbo.apache.org/dubbo-go/v3/imports"
|
||||||
|
_ "exhibition-register/internal/handler"
|
||||||
|
"exhibition-register/pkg/app"
|
||||||
|
"exhibition-register/pkg/tracing"
|
||||||
|
"github.com/bwmarrin/snowflake"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewApp(Lg *zap.Logger, JaegerTracer *tracing.JaegerProvider, SfNode *snowflake.Node, ExhibitionRegister *gorm.DB) *app.App {
|
||||||
|
return &app.App{
|
||||||
|
Lg: Lg,
|
||||||
|
JaegerTracer: JaegerTracer,
|
||||||
|
SfNode: SfNode,
|
||||||
|
ExhibitionRegister: ExhibitionRegister,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//func main() {
|
||||||
|
// var err error
|
||||||
|
// exhibitionConfig.GetOptions()
|
||||||
|
// app.ModuleClients, err = InitApp()
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //l, err := net.Listen("tcp", ":8883")
|
||||||
|
// //if err != nil {
|
||||||
|
// // fmt.Printf("failed to listen: %v", err)
|
||||||
|
// // return
|
||||||
|
// //}
|
||||||
|
// //
|
||||||
|
// //s := grpc.NewServer() // 创建gRPC服务器
|
||||||
|
// //dci.RegisterDciServer(s, &controller.DciProvider{}) // 在gRPC服务端注册服务
|
||||||
|
// // 启动服务
|
||||||
|
// //err = s.Serve(l)
|
||||||
|
// //注册服务
|
||||||
|
// config.SetProviderService(&controller.ExamProvider{})
|
||||||
|
// common.Init()
|
||||||
|
// if err = config.Load(); err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// select {}
|
||||||
|
//}
|
19
cmd/wire.go
Normal file
19
cmd/wire.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// go:build wireinject
|
||||||
|
//go:build wireinject
|
||||||
|
// +build wireinject
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"exhibition-register/pkg/app"
|
||||||
|
"exhibition-register/pkg/db"
|
||||||
|
"exhibition-register/pkg/logger"
|
||||||
|
"exhibition-register/pkg/snowf"
|
||||||
|
"exhibition-register/pkg/tracing"
|
||||||
|
"github.com/google/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitApp() (*app.App, error) {
|
||||||
|
wire.Build(logger.Provider, tracing.Provider, snowf.Provider, db.Provider, NewApp)
|
||||||
|
return &app.App{}, nil
|
||||||
|
}
|
27
conf/config.yaml
Normal file
27
conf/config.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
system:
|
||||||
|
mode: dev #正式 prod #测试 test # 开发 dev
|
||||||
|
config_source: config
|
||||||
|
exhibitionRegister:
|
||||||
|
host: 121.229.45.214
|
||||||
|
port: 9007
|
||||||
|
user: artuser
|
||||||
|
password: C250PflXIWv2SQm8
|
||||||
|
db_name: "exhibition_register"
|
||||||
|
zapLog:
|
||||||
|
level: "info"
|
||||||
|
filename: "logs/exhibition_register.log"
|
||||||
|
max_size: 5
|
||||||
|
max_age: 30
|
||||||
|
max_backups: 30
|
||||||
|
snowflake:
|
||||||
|
node_num: 4
|
||||||
|
start_time: "2024-01-29"
|
||||||
|
jaeger:
|
||||||
|
addr: "127.0.0.1:6831"
|
||||||
|
open: false
|
||||||
|
#rabbitmq:
|
||||||
|
# user: "myuser"
|
||||||
|
# password: "mypass"
|
||||||
|
# host: "localhost"
|
||||||
|
# port: 5672
|
||||||
|
# vhost: "oa"
|
@ -15,7 +15,7 @@ zapLog:
|
|||||||
max_backups: 30
|
max_backups: 30
|
||||||
snowflake:
|
snowflake:
|
||||||
node_num: 4
|
node_num: 4
|
||||||
start_time: "2023-12-20"
|
start_time: "2024-01-29"
|
||||||
jaeger:
|
jaeger:
|
||||||
addr: "127.0.0.1:6831"
|
addr: "127.0.0.1:6831"
|
||||||
open: false
|
open: false
|
||||||
|
69
conf/dubbogo.yaml
Normal file
69
conf/dubbogo.yaml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
dubbo:
|
||||||
|
metrics:
|
||||||
|
enable: true # default is true
|
||||||
|
path: /metrics # default is /metrics
|
||||||
|
port: 9092 # default is 9090
|
||||||
|
namespace: dubboExhibition # default is dubbo 作为数据上报 metrics 的前缀
|
||||||
|
registries:
|
||||||
|
demoZK:
|
||||||
|
protocol: zookeeper
|
||||||
|
timeout: 10s
|
||||||
|
address: 127.0.0.1:2181 #本地
|
||||||
|
# address: 114.218.158.24:2181 #测试环境
|
||||||
|
protocols:
|
||||||
|
triple: #triple
|
||||||
|
name: tri
|
||||||
|
port: 21501
|
||||||
|
provider:
|
||||||
|
filter: tracing
|
||||||
|
services:
|
||||||
|
ExhibitionProvider:
|
||||||
|
interface: com.fontree.microservices.common.Exhibition
|
||||||
|
retries: 0
|
||||||
|
filter: tps,tracing
|
||||||
|
tps.limiter: method-service
|
||||||
|
tps.limit.strategy: fixedWindow
|
||||||
|
tps.limit.rejected.handler: DefaultValueHandler
|
||||||
|
tps.limit.interval: 1000 # 间隔时间
|
||||||
|
tps.limit.rate: 30 # 间隔时间内次数
|
||||||
|
warmup: 100 #预热时间
|
||||||
|
logger:
|
||||||
|
zap-config:
|
||||||
|
level: info # 日志级别
|
||||||
|
development: false
|
||||||
|
disableCaller: false
|
||||||
|
disableStacktrace: false
|
||||||
|
encoding: "json"
|
||||||
|
# zap encoder 配置
|
||||||
|
encoderConfig:
|
||||||
|
messageKey: "message"
|
||||||
|
levelKey: "level"
|
||||||
|
timeKey: "time"
|
||||||
|
nameKey: "logger"
|
||||||
|
callerKey: "caller"
|
||||||
|
stacktraceKey: "stacktrace"
|
||||||
|
lineEnding: ""
|
||||||
|
levelEncoder: "capitalColor"
|
||||||
|
timeEncoder: "iso8601"
|
||||||
|
durationEncoder: "seconds"
|
||||||
|
callerEncoder: "short"
|
||||||
|
nameEncoder: ""
|
||||||
|
EncodeTime: zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000"),
|
||||||
|
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||||
|
outputPaths:
|
||||||
|
- "stderr"
|
||||||
|
errorOutputPaths:
|
||||||
|
- "stderr"
|
||||||
|
lumberjack-config:
|
||||||
|
# 写日志的文件名称
|
||||||
|
filename: "runtime/logs/exhibition_register.log"
|
||||||
|
# 每个日志文件长度的最大大小,单位是 MiB。默认 100MiB
|
||||||
|
maxSize: 5
|
||||||
|
# 日志保留的最大天数(只保留最近多少天的日志)
|
||||||
|
maxAge: 30
|
||||||
|
# 只保留最近多少个日志文件,用于控制程序总日志的大小
|
||||||
|
maxBackups: 30
|
||||||
|
# 是否使用本地时间,默认使用 UTC 时间
|
||||||
|
localTime: true
|
||||||
|
# 是否压缩日志文件,压缩方法 gzip
|
||||||
|
compress: false
|
@ -19,7 +19,7 @@ zapLog:
|
|||||||
max_backups: 30
|
max_backups: 30
|
||||||
snowflake:
|
snowflake:
|
||||||
node_num: 4
|
node_num: 4
|
||||||
start_time: "2023-12-20"
|
start_time: "2024-01-29"
|
||||||
jaeger:
|
jaeger:
|
||||||
addr: "127.0.0.1:6831"
|
addr: "127.0.0.1:6831"
|
||||||
open: false
|
open: false
|
||||||
|
@ -19,7 +19,7 @@ zapLog:
|
|||||||
max_backups: 30
|
max_backups: 30
|
||||||
snowflake:
|
snowflake:
|
||||||
node_num: 4
|
node_num: 4
|
||||||
start_time: "2023-12-20"
|
start_time: "2024-01-29"
|
||||||
jaeger:
|
jaeger:
|
||||||
addr: "127.0.0.1:6831"
|
addr: "127.0.0.1:6831"
|
||||||
open: false
|
open: false
|
||||||
|
@ -19,7 +19,7 @@ zapLog:
|
|||||||
max_backups: 30
|
max_backups: 30
|
||||||
snowflake:
|
snowflake:
|
||||||
node_num: 4
|
node_num: 4
|
||||||
start_time: "2023-12-20"
|
start_time: "2024-01-29"
|
||||||
jaeger:
|
jaeger:
|
||||||
addr: "127.0.0.1:6831"
|
addr: "127.0.0.1:6831"
|
||||||
open: false
|
open: false
|
||||||
|
152
config/config.go
Normal file
152
config/config.go
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/common/constant"
|
||||||
|
"exhibition-register/pkg/msg"
|
||||||
|
"fmt"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Data = new(AppConfig)
|
||||||
|
|
||||||
|
type AppConfig struct {
|
||||||
|
System struct {
|
||||||
|
Mode string
|
||||||
|
ConfigSource string `mapstructure:"config_source"`
|
||||||
|
}
|
||||||
|
ExhibitionRegister struct {
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
User string
|
||||||
|
Password string
|
||||||
|
DbName string `mapstructure:"db_name"`
|
||||||
|
}
|
||||||
|
Redis struct {
|
||||||
|
DB string
|
||||||
|
Addr string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
ZapLog struct {
|
||||||
|
Level string `mapstructure:"level"`
|
||||||
|
Filename string `mapstructure:"filename"`
|
||||||
|
MaxSize string `mapstructure:"max_size"`
|
||||||
|
MaxAge string `mapstructure:"max_age"`
|
||||||
|
MaxBackups string `mapstructure:"max_backups"`
|
||||||
|
}
|
||||||
|
SnowFlake struct {
|
||||||
|
NodeNum string `mapstructure:"node_num"`
|
||||||
|
StartTime string `mapstructure:"start_time"`
|
||||||
|
}
|
||||||
|
Jaeger struct {
|
||||||
|
Addr string `mapstructure:"host"`
|
||||||
|
Open string `mapstructure:"open"`
|
||||||
|
}
|
||||||
|
RabbitMq struct {
|
||||||
|
User string `mapstructure:"user"`
|
||||||
|
Password string `mapstructure:"password"`
|
||||||
|
Host string `mapstructure:"host"`
|
||||||
|
Port string `mapstructure:"port"`
|
||||||
|
Vhost string `mapstructure:"vhost"`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConf() (iniConf string, err error) {
|
||||||
|
if os.Getenv(msg.MODE_ENV) != "" {
|
||||||
|
if err = os.Setenv(constant.ConfigFileEnvKey, fmt.Sprintf("./conf/%s/%s", os.Getenv(msg.MODE_ENV), msg.SERVER_DUBBOGO_CONFIG)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if os.Getenv(msg.MODE_ENV) == "" {
|
||||||
|
iniConf = fmt.Sprintf("./conf/%s", msg.SERVER_CONFIG)
|
||||||
|
} else {
|
||||||
|
iniConf = fmt.Sprintf("./conf/%s/%s", os.Getenv(msg.MODE_ENV), msg.SERVER_CONFIG)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOptions() {
|
||||||
|
iniConf, err := GetConf()
|
||||||
|
if err != nil {
|
||||||
|
panic("GetOptions err" + err.Error())
|
||||||
|
}
|
||||||
|
if err = Viper(iniConf); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Viper(iniConf string) (err error) {
|
||||||
|
viper.SetConfigFile(iniConf)
|
||||||
|
err = viper.ReadInConfig()
|
||||||
|
if err != nil {
|
||||||
|
panic("viper.ReadInConfig failed" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = viper.Unmarshal(Data); err != nil {
|
||||||
|
panic("viper.Unmarshal failed" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 如果是configmap模式再修改
|
||||||
|
fmt.Println(Data.System)
|
||||||
|
if Data.System.ConfigSource == "configmap" {
|
||||||
|
traverseFields(reflect.ValueOf(*Data), "", Data)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func traverseFields(value reflect.Value, prefix string, configPtr interface{}) {
|
||||||
|
valueType := value.Type()
|
||||||
|
prefixEnv := "${"
|
||||||
|
suffixEnv := "}"
|
||||||
|
// 遍历结构体的字段
|
||||||
|
for i := 0; i < valueType.NumField(); i++ {
|
||||||
|
field := valueType.Field(i)
|
||||||
|
fieldValue := value.Field(i)
|
||||||
|
// 拼接字段名(带有前缀)
|
||||||
|
fieldName := prefix + field.Name
|
||||||
|
// 判断字段的类型
|
||||||
|
if fieldValue.Kind() == reflect.Struct {
|
||||||
|
// 递归遍历嵌套结构体字段
|
||||||
|
traverseFields(fieldValue, fieldName+".", configPtr)
|
||||||
|
} else {
|
||||||
|
// 获取字段的值
|
||||||
|
fieldValueStr := fmt.Sprintf("%v", fieldValue.Interface())
|
||||||
|
// 判断是不是需要通过环境变量获取
|
||||||
|
if len(fieldValueStr) > 3 && strings.HasPrefix(fieldValueStr, prefixEnv) && strings.HasSuffix(fieldValueStr, suffixEnv) {
|
||||||
|
end := len(fieldValueStr) - len(suffixEnv)
|
||||||
|
var hasDefault bool
|
||||||
|
if strings.Index(fieldValueStr, "|") > 0 {
|
||||||
|
hasDefault = true
|
||||||
|
end = strings.Index(fieldValueStr, "|")
|
||||||
|
}
|
||||||
|
envStr := fieldValueStr[len(prefixEnv):end]
|
||||||
|
getValue := os.Getenv(envStr)
|
||||||
|
if getValue == "" && hasDefault {
|
||||||
|
getValue = fieldValueStr[end+1 : len(fieldValueStr)-len(suffixEnv)]
|
||||||
|
}
|
||||||
|
setSubFieldValue(configPtr, fieldName, getValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSubFieldValue(configPtr interface{}, fieldPath string, newValue interface{}) {
|
||||||
|
value := reflect.ValueOf(configPtr).Elem()
|
||||||
|
fields := strings.Split(fieldPath, ".")
|
||||||
|
for _, field := range fields {
|
||||||
|
value = value.FieldByName(field)
|
||||||
|
if !value.IsValid() {
|
||||||
|
return // 字段不存在,直接返回
|
||||||
|
}
|
||||||
|
if value.Kind() == reflect.Ptr {
|
||||||
|
value = value.Elem() // 解引用指针类型的字段
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 检查字段是否可设置
|
||||||
|
if value.CanSet() {
|
||||||
|
// 根据字段类型,将新值转换为对应类型并设置字段的值
|
||||||
|
newValue := reflect.ValueOf(newValue).Convert(value.Type())
|
||||||
|
value.Set(newValue)
|
||||||
|
}
|
||||||
|
}
|
157
go.mod
Normal file
157
go.mod
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
module exhibition-register
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
dubbo.apache.org/dubbo-go/v3 v3.0.5
|
||||||
|
github.com/bwmarrin/snowflake v0.3.0
|
||||||
|
github.com/gin-gonic/gin v1.9.1
|
||||||
|
github.com/go-redis/redis v6.15.9+incompatible
|
||||||
|
github.com/google/wire v0.5.0
|
||||||
|
github.com/nacos-group/nacos-sdk-go v1.1.4
|
||||||
|
github.com/natefinch/lumberjack v2.0.0+incompatible
|
||||||
|
github.com/opentracing/opentracing-go v1.2.0
|
||||||
|
github.com/spf13/viper v1.17.0
|
||||||
|
github.com/streadway/amqp v1.1.0
|
||||||
|
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
||||||
|
go.uber.org/zap v1.26.0
|
||||||
|
gorm.io/driver/mysql v1.5.2
|
||||||
|
gorm.io/gorm v1.25.5
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
cloud.google.com/go/compute v1.23.0 // indirect
|
||||||
|
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||||
|
contrib.go.opencensus.io/exporter/prometheus v0.4.1 // indirect
|
||||||
|
github.com/RoaringBitmap/roaring v1.2.3 // indirect
|
||||||
|
github.com/Workiva/go-datastructures v1.0.52 // indirect
|
||||||
|
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 // indirect
|
||||||
|
github.com/alibaba/sentinel-golang v1.0.4 // indirect
|
||||||
|
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1704 // indirect
|
||||||
|
github.com/apache/dubbo-getty v1.4.9-0.20221022181821-4dc6252ce98c // indirect
|
||||||
|
github.com/apache/dubbo-go-hessian2 v1.11.5 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/bits-and-blooms/bitset v1.2.0 // indirect
|
||||||
|
github.com/buger/jsonparser v1.1.1 // indirect
|
||||||
|
github.com/bytedance/sonic v1.9.1 // indirect
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
|
||||||
|
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect
|
||||||
|
github.com/coreos/go-semver v0.3.0 // indirect
|
||||||
|
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||||
|
github.com/creasty/defaults v1.5.2 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
|
github.com/dlclark/regexp2 v1.7.0 // indirect
|
||||||
|
github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5 // indirect
|
||||||
|
github.com/dubbogo/gost v1.13.2 // indirect
|
||||||
|
github.com/dubbogo/grpc-go v1.42.10 // indirect
|
||||||
|
github.com/dubbogo/triple v1.2.2-rc2 // indirect
|
||||||
|
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
|
||||||
|
github.com/envoyproxy/go-control-plane v0.11.1 // indirect
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/go-co-op/gocron v1.9.0 // indirect
|
||||||
|
github.com/go-errors/errors v1.0.1 // indirect
|
||||||
|
github.com/go-kit/log v0.1.0 // indirect
|
||||||
|
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||||
|
github.com/go-logr/logr v1.2.3 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||||
|
github.com/go-resty/resty/v2 v2.7.0 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
|
||||||
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
|
github.com/hashicorp/vault/sdk v0.7.0 // indirect
|
||||||
|
github.com/jinzhu/copier v0.3.5 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/k0kubun/pp v3.0.1+incompatible // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||||
|
github.com/knadh/koanf v1.5.0 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/mschoch/smat v0.2.0 // indirect
|
||||||
|
github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect
|
||||||
|
github.com/pelletier/go-toml v1.7.0 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
|
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/polarismesh/polaris-go v1.3.0 // indirect
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
|
github.com/prometheus/client_golang v1.12.2 // indirect
|
||||||
|
github.com/prometheus/client_model v0.4.0 // indirect
|
||||||
|
github.com/prometheus/common v0.32.1 // indirect
|
||||||
|
github.com/prometheus/procfs v0.7.3 // indirect
|
||||||
|
github.com/prometheus/statsd_exporter v0.21.0 // indirect
|
||||||
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
|
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||||
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
|
github.com/shirou/gopsutil/v3 v3.22.2 // indirect
|
||||||
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
github.com/spf13/afero v1.10.0 // indirect
|
||||||
|
github.com/spf13/cast v1.5.1 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
|
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.4.0 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
|
go.etcd.io/etcd/api/v3 v3.5.9 // indirect
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
|
||||||
|
go.etcd.io/etcd/client/v3 v3.5.9 // indirect
|
||||||
|
go.opencensus.io v0.24.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.11.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.11.0 // indirect
|
||||||
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
|
golang.org/x/crypto v0.13.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
|
golang.org/x/net v0.15.0 // indirect
|
||||||
|
golang.org/x/oauth2 v0.12.0 // indirect
|
||||||
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
|
golang.org/x/text v0.13.0 // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
|
||||||
|
google.golang.org/grpc v1.58.2 // indirect
|
||||||
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
1
internal/controller/register.go
Normal file
1
internal/controller/register.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package controller
|
57
internal/handler/default_handler.go
Normal file
57
internal/handler/default_handler.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/common"
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/common/extension"
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/filter"
|
||||||
|
"dubbo.apache.org/dubbo-go/v3/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
extension.SetRejectedExecutionHandler("DefaultValueHandler", GetDefaultValueRejectedExecutionHandlerSingleton)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DefaultValueRejectedExecutionHandler struct {
|
||||||
|
defaultResult sync.Map
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mh *DefaultValueRejectedExecutionHandler) RejectedExecution(url *common.URL, invocation protocol.Invocation) protocol.Result {
|
||||||
|
key := url.ServiceKey() + "#" + invocation.MethodName()
|
||||||
|
result, loaded := mh.defaultResult.Load(key)
|
||||||
|
if !loaded {
|
||||||
|
// we didn't configure any default value for this invocation
|
||||||
|
return &protocol.RPCResult{
|
||||||
|
Err: errors.New("请求太频繁"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.(*protocol.RPCResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCustomRejectedExecutionHandler() filter.RejectedExecutionHandler {
|
||||||
|
return &DefaultValueRejectedExecutionHandler{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
customHandlerOnce sync.Once
|
||||||
|
customHandlerInstance *DefaultValueRejectedExecutionHandler
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the better way is designing the RejectedExecutionHandler as singleton.
|
||||||
|
*/
|
||||||
|
func GetDefaultValueRejectedExecutionHandlerSingleton() filter.RejectedExecutionHandler {
|
||||||
|
customHandlerOnce.Do(func() {
|
||||||
|
customHandlerInstance = &DefaultValueRejectedExecutionHandler{}
|
||||||
|
})
|
||||||
|
|
||||||
|
initDefaultValue()
|
||||||
|
|
||||||
|
return customHandlerInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDefaultValue() {
|
||||||
|
// setting your default value
|
||||||
|
}
|
1
internal/logic/register.go
Normal file
1
internal/logic/register.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package logic
|
1
internal/model/register.go
Normal file
1
internal/model/register.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package model
|
923
pb/descriptor.proto
Normal file
923
pb/descriptor.proto
Normal file
@ -0,0 +1,923 @@
|
|||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
//
|
||||||
|
// The messages in this file describe the definitions found in .proto files.
|
||||||
|
// A valid .proto file can be translated directly to a FileDescriptorProto
|
||||||
|
// without any other information (e.g. without reading its imports).
|
||||||
|
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
package google.protobuf;
|
||||||
|
|
||||||
|
option go_package = "google.golang.org/protobuf/types/descriptorpb";
|
||||||
|
option java_package = "com.google.protobuf";
|
||||||
|
option java_outer_classname = "DescriptorProtos";
|
||||||
|
option csharp_namespace = "Google.Protobuf.Reflection";
|
||||||
|
option objc_class_prefix = "GPB";
|
||||||
|
option cc_enable_arenas = true;
|
||||||
|
|
||||||
|
// descriptor.proto must be optimized for speed because reflection-based
|
||||||
|
// algorithms don't work during bootstrapping.
|
||||||
|
option optimize_for = SPEED;
|
||||||
|
|
||||||
|
// The protocol compiler can output a FileDescriptorSet containing the .proto
|
||||||
|
// files it parses.
|
||||||
|
message FileDescriptorSet {
|
||||||
|
repeated FileDescriptorProto file = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a complete .proto file.
|
||||||
|
message FileDescriptorProto {
|
||||||
|
optional string name = 1; // file name, relative to root of source tree
|
||||||
|
optional string package = 2; // e.g. "foo", "foo.bar", etc.
|
||||||
|
|
||||||
|
// Names of files imported by this file.
|
||||||
|
repeated string dependency = 3;
|
||||||
|
// Indexes of the public imported files in the dependency list above.
|
||||||
|
repeated int32 public_dependency = 10;
|
||||||
|
// Indexes of the weak imported files in the dependency list.
|
||||||
|
// For Google-internal migration only. Do not use.
|
||||||
|
repeated int32 weak_dependency = 11;
|
||||||
|
|
||||||
|
// All top-level definitions in this file.
|
||||||
|
repeated DescriptorProto message_type = 4;
|
||||||
|
repeated EnumDescriptorProto enum_type = 5;
|
||||||
|
repeated ServiceDescriptorProto service = 6;
|
||||||
|
repeated FieldDescriptorProto extension = 7;
|
||||||
|
|
||||||
|
optional FileOptions options = 8;
|
||||||
|
|
||||||
|
// This field contains optional information about the original source code.
|
||||||
|
// You may safely remove this entire field without harming runtime
|
||||||
|
// functionality of the descriptors -- the information is needed only by
|
||||||
|
// development tools.
|
||||||
|
optional SourceCodeInfo source_code_info = 9;
|
||||||
|
|
||||||
|
// The syntax of the proto file.
|
||||||
|
// The supported values are "proto2", "proto3", and "editions".
|
||||||
|
//
|
||||||
|
// If `edition` is present, this value must be "editions".
|
||||||
|
optional string syntax = 12;
|
||||||
|
|
||||||
|
// The edition of the proto file, which is an opaque string.
|
||||||
|
optional string edition = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a message type.
|
||||||
|
message DescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
repeated FieldDescriptorProto field = 2;
|
||||||
|
repeated FieldDescriptorProto extension = 6;
|
||||||
|
|
||||||
|
repeated DescriptorProto nested_type = 3;
|
||||||
|
repeated EnumDescriptorProto enum_type = 4;
|
||||||
|
|
||||||
|
message ExtensionRange {
|
||||||
|
optional int32 start = 1; // Inclusive.
|
||||||
|
optional int32 end = 2; // Exclusive.
|
||||||
|
|
||||||
|
optional ExtensionRangeOptions options = 3;
|
||||||
|
}
|
||||||
|
repeated ExtensionRange extension_range = 5;
|
||||||
|
|
||||||
|
repeated OneofDescriptorProto oneof_decl = 8;
|
||||||
|
|
||||||
|
optional MessageOptions options = 7;
|
||||||
|
|
||||||
|
// Range of reserved tag numbers. Reserved tag numbers may not be used by
|
||||||
|
// fields or extension ranges in the same message. Reserved ranges may
|
||||||
|
// not overlap.
|
||||||
|
message ReservedRange {
|
||||||
|
optional int32 start = 1; // Inclusive.
|
||||||
|
optional int32 end = 2; // Exclusive.
|
||||||
|
}
|
||||||
|
repeated ReservedRange reserved_range = 9;
|
||||||
|
// Reserved field names, which may not be used by fields in the same message.
|
||||||
|
// A given name may only be reserved once.
|
||||||
|
repeated string reserved_name = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExtensionRangeOptions {
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a field within a message.
|
||||||
|
message FieldDescriptorProto {
|
||||||
|
enum Type {
|
||||||
|
// 0 is reserved for errors.
|
||||||
|
// Order is weird for historical reasons.
|
||||||
|
TYPE_DOUBLE = 1;
|
||||||
|
TYPE_FLOAT = 2;
|
||||||
|
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
|
||||||
|
// negative values are likely.
|
||||||
|
TYPE_INT64 = 3;
|
||||||
|
TYPE_UINT64 = 4;
|
||||||
|
// Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
|
||||||
|
// negative values are likely.
|
||||||
|
TYPE_INT32 = 5;
|
||||||
|
TYPE_FIXED64 = 6;
|
||||||
|
TYPE_FIXED32 = 7;
|
||||||
|
TYPE_BOOL = 8;
|
||||||
|
TYPE_STRING = 9;
|
||||||
|
// Tag-delimited aggregate.
|
||||||
|
// Group type is deprecated and not supported in proto3. However, Proto3
|
||||||
|
// implementations should still be able to parse the group wire format and
|
||||||
|
// treat group fields as unknown fields.
|
||||||
|
TYPE_GROUP = 10;
|
||||||
|
TYPE_MESSAGE = 11; // Length-delimited aggregate.
|
||||||
|
|
||||||
|
// New in version 2.
|
||||||
|
TYPE_BYTES = 12;
|
||||||
|
TYPE_UINT32 = 13;
|
||||||
|
TYPE_ENUM = 14;
|
||||||
|
TYPE_SFIXED32 = 15;
|
||||||
|
TYPE_SFIXED64 = 16;
|
||||||
|
TYPE_SINT32 = 17; // Uses ZigZag encoding.
|
||||||
|
TYPE_SINT64 = 18; // Uses ZigZag encoding.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Label {
|
||||||
|
// 0 is reserved for errors
|
||||||
|
LABEL_OPTIONAL = 1;
|
||||||
|
LABEL_REQUIRED = 2;
|
||||||
|
LABEL_REPEATED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional string name = 1;
|
||||||
|
optional int32 number = 3;
|
||||||
|
optional Label label = 4;
|
||||||
|
|
||||||
|
// If type_name is set, this need not be set. If both this and type_name
|
||||||
|
// are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
|
||||||
|
optional Type type = 5;
|
||||||
|
|
||||||
|
// For message and enum types, this is the name of the type. If the name
|
||||||
|
// starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
|
||||||
|
// rules are used to find the type (i.e. first the nested types within this
|
||||||
|
// message are searched, then within the parent, on up to the root
|
||||||
|
// namespace).
|
||||||
|
optional string type_name = 6;
|
||||||
|
|
||||||
|
// For extensions, this is the name of the type being extended. It is
|
||||||
|
// resolved in the same manner as type_name.
|
||||||
|
optional string extendee = 2;
|
||||||
|
|
||||||
|
// For numeric types, contains the original text representation of the value.
|
||||||
|
// For booleans, "true" or "false".
|
||||||
|
// For strings, contains the default text contents (not escaped in any way).
|
||||||
|
// For bytes, contains the C escaped value. All bytes >= 128 are escaped.
|
||||||
|
optional string default_value = 7;
|
||||||
|
|
||||||
|
// If set, gives the index of a oneof in the containing type's oneof_decl
|
||||||
|
// list. This field is a member of that oneof.
|
||||||
|
optional int32 oneof_index = 9;
|
||||||
|
|
||||||
|
// JSON name of this field. The value is set by protocol compiler. If the
|
||||||
|
// user has set a "json_name" option on this field, that option's value
|
||||||
|
// will be used. Otherwise, it's deduced from the field's name by converting
|
||||||
|
// it to camelCase.
|
||||||
|
optional string json_name = 10;
|
||||||
|
|
||||||
|
optional FieldOptions options = 8;
|
||||||
|
|
||||||
|
// If true, this is a proto3 "optional". When a proto3 field is optional, it
|
||||||
|
// tracks presence regardless of field type.
|
||||||
|
//
|
||||||
|
// When proto3_optional is true, this field must be belong to a oneof to
|
||||||
|
// signal to old proto3 clients that presence is tracked for this field. This
|
||||||
|
// oneof is known as a "synthetic" oneof, and this field must be its sole
|
||||||
|
// member (each proto3 optional field gets its own synthetic oneof). Synthetic
|
||||||
|
// oneofs exist in the descriptor only, and do not generate any API. Synthetic
|
||||||
|
// oneofs must be ordered after all "real" oneofs.
|
||||||
|
//
|
||||||
|
// For message fields, proto3_optional doesn't create any semantic change,
|
||||||
|
// since non-repeated message fields always track presence. However it still
|
||||||
|
// indicates the semantic detail of whether the user wrote "optional" or not.
|
||||||
|
// This can be useful for round-tripping the .proto file. For consistency we
|
||||||
|
// give message fields a synthetic oneof also, even though it is not required
|
||||||
|
// to track presence. This is especially important because the parser can't
|
||||||
|
// tell if a field is a message or an enum, so it must always create a
|
||||||
|
// synthetic oneof.
|
||||||
|
//
|
||||||
|
// Proto2 optional fields do not set this flag, because they already indicate
|
||||||
|
// optional with `LABEL_OPTIONAL`.
|
||||||
|
optional bool proto3_optional = 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a oneof.
|
||||||
|
message OneofDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
optional OneofOptions options = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes an enum type.
|
||||||
|
message EnumDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
repeated EnumValueDescriptorProto value = 2;
|
||||||
|
|
||||||
|
optional EnumOptions options = 3;
|
||||||
|
|
||||||
|
// Range of reserved numeric values. Reserved values may not be used by
|
||||||
|
// entries in the same enum. Reserved ranges may not overlap.
|
||||||
|
//
|
||||||
|
// Note that this is distinct from DescriptorProto.ReservedRange in that it
|
||||||
|
// is inclusive such that it can appropriately represent the entire int32
|
||||||
|
// domain.
|
||||||
|
message EnumReservedRange {
|
||||||
|
optional int32 start = 1; // Inclusive.
|
||||||
|
optional int32 end = 2; // Inclusive.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range of reserved numeric values. Reserved numeric values may not be used
|
||||||
|
// by enum values in the same enum declaration. Reserved ranges may not
|
||||||
|
// overlap.
|
||||||
|
repeated EnumReservedRange reserved_range = 4;
|
||||||
|
|
||||||
|
// Reserved enum value names, which may not be reused. A given name may only
|
||||||
|
// be reserved once.
|
||||||
|
repeated string reserved_name = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a value within an enum.
|
||||||
|
message EnumValueDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
optional int32 number = 2;
|
||||||
|
|
||||||
|
optional EnumValueOptions options = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a service.
|
||||||
|
message ServiceDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
repeated MethodDescriptorProto method = 2;
|
||||||
|
|
||||||
|
optional ServiceOptions options = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes a method of a service.
|
||||||
|
message MethodDescriptorProto {
|
||||||
|
optional string name = 1;
|
||||||
|
|
||||||
|
// Input and output type names. These are resolved in the same way as
|
||||||
|
// FieldDescriptorProto.type_name, but must refer to a message type.
|
||||||
|
optional string input_type = 2;
|
||||||
|
optional string output_type = 3;
|
||||||
|
|
||||||
|
optional MethodOptions options = 4;
|
||||||
|
|
||||||
|
// Identifies if client streams multiple client messages
|
||||||
|
optional bool client_streaming = 5 [default = false];
|
||||||
|
// Identifies if server streams multiple server messages
|
||||||
|
optional bool server_streaming = 6 [default = false];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Options
|
||||||
|
|
||||||
|
// Each of the definitions above may have "options" attached. These are
|
||||||
|
// just annotations which may cause code to be generated slightly differently
|
||||||
|
// or may contain hints for code that manipulates protocol messages.
|
||||||
|
//
|
||||||
|
// Clients may define custom options as extensions of the *Options messages.
|
||||||
|
// These extensions may not yet be known at parsing time, so the parser cannot
|
||||||
|
// store the values in them. Instead it stores them in a field in the *Options
|
||||||
|
// message called uninterpreted_option. This field must have the same name
|
||||||
|
// across all *Options messages. We then use this field to populate the
|
||||||
|
// extensions when we build a descriptor, at which point all protos have been
|
||||||
|
// parsed and so all extensions are known.
|
||||||
|
//
|
||||||
|
// Extension numbers for custom options may be chosen as follows:
|
||||||
|
// * For options which will only be used within a single application or
|
||||||
|
// organization, or for experimental options, use field numbers 50000
|
||||||
|
// through 99999. It is up to you to ensure that you do not use the
|
||||||
|
// same number for multiple options.
|
||||||
|
// * For options which will be published and used publicly by multiple
|
||||||
|
// independent entities, e-mail protobuf-global-extension-registry@google.com
|
||||||
|
// to reserve extension numbers. Simply provide your project name (e.g.
|
||||||
|
// Objective-C plugin) and your project website (if available) -- there's no
|
||||||
|
// need to explain how you intend to use them. Usually you only need one
|
||||||
|
// extension number. You can declare multiple options with only one extension
|
||||||
|
// number by putting them in a sub-message. See the Custom Options section of
|
||||||
|
// the docs for examples:
|
||||||
|
// https://developers.google.com/protocol-buffers/docs/proto#options
|
||||||
|
// If this turns out to be popular, a web service will be set up
|
||||||
|
// to automatically assign option numbers.
|
||||||
|
|
||||||
|
message FileOptions {
|
||||||
|
|
||||||
|
// Sets the Java package where classes generated from this .proto will be
|
||||||
|
// placed. By default, the proto package is used, but this is often
|
||||||
|
// inappropriate because proto packages do not normally start with backwards
|
||||||
|
// domain names.
|
||||||
|
optional string java_package = 1;
|
||||||
|
|
||||||
|
|
||||||
|
// Controls the name of the wrapper Java class generated for the .proto file.
|
||||||
|
// That class will always contain the .proto file's getDescriptor() method as
|
||||||
|
// well as any top-level extensions defined in the .proto file.
|
||||||
|
// If java_multiple_files is disabled, then all the other classes from the
|
||||||
|
// .proto file will be nested inside the single wrapper outer class.
|
||||||
|
optional string java_outer_classname = 8;
|
||||||
|
|
||||||
|
// If enabled, then the Java code generator will generate a separate .java
|
||||||
|
// file for each top-level message, enum, and service defined in the .proto
|
||||||
|
// file. Thus, these types will *not* be nested inside the wrapper class
|
||||||
|
// named by java_outer_classname. However, the wrapper class will still be
|
||||||
|
// generated to contain the file's getDescriptor() method as well as any
|
||||||
|
// top-level extensions defined in the file.
|
||||||
|
optional bool java_multiple_files = 10 [default = false];
|
||||||
|
|
||||||
|
// This option does nothing.
|
||||||
|
optional bool java_generate_equals_and_hash = 20 [deprecated=true];
|
||||||
|
|
||||||
|
// If set true, then the Java2 code generator will generate code that
|
||||||
|
// throws an exception whenever an attempt is made to assign a non-UTF-8
|
||||||
|
// byte sequence to a string field.
|
||||||
|
// Message reflection will do the same.
|
||||||
|
// However, an extension field still accepts non-UTF-8 byte sequences.
|
||||||
|
// This option has no effect on when used with the lite runtime.
|
||||||
|
optional bool java_string_check_utf8 = 27 [default = false];
|
||||||
|
|
||||||
|
|
||||||
|
// Generated classes can be optimized for speed or code size.
|
||||||
|
enum OptimizeMode {
|
||||||
|
SPEED = 1; // Generate complete code for parsing, serialization,
|
||||||
|
// etc.
|
||||||
|
CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
|
||||||
|
LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
|
||||||
|
}
|
||||||
|
optional OptimizeMode optimize_for = 9 [default = SPEED];
|
||||||
|
|
||||||
|
// Sets the Go package where structs generated from this .proto will be
|
||||||
|
// placed. If omitted, the Go package will be derived from the following:
|
||||||
|
// - The basename of the package import path, if provided.
|
||||||
|
// - Otherwise, the package statement in the .proto file, if present.
|
||||||
|
// - Otherwise, the basename of the .proto file, without extension.
|
||||||
|
optional string go_package = 11;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Should generic services be generated in each language? "Generic" services
|
||||||
|
// are not specific to any particular RPC system. They are generated by the
|
||||||
|
// main code generators in each language (without additional plugins).
|
||||||
|
// Generic services were the only kind of service generation supported by
|
||||||
|
// early versions of google.protobuf.
|
||||||
|
//
|
||||||
|
// Generic services are now considered deprecated in favor of using plugins
|
||||||
|
// that generate code specific to your particular RPC system. Therefore,
|
||||||
|
// these default to false. Old code which depends on generic services should
|
||||||
|
// explicitly set them to true.
|
||||||
|
optional bool cc_generic_services = 16 [default = false];
|
||||||
|
optional bool java_generic_services = 17 [default = false];
|
||||||
|
optional bool py_generic_services = 18 [default = false];
|
||||||
|
optional bool php_generic_services = 42 [default = false];
|
||||||
|
|
||||||
|
// Is this file deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for everything in the file, or it will be completely ignored; in the very
|
||||||
|
// least, this is a formalization for deprecating files.
|
||||||
|
optional bool deprecated = 23 [default = false];
|
||||||
|
|
||||||
|
// Enables the use of arenas for the proto messages in this file. This applies
|
||||||
|
// only to generated classes for C++.
|
||||||
|
optional bool cc_enable_arenas = 31 [default = true];
|
||||||
|
|
||||||
|
|
||||||
|
// Sets the objective c class prefix which is prepended to all objective c
|
||||||
|
// generated classes from this .proto. There is no default.
|
||||||
|
optional string objc_class_prefix = 36;
|
||||||
|
|
||||||
|
// Namespace for generated classes; defaults to the package.
|
||||||
|
optional string csharp_namespace = 37;
|
||||||
|
|
||||||
|
// By default Swift generators will take the proto package and CamelCase it
|
||||||
|
// replacing '.' with underscore and use that to prefix the types/symbols
|
||||||
|
// defined. When this options is provided, they will use this value instead
|
||||||
|
// to prefix the types/symbols defined.
|
||||||
|
optional string swift_prefix = 39;
|
||||||
|
|
||||||
|
// Sets the php class prefix which is prepended to all php generated classes
|
||||||
|
// from this .proto. Default is empty.
|
||||||
|
optional string php_class_prefix = 40;
|
||||||
|
|
||||||
|
// Use this option to change the namespace of php generated classes. Default
|
||||||
|
// is empty. When this option is empty, the package name will be used for
|
||||||
|
// determining the namespace.
|
||||||
|
optional string php_namespace = 41;
|
||||||
|
|
||||||
|
// Use this option to change the namespace of php generated metadata classes.
|
||||||
|
// Default is empty. When this option is empty, the proto file name will be
|
||||||
|
// used for determining the namespace.
|
||||||
|
optional string php_metadata_namespace = 44;
|
||||||
|
|
||||||
|
// Use this option to change the package of ruby generated classes. Default
|
||||||
|
// is empty. When this option is not set, the package name will be used for
|
||||||
|
// determining the ruby package.
|
||||||
|
optional string ruby_package = 45;
|
||||||
|
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here.
|
||||||
|
// See the documentation for the "Options" section above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message.
|
||||||
|
// See the documentation for the "Options" section above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
|
||||||
|
reserved 38;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageOptions {
|
||||||
|
// Set true to use the old proto1 MessageSet wire format for extensions.
|
||||||
|
// This is provided for backwards-compatibility with the MessageSet wire
|
||||||
|
// format. You should not use this for any other reason: It's less
|
||||||
|
// efficient, has fewer features, and is more complicated.
|
||||||
|
//
|
||||||
|
// The message must be defined exactly as follows:
|
||||||
|
// message Foo {
|
||||||
|
// option message_set_wire_format = true;
|
||||||
|
// extensions 4 to max;
|
||||||
|
// }
|
||||||
|
// Note that the message cannot have any defined fields; MessageSets only
|
||||||
|
// have extensions.
|
||||||
|
//
|
||||||
|
// All extensions of your type must be singular messages; e.g. they cannot
|
||||||
|
// be int32s, enums, or repeated messages.
|
||||||
|
//
|
||||||
|
// Because this is an option, the above two restrictions are not enforced by
|
||||||
|
// the protocol compiler.
|
||||||
|
optional bool message_set_wire_format = 1 [default = false];
|
||||||
|
|
||||||
|
// Disables the generation of the standard "descriptor()" accessor, which can
|
||||||
|
// conflict with a field of the same name. This is meant to make migration
|
||||||
|
// from proto1 easier; new code should avoid fields named "descriptor".
|
||||||
|
optional bool no_standard_descriptor_accessor = 2 [default = false];
|
||||||
|
|
||||||
|
// Is this message deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the message, or it will be completely ignored; in the very least,
|
||||||
|
// this is a formalization for deprecating messages.
|
||||||
|
optional bool deprecated = 3 [default = false];
|
||||||
|
|
||||||
|
reserved 4, 5, 6;
|
||||||
|
|
||||||
|
// Whether the message is an automatically generated map entry type for the
|
||||||
|
// maps field.
|
||||||
|
//
|
||||||
|
// For maps fields:
|
||||||
|
// map<KeyType, ValueType> map_field = 1;
|
||||||
|
// The parsed descriptor looks like:
|
||||||
|
// message MapFieldEntry {
|
||||||
|
// option map_entry = true;
|
||||||
|
// optional KeyType key = 1;
|
||||||
|
// optional ValueType value = 2;
|
||||||
|
// }
|
||||||
|
// repeated MapFieldEntry map_field = 1;
|
||||||
|
//
|
||||||
|
// Implementations may choose not to generate the map_entry=true message, but
|
||||||
|
// use a native map in the target language to hold the keys and values.
|
||||||
|
// The reflection APIs in such implementations still need to work as
|
||||||
|
// if the field is a repeated message field.
|
||||||
|
//
|
||||||
|
// NOTE: Do not set the option in .proto files. Always use the maps syntax
|
||||||
|
// instead. The option should only be implicitly set by the proto compiler
|
||||||
|
// parser.
|
||||||
|
optional bool map_entry = 7;
|
||||||
|
|
||||||
|
reserved 8; // javalite_serializable
|
||||||
|
reserved 9; // javanano_as_lite
|
||||||
|
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FieldOptions {
|
||||||
|
// The ctype option instructs the C++ code generator to use a different
|
||||||
|
// representation of the field than it normally would. See the specific
|
||||||
|
// options below. This option is not yet implemented in the open source
|
||||||
|
// release -- sorry, we'll try to include it in a future version!
|
||||||
|
optional CType ctype = 1 [default = STRING];
|
||||||
|
enum CType {
|
||||||
|
// Default mode.
|
||||||
|
STRING = 0;
|
||||||
|
|
||||||
|
CORD = 1;
|
||||||
|
|
||||||
|
STRING_PIECE = 2;
|
||||||
|
}
|
||||||
|
// The packed option can be enabled for repeated primitive fields to enable
|
||||||
|
// a more efficient representation on the wire. Rather than repeatedly
|
||||||
|
// writing the tag and type for each element, the entire array is encoded as
|
||||||
|
// a single length-delimited blob. In proto3, only explicit setting it to
|
||||||
|
// false will avoid using packed encoding.
|
||||||
|
optional bool packed = 2;
|
||||||
|
|
||||||
|
// The jstype option determines the JavaScript type used for values of the
|
||||||
|
// field. The option is permitted only for 64 bit integral and fixed types
|
||||||
|
// (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING
|
||||||
|
// is represented as JavaScript string, which avoids loss of precision that
|
||||||
|
// can happen when a large value is converted to a floating point JavaScript.
|
||||||
|
// Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
|
||||||
|
// use the JavaScript "number" type. The behavior of the default option
|
||||||
|
// JS_NORMAL is implementation dependent.
|
||||||
|
//
|
||||||
|
// This option is an enum to permit additional types to be added, e.g.
|
||||||
|
// goog.math.Integer.
|
||||||
|
optional JSType jstype = 6 [default = JS_NORMAL];
|
||||||
|
enum JSType {
|
||||||
|
// Use the default type.
|
||||||
|
JS_NORMAL = 0;
|
||||||
|
|
||||||
|
// Use JavaScript strings.
|
||||||
|
JS_STRING = 1;
|
||||||
|
|
||||||
|
// Use JavaScript numbers.
|
||||||
|
JS_NUMBER = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should this field be parsed lazily? Lazy applies only to message-type
|
||||||
|
// fields. It means that when the outer message is initially parsed, the
|
||||||
|
// inner message's contents will not be parsed but instead stored in encoded
|
||||||
|
// form. The inner message will actually be parsed when it is first accessed.
|
||||||
|
//
|
||||||
|
// This is only a hint. Implementations are free to choose whether to use
|
||||||
|
// eager or lazy parsing regardless of the value of this option. However,
|
||||||
|
// setting this option true suggests that the protocol author believes that
|
||||||
|
// using lazy parsing on this field is worth the additional bookkeeping
|
||||||
|
// overhead typically needed to implement it.
|
||||||
|
//
|
||||||
|
// This option does not affect the public interface of any generated code;
|
||||||
|
// all method signatures remain the same. Furthermore, thread-safety of the
|
||||||
|
// interface is not affected by this option; const methods remain safe to
|
||||||
|
// call from multiple threads concurrently, while non-const methods continue
|
||||||
|
// to require exclusive access.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Note that implementations may choose not to check required fields within
|
||||||
|
// a lazy sub-message. That is, calling IsInitialized() on the outer message
|
||||||
|
// may return true even if the inner message has missing required fields.
|
||||||
|
// This is necessary because otherwise the inner message would have to be
|
||||||
|
// parsed in order to perform the check, defeating the purpose of lazy
|
||||||
|
// parsing. An implementation which chooses not to check required fields
|
||||||
|
// must be consistent about it. That is, for any particular sub-message, the
|
||||||
|
// implementation must either *always* check its required fields, or *never*
|
||||||
|
// check its required fields, regardless of whether or not the message has
|
||||||
|
// been parsed.
|
||||||
|
//
|
||||||
|
// As of May 2022, lazy verifies the contents of the byte stream during
|
||||||
|
// parsing. An invalid byte stream will cause the overall parsing to fail.
|
||||||
|
optional bool lazy = 5 [default = false];
|
||||||
|
|
||||||
|
// unverified_lazy does no correctness checks on the byte stream. This should
|
||||||
|
// only be used where lazy with verification is prohibitive for performance
|
||||||
|
// reasons.
|
||||||
|
optional bool unverified_lazy = 15 [default = false];
|
||||||
|
|
||||||
|
// Is this field deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for accessors, or it will be completely ignored; in the very least, this
|
||||||
|
// is a formalization for deprecating fields.
|
||||||
|
optional bool deprecated = 3 [default = false];
|
||||||
|
|
||||||
|
// For Google-internal migration only. Do not use.
|
||||||
|
optional bool weak = 10 [default = false];
|
||||||
|
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
|
||||||
|
reserved 4; // removed jtype
|
||||||
|
}
|
||||||
|
|
||||||
|
message OneofOptions {
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumOptions {
|
||||||
|
|
||||||
|
// Set this option to true to allow mapping different tag names to the same
|
||||||
|
// value.
|
||||||
|
optional bool allow_alias = 2;
|
||||||
|
|
||||||
|
// Is this enum deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the enum, or it will be completely ignored; in the very least, this
|
||||||
|
// is a formalization for deprecating enums.
|
||||||
|
optional bool deprecated = 3 [default = false];
|
||||||
|
|
||||||
|
reserved 5; // javanano_as_lite
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumValueOptions {
|
||||||
|
// Is this enum value deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the enum value, or it will be completely ignored; in the very least,
|
||||||
|
// this is a formalization for deprecating enum values.
|
||||||
|
optional bool deprecated = 1 [default = false];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ServiceOptions {
|
||||||
|
|
||||||
|
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
|
||||||
|
// framework. We apologize for hoarding these numbers to ourselves, but
|
||||||
|
// we were already using them long before we decided to release Protocol
|
||||||
|
// Buffers.
|
||||||
|
|
||||||
|
// Is this service deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the service, or it will be completely ignored; in the very least,
|
||||||
|
// this is a formalization for deprecating services.
|
||||||
|
optional bool deprecated = 33 [default = false];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MethodOptions {
|
||||||
|
|
||||||
|
// Note: Field numbers 1 through 32 are reserved for Google's internal RPC
|
||||||
|
// framework. We apologize for hoarding these numbers to ourselves, but
|
||||||
|
// we were already using them long before we decided to release Protocol
|
||||||
|
// Buffers.
|
||||||
|
|
||||||
|
// Is this method deprecated?
|
||||||
|
// Depending on the target platform, this can emit Deprecated annotations
|
||||||
|
// for the method, or it will be completely ignored; in the very least,
|
||||||
|
// this is a formalization for deprecating methods.
|
||||||
|
optional bool deprecated = 33 [default = false];
|
||||||
|
|
||||||
|
// Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
|
||||||
|
// or neither? HTTP based RPC implementation may choose GET verb for safe
|
||||||
|
// methods, and PUT verb for idempotent methods instead of the default POST.
|
||||||
|
enum IdempotencyLevel {
|
||||||
|
IDEMPOTENCY_UNKNOWN = 0;
|
||||||
|
NO_SIDE_EFFECTS = 1; // implies idempotent
|
||||||
|
IDEMPOTENT = 2; // idempotent, but may have side effects
|
||||||
|
}
|
||||||
|
optional IdempotencyLevel idempotency_level = 34
|
||||||
|
[default = IDEMPOTENCY_UNKNOWN];
|
||||||
|
|
||||||
|
// The parser stores options it doesn't recognize here. See above.
|
||||||
|
repeated UninterpretedOption uninterpreted_option = 999;
|
||||||
|
|
||||||
|
// Clients can define custom options in extensions of this message. See above.
|
||||||
|
extensions 1000 to max;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A message representing a option the parser does not recognize. This only
|
||||||
|
// appears in options protos created by the compiler::Parser class.
|
||||||
|
// DescriptorPool resolves these when building Descriptor objects. Therefore,
|
||||||
|
// options protos in descriptor objects (e.g. returned by Descriptor::options(),
|
||||||
|
// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
|
||||||
|
// in them.
|
||||||
|
message UninterpretedOption {
|
||||||
|
// The name of the uninterpreted option. Each string represents a segment in
|
||||||
|
// a dot-separated name. is_extension is true iff a segment represents an
|
||||||
|
// extension (denoted with parentheses in options specs in .proto files).
|
||||||
|
// E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents
|
||||||
|
// "foo.(bar.baz).moo".
|
||||||
|
message NamePart {
|
||||||
|
required string name_part = 1;
|
||||||
|
required bool is_extension = 2;
|
||||||
|
}
|
||||||
|
repeated NamePart name = 2;
|
||||||
|
|
||||||
|
// The value of the uninterpreted option, in whatever type the tokenizer
|
||||||
|
// identified it as during parsing. Exactly one of these should be set.
|
||||||
|
optional string identifier_value = 3;
|
||||||
|
optional uint64 positive_int_value = 4;
|
||||||
|
optional int64 negative_int_value = 5;
|
||||||
|
optional double double_value = 6;
|
||||||
|
optional bytes string_value = 7;
|
||||||
|
optional string aggregate_value = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
// Optional source code info
|
||||||
|
|
||||||
|
// Encapsulates information about the original source file from which a
|
||||||
|
// FileDescriptorProto was generated.
|
||||||
|
message SourceCodeInfo {
|
||||||
|
// A Location identifies a piece of source code in a .proto file which
|
||||||
|
// corresponds to a particular definition. This information is intended
|
||||||
|
// to be useful to IDEs, code indexers, documentation generators, and similar
|
||||||
|
// tools.
|
||||||
|
//
|
||||||
|
// For example, say we have a file like:
|
||||||
|
// message Foo {
|
||||||
|
// optional string foo = 1;
|
||||||
|
// }
|
||||||
|
// Let's look at just the field definition:
|
||||||
|
// optional string foo = 1;
|
||||||
|
// ^ ^^ ^^ ^ ^^^
|
||||||
|
// a bc de f ghi
|
||||||
|
// We have the following locations:
|
||||||
|
// span path represents
|
||||||
|
// [a,i) [ 4, 0, 2, 0 ] The whole field definition.
|
||||||
|
// [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
|
||||||
|
// [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
|
||||||
|
// [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
|
||||||
|
// [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// - A location may refer to a repeated field itself (i.e. not to any
|
||||||
|
// particular index within it). This is used whenever a set of elements are
|
||||||
|
// logically enclosed in a single code segment. For example, an entire
|
||||||
|
// extend block (possibly containing multiple extension definitions) will
|
||||||
|
// have an outer location whose path refers to the "extensions" repeated
|
||||||
|
// field without an index.
|
||||||
|
// - Multiple locations may have the same path. This happens when a single
|
||||||
|
// logical declaration is spread out across multiple places. The most
|
||||||
|
// obvious example is the "extend" block again -- there may be multiple
|
||||||
|
// extend blocks in the same scope, each of which will have the same path.
|
||||||
|
// - A location's span is not always a subset of its parent's span. For
|
||||||
|
// example, the "extendee" of an extension declaration appears at the
|
||||||
|
// beginning of the "extend" block and is shared by all extensions within
|
||||||
|
// the block.
|
||||||
|
// - Just because a location's span is a subset of some other location's span
|
||||||
|
// does not mean that it is a descendant. For example, a "group" defines
|
||||||
|
// both a type and a field in a single declaration. Thus, the locations
|
||||||
|
// corresponding to the type and field and their components will overlap.
|
||||||
|
// - Code which tries to interpret locations should probably be designed to
|
||||||
|
// ignore those that it doesn't understand, as more types of locations could
|
||||||
|
// be recorded in the future.
|
||||||
|
repeated Location location = 1;
|
||||||
|
message Location {
|
||||||
|
// Identifies which part of the FileDescriptorProto was defined at this
|
||||||
|
// location.
|
||||||
|
//
|
||||||
|
// Each element is a field number or an index. They form a path from
|
||||||
|
// the root FileDescriptorProto to the place where the definition occurs.
|
||||||
|
// For example, this path:
|
||||||
|
// [ 4, 3, 2, 7, 1 ]
|
||||||
|
// refers to:
|
||||||
|
// file.message_type(3) // 4, 3
|
||||||
|
// .field(7) // 2, 7
|
||||||
|
// .name() // 1
|
||||||
|
// This is because FileDescriptorProto.message_type has field number 4:
|
||||||
|
// repeated DescriptorProto message_type = 4;
|
||||||
|
// and DescriptorProto.field has field number 2:
|
||||||
|
// repeated FieldDescriptorProto field = 2;
|
||||||
|
// and FieldDescriptorProto.name has field number 1:
|
||||||
|
// optional string name = 1;
|
||||||
|
//
|
||||||
|
// Thus, the above path gives the location of a field name. If we removed
|
||||||
|
// the last element:
|
||||||
|
// [ 4, 3, 2, 7 ]
|
||||||
|
// this path refers to the whole field declaration (from the beginning
|
||||||
|
// of the label to the terminating semicolon).
|
||||||
|
repeated int32 path = 1 [packed = true];
|
||||||
|
|
||||||
|
// Always has exactly three or four elements: start line, start column,
|
||||||
|
// end line (optional, otherwise assumed same as start line), end column.
|
||||||
|
// These are packed into a single field for efficiency. Note that line
|
||||||
|
// and column numbers are zero-based -- typically you will want to add
|
||||||
|
// 1 to each before displaying to a user.
|
||||||
|
repeated int32 span = 2 [packed = true];
|
||||||
|
|
||||||
|
// If this SourceCodeInfo represents a complete declaration, these are any
|
||||||
|
// comments appearing before and after the declaration which appear to be
|
||||||
|
// attached to the declaration.
|
||||||
|
//
|
||||||
|
// A series of line comments appearing on consecutive lines, with no other
|
||||||
|
// tokens appearing on those lines, will be treated as a single comment.
|
||||||
|
//
|
||||||
|
// leading_detached_comments will keep paragraphs of comments that appear
|
||||||
|
// before (but not connected to) the current element. Each paragraph,
|
||||||
|
// separated by empty lines, will be one comment element in the repeated
|
||||||
|
// field.
|
||||||
|
//
|
||||||
|
// Only the comment content is provided; comment markers (e.g. //) are
|
||||||
|
// stripped out. For block comments, leading whitespace and an asterisk
|
||||||
|
// will be stripped from the beginning of each line other than the first.
|
||||||
|
// Newlines are included in the output.
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
//
|
||||||
|
// optional int32 foo = 1; // Comment attached to foo.
|
||||||
|
// // Comment attached to bar.
|
||||||
|
// optional int32 bar = 2;
|
||||||
|
//
|
||||||
|
// optional string baz = 3;
|
||||||
|
// // Comment attached to baz.
|
||||||
|
// // Another line attached to baz.
|
||||||
|
//
|
||||||
|
// // Comment attached to moo.
|
||||||
|
// //
|
||||||
|
// // Another line attached to moo.
|
||||||
|
// optional double moo = 4;
|
||||||
|
//
|
||||||
|
// // Detached comment for corge. This is not leading or trailing comments
|
||||||
|
// // to moo or corge because there are blank lines separating it from
|
||||||
|
// // both.
|
||||||
|
//
|
||||||
|
// // Detached comment for corge paragraph 2.
|
||||||
|
//
|
||||||
|
// optional string corge = 5;
|
||||||
|
// /* Block comment attached
|
||||||
|
// * to corge. Leading asterisks
|
||||||
|
// * will be removed. */
|
||||||
|
// /* Block comment attached to
|
||||||
|
// * grault. */
|
||||||
|
// optional int32 grault = 6;
|
||||||
|
//
|
||||||
|
// // ignored detached comments.
|
||||||
|
optional string leading_comments = 3;
|
||||||
|
optional string trailing_comments = 4;
|
||||||
|
repeated string leading_detached_comments = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describes the relationship between generated code and its original source
|
||||||
|
// file. A GeneratedCodeInfo message is associated with only one generated
|
||||||
|
// source file, but may contain references to different source .proto files.
|
||||||
|
message GeneratedCodeInfo {
|
||||||
|
// An Annotation connects some span of text in generated code to an element
|
||||||
|
// of its generating .proto file.
|
||||||
|
repeated Annotation annotation = 1;
|
||||||
|
message Annotation {
|
||||||
|
// Identifies the element in the original source .proto file. This field
|
||||||
|
// is formatted the same as SourceCodeInfo.Location.path.
|
||||||
|
repeated int32 path = 1 [packed = true];
|
||||||
|
|
||||||
|
// Identifies the filesystem path to the original source .proto.
|
||||||
|
optional string source_file = 2;
|
||||||
|
|
||||||
|
// Identifies the starting offset in bytes in the generated code
|
||||||
|
// that relates to the identified object.
|
||||||
|
optional int32 begin = 3;
|
||||||
|
|
||||||
|
// Identifies the ending offset in bytes in the generated code that
|
||||||
|
// relates to the identified offset. The end offset should be one past
|
||||||
|
// the last relevant byte (so the length of the text = end - begin).
|
||||||
|
optional int32 end = 4;
|
||||||
|
}
|
||||||
|
}
|
11
pb/exhibition.proto
Normal file
11
pb/exhibition.proto
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package exhibition;
|
||||||
|
option go_package = "./exhibition";
|
||||||
|
|
||||||
|
import "pb/descriptor.proto";
|
||||||
|
import "pb/validator.proto";
|
||||||
|
|
||||||
|
service Exhibition {
|
||||||
|
|
||||||
|
}
|
80
pb/validator.proto
Normal file
80
pb/validator.proto
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// Copyright 2016 Michal Witkowski. All Rights Reserved.
|
||||||
|
// See LICENSE for licensing terms.
|
||||||
|
|
||||||
|
// Protocol Buffers extensions for defining auto-generateable validators for messages.
|
||||||
|
|
||||||
|
// TODO(mwitkow): Add example.
|
||||||
|
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
package validator;
|
||||||
|
|
||||||
|
import "pb/descriptor.proto";
|
||||||
|
|
||||||
|
option go_package = "github.com/mwitkow/go-proto-validators;validator";
|
||||||
|
|
||||||
|
// TODO(mwitkow): Email protobuf-global-extension-registry@google.com to get an extension ID.
|
||||||
|
|
||||||
|
extend google.protobuf.FieldOptions {
|
||||||
|
optional FieldValidator field = 65020;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend google.protobuf.OneofOptions {
|
||||||
|
optional OneofValidator oneof = 65021;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FieldValidator {
|
||||||
|
// Uses a Golang RE2-syntax regex to match the field contents.
|
||||||
|
optional string regex = 1;
|
||||||
|
// Field value of integer strictly greater than this value.
|
||||||
|
optional int64 int_gt = 2;
|
||||||
|
// Field value of integer strictly smaller than this value.
|
||||||
|
optional int64 int_lt = 3;
|
||||||
|
// Used for nested message types, requires that the message type exists.
|
||||||
|
optional bool msg_exists = 4;
|
||||||
|
// Human error specifies a user-customizable error that is visible to the user.
|
||||||
|
optional string human_error = 5;
|
||||||
|
// Field value of double strictly greater than this value.
|
||||||
|
// Note that this value can only take on a valid floating point
|
||||||
|
// value. Use together with float_epsilon if you need something more specific.
|
||||||
|
optional double float_gt = 6;
|
||||||
|
// Field value of double strictly smaller than this value.
|
||||||
|
// Note that this value can only take on a valid floating point
|
||||||
|
// value. Use together with float_epsilon if you need something more specific.
|
||||||
|
optional double float_lt = 7;
|
||||||
|
// Field value of double describing the epsilon within which
|
||||||
|
// any comparison should be considered to be true. For example,
|
||||||
|
// when using float_gt = 0.35, using a float_epsilon of 0.05
|
||||||
|
// would mean that any value above 0.30 is acceptable. It can be
|
||||||
|
// thought of as a {float_value_condition} +- {float_epsilon}.
|
||||||
|
// If unset, no correction for floating point inaccuracies in
|
||||||
|
// comparisons will be attempted.
|
||||||
|
optional double float_epsilon = 8;
|
||||||
|
// Floating-point value compared to which the field content should be greater or equal.
|
||||||
|
optional double float_gte = 9;
|
||||||
|
// Floating-point value compared to which the field content should be smaller or equal.
|
||||||
|
optional double float_lte = 10;
|
||||||
|
// Used for string fields, requires the string to be not empty (i.e different from "").
|
||||||
|
optional bool string_not_empty = 11;
|
||||||
|
// Repeated field with at least this number of elements.
|
||||||
|
optional int64 repeated_count_min = 12;
|
||||||
|
// Repeated field with at most this number of elements.
|
||||||
|
optional int64 repeated_count_max = 13;
|
||||||
|
// Field value of length greater than this value.
|
||||||
|
optional int64 length_gt = 14;
|
||||||
|
// Field value of length smaller than this value.
|
||||||
|
optional int64 length_lt = 15;
|
||||||
|
// Field value of length strictly equal to this value.
|
||||||
|
optional int64 length_eq = 16;
|
||||||
|
// Requires that the value is in the enum.
|
||||||
|
optional bool is_in_enum = 17;
|
||||||
|
// Ensures that a string value is in UUID format.
|
||||||
|
// uuid_ver specifies the valid UUID versions. Valid values are: 0-5.
|
||||||
|
// If uuid_ver is 0 all UUID versions are accepted.
|
||||||
|
optional int32 uuid_ver = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OneofValidator {
|
||||||
|
// Require that one of the oneof fields is set.
|
||||||
|
optional bool required = 1;
|
||||||
|
}
|
20
pkg/amqp/rabbitmq.go
Normal file
20
pkg/amqp/rabbitmq.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package amqp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/wire"
|
||||||
|
"github.com/streadway/amqp"
|
||||||
|
)
|
||||||
|
|
||||||
|
var RabbitMqConn *amqp.Connection
|
||||||
|
|
||||||
|
var Provider = wire.NewSet(NewRabbitMq)
|
||||||
|
|
||||||
|
func NewRabbitMq() *amqp.Connection {
|
||||||
|
//var err error
|
||||||
|
// 创建连接
|
||||||
|
/*RabbitMqConn, err = amqp.Dial(fmt.Sprintf("amqp://%s:%s@%s:%d/%s", appConfig.Data.RabbitMq.User, appConfig.Data.RabbitMq.Password, appConfig.Data.RabbitMq.Host, appConfig.Data.RabbitMq.Port, appConfig.Data.RabbitMq.Vhost))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to connect RabbitMQ: %v", err)
|
||||||
|
}*/
|
||||||
|
return RabbitMqConn
|
||||||
|
}
|
18
pkg/app/app.go
Normal file
18
pkg/app/app.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"exhibition-register/pkg/tracing"
|
||||||
|
"github.com/bwmarrin/snowflake"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ModuleClients *App
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
Lg *zap.Logger
|
||||||
|
//RedisClient *redis.Client
|
||||||
|
JaegerTracer *tracing.JaegerProvider
|
||||||
|
ExhibitionRegister *gorm.DB
|
||||||
|
SfNode *snowflake.Node
|
||||||
|
}
|
24
pkg/cache/redis.go
vendored
Normal file
24
pkg/cache/redis.go
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-redis/redis"
|
||||||
|
"github.com/google/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
var RedisProvider = wire.NewSet(NewRedis)
|
||||||
|
|
||||||
|
// TODO 添加连接池
|
||||||
|
func NewRedis() *redis.Client {
|
||||||
|
//redisDb, _ := strconv.Atoi(dciConfig.Data.Redis.DB)
|
||||||
|
//RedisClient := redis.NewClient(&redis.Options{
|
||||||
|
// Addr: dciConfig.Data.Redis.Addr,
|
||||||
|
// Password: dciConfig.Data.Redis.Password,
|
||||||
|
// DB: redisDb,
|
||||||
|
//})
|
||||||
|
//_, err := RedisClient.Ping().Result()
|
||||||
|
//if err != nil {
|
||||||
|
// logger.Errorf("connRedis err", err)
|
||||||
|
// panic(err)
|
||||||
|
//}
|
||||||
|
return nil
|
||||||
|
}
|
18
pkg/db/exhibition_register.go
Normal file
18
pkg/db/exhibition_register.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
exhibitionConfig "exhibition-register/config"
|
||||||
|
"github.com/google/wire"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Provider = wire.NewSet(NewDB)
|
||||||
|
|
||||||
|
func NewDB() *gorm.DB {
|
||||||
|
connDci := strings.Join([]string{exhibitionConfig.Data.ExhibitionRegister.User, ":", exhibitionConfig.Data.ExhibitionRegister.Password,
|
||||||
|
"@tcp(", exhibitionConfig.Data.ExhibitionRegister.Host, ":", exhibitionConfig.Data.ExhibitionRegister.Port, ")/",
|
||||||
|
exhibitionConfig.Data.ExhibitionRegister.DbName, "?charset=utf8mb4&parseTime=true&loc=Local"}, "")
|
||||||
|
ExhibitionRegister := loadMysqlConn(connDci)
|
||||||
|
return ExhibitionRegister
|
||||||
|
}
|
62
pkg/db/mysql.go
Normal file
62
pkg/db/mysql.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
|
"gorm.io/gorm/schema"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loadMysqlConn(conn string) *gorm.DB {
|
||||||
|
var ormLogger logger.Interface
|
||||||
|
if gin.Mode() == "debug" {
|
||||||
|
ormLogger = logger.Default.LogMode(logger.Info)
|
||||||
|
} else {
|
||||||
|
ormLogger = logger.Default
|
||||||
|
}
|
||||||
|
db, err := gorm.Open(mysql.New(mysql.Config{
|
||||||
|
DSN: conn, // DSN data source name
|
||||||
|
DefaultStringSize: 256, // string 类型字段的默认长度
|
||||||
|
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
|
||||||
|
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
|
||||||
|
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
|
||||||
|
SkipInitializeWithVersion: false, // 根据版本自动配置
|
||||||
|
}), &gorm.Config{
|
||||||
|
Logger: ormLogger,
|
||||||
|
NamingStrategy: schema.NamingStrategy{
|
||||||
|
SingularTable: true,
|
||||||
|
},
|
||||||
|
DisableForeignKeyConstraintWhenMigrating: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sqlDB, _ := db.DB()
|
||||||
|
sqlDB.SetMaxIdleConns(20) //设置连接池,空闲
|
||||||
|
sqlDB.SetMaxOpenConns(100) //打开
|
||||||
|
sqlDB.SetConnMaxLifetime(time.Second * 30)
|
||||||
|
err = db.AutoMigrate() //自迁移
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
|
||||||
|
func addColumn(db *gorm.DB, dst interface{}, column string) {
|
||||||
|
exist := db.Migrator().HasColumn(dst, column)
|
||||||
|
if !exist {
|
||||||
|
err := db.Migrator().AddColumn(dst, column)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func addTable(db *gorm.DB, dst interface{}) {
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
28
pkg/err/common.go
Normal file
28
pkg/err/common.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package err
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"exhibition-register/pkg/app"
|
||||||
|
"fmt"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ReturnError(err error, msg, print string) error {
|
||||||
|
if err != nil {
|
||||||
|
field := zap.Field{}
|
||||||
|
field.String = err.Error()
|
||||||
|
//app.ModuleClients.Lg.Error(print, field)
|
||||||
|
fmt.Printf(print+"%+v\n", err)
|
||||||
|
return errors.New(msg)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NoReturnError(err error, print string) {
|
||||||
|
if err != nil {
|
||||||
|
field := zap.Field{}
|
||||||
|
field.String = err.Error()
|
||||||
|
app.ModuleClients.Lg.Error(print, field)
|
||||||
|
fmt.Printf(print+"%+v\n", err)
|
||||||
|
}
|
||||||
|
}
|
9
pkg/err/resultCode.go
Normal file
9
pkg/err/resultCode.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package err
|
||||||
|
|
||||||
|
var ResultCode = map[string]string{
|
||||||
|
"OK": "正常返回",
|
||||||
|
"BAD_REQUEST": "请求参数错误",
|
||||||
|
"PERMISSION_ERROR": "权限错误",
|
||||||
|
"BUSINESS_ERROR": "业务内容错误",
|
||||||
|
"SERVER_ERROR": "服务器错误",
|
||||||
|
}
|
3
pkg/err/resultMsg.go
Normal file
3
pkg/err/resultMsg.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package err
|
||||||
|
|
||||||
|
var ResultMsg = map[string]string{}
|
5
pkg/init/start.go
Normal file
5
pkg/init/start.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
//db.DBMigration()
|
||||||
|
}
|
63
pkg/logger/zap_logger.go
Normal file
63
pkg/logger/zap_logger.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
exhibitionConfig "exhibition-register/config"
|
||||||
|
"github.com/google/wire"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/natefinch/lumberjack"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Provider = wire.NewSet(ZapInit)
|
||||||
|
|
||||||
|
// ZapInit 初始化lg
|
||||||
|
func ZapInit() *zap.Logger {
|
||||||
|
var err error
|
||||||
|
maxSize, _ := strconv.Atoi(exhibitionConfig.Data.ZapLog.MaxSize)
|
||||||
|
maxAge, _ := strconv.Atoi(exhibitionConfig.Data.ZapLog.MaxAge)
|
||||||
|
maxBackups, _ := strconv.Atoi(exhibitionConfig.Data.ZapLog.MaxAge)
|
||||||
|
writeSyncer := getLogWriter(exhibitionConfig.Data.ZapLog.Filename, maxSize, maxBackups, maxAge)
|
||||||
|
encoder := getEncoder()
|
||||||
|
var l = new(zapcore.Level)
|
||||||
|
err = l.UnmarshalText([]byte(exhibitionConfig.Data.ZapLog.Level))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var core zapcore.Core
|
||||||
|
if exhibitionConfig.Data.System.Mode == "dev" {
|
||||||
|
// 进入开发模式,日志输出到终端
|
||||||
|
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
|
||||||
|
core = zapcore.NewTee(
|
||||||
|
zapcore.NewCore(encoder, writeSyncer, l),
|
||||||
|
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), zapcore.DebugLevel),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
core = zapcore.NewCore(encoder, writeSyncer, l)
|
||||||
|
}
|
||||||
|
lg := zap.New(core, zap.AddCaller())
|
||||||
|
zap.ReplaceGlobals(lg)
|
||||||
|
return lg
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEncoder() zapcore.Encoder {
|
||||||
|
encoderConfig := zap.NewProductionEncoderConfig()
|
||||||
|
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||||
|
encoderConfig.TimeKey = "time"
|
||||||
|
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
|
||||||
|
encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
|
||||||
|
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
|
||||||
|
return zapcore.NewJSONEncoder(encoderConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer {
|
||||||
|
lumberJackLogger := &lumberjack.Logger{
|
||||||
|
Filename: filename,
|
||||||
|
MaxSize: maxSize,
|
||||||
|
MaxBackups: maxBackup,
|
||||||
|
MaxAge: maxAge,
|
||||||
|
}
|
||||||
|
return zapcore.AddSync(lumberJackLogger)
|
||||||
|
}
|
122
pkg/msg/msg.go
Normal file
122
pkg/msg/msg.go
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
package msg
|
||||||
|
|
||||||
|
const (
|
||||||
|
SERVER_CONFIG = "config.yaml"
|
||||||
|
SERVER_DUBBOGO_CONFIG = "dubbogo.yaml"
|
||||||
|
MODE_ENV = "MODE_ENV"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Success = "操作成功"
|
||||||
|
Failed = "操作失败"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WholeTimeFormat = "2006-01-02 15:04:05"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//ExamWaiting = 1 //未开始
|
||||||
|
ExamDoing = 1 //进行中
|
||||||
|
ExamFinished = 2 //已结束
|
||||||
|
|
||||||
|
TrainWaiting = 1 //未开始
|
||||||
|
TrainDoing = 2 //进行中
|
||||||
|
TrainFinished = 3 //已结束
|
||||||
|
|
||||||
|
IsRight = 1 //正确
|
||||||
|
IsErr = 2 //正确
|
||||||
|
|
||||||
|
IsPass = 3 // 通过
|
||||||
|
NotPass = 2 // 未通过
|
||||||
|
IsNotStart = 1 // 未完成
|
||||||
|
|
||||||
|
NotGot = 1
|
||||||
|
IsGot = 2
|
||||||
|
|
||||||
|
IsGift = 2
|
||||||
|
IsNotGift = 1
|
||||||
|
|
||||||
|
IsTrain = 1 // 完成培训 及 录制了视频
|
||||||
|
|
||||||
|
IsNeedAnswer = 1 // 需要答题
|
||||||
|
|
||||||
|
IsNeedTrain = 1 // 需要培训
|
||||||
|
|
||||||
|
IsAll = 1 // 全部都需要参加
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Http = 200
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ErrorLogin = "账号或密码错误"
|
||||||
|
ErrorJSONParse = "json解析失败"
|
||||||
|
ErrorJSONMarshal = "json序列化失败"
|
||||||
|
ErrorForUpdate = "锁定错误"
|
||||||
|
ErrorInsert = "插入异常"
|
||||||
|
ErrorDelete = "删除异常"
|
||||||
|
ErrorUpdate = "更新异常"
|
||||||
|
ErrorSelect = "查询异常"
|
||||||
|
ErrorEmptyParam = "值为空"
|
||||||
|
ErrorCopierStruct = "拷贝结构体错误"
|
||||||
|
ErrorNoAction = "无需操作"
|
||||||
|
ErrorInvalidParam = "参数不合法"
|
||||||
|
ErrorNoData = "没有数据"
|
||||||
|
ErrorDatetime = "时间格式错误"
|
||||||
|
|
||||||
|
ErrorSha256Write = "sha256加密错误"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ErrOperate = "操作错误"
|
||||||
|
|
||||||
|
ErrCreateUser = "创建用户失败"
|
||||||
|
ErrUpdateUser = "更新用户失败"
|
||||||
|
ErrGetUserInfo = "查询用户信息失败"
|
||||||
|
ErrGetUserInfoExam = "查询答题用户信息失败"
|
||||||
|
ErrUserNotRegister = "用户未注册"
|
||||||
|
ErrVerifyUser = "校验用户信息失败"
|
||||||
|
ErrUserHad = "当前用户信息已存在"
|
||||||
|
|
||||||
|
ErrCreateExam = "创建考试失败"
|
||||||
|
ErrUpdateExam = "更新考试失败"
|
||||||
|
ErrGetExamInfoData = "查询考试信息失败"
|
||||||
|
ErrGetExamInfoCount = "查询考试信息失败"
|
||||||
|
ErrGetExamInfoNoParams = "查询考试信息条件错误"
|
||||||
|
ErUpdateExamStatus = "更新考试状态错误"
|
||||||
|
|
||||||
|
ErrCreateTrain = "创建培训失败"
|
||||||
|
ErrUpdateTrain = "更新培训失败"
|
||||||
|
ErrGetTrainInfoData = "查询培训信息失败"
|
||||||
|
ErrGetTrainInfoCount = "查询培训信息失败"
|
||||||
|
ErrGetTrainInfoNoParams = "查询培训信息条件错误"
|
||||||
|
|
||||||
|
ErrCreateQuestion = "创建题目失败"
|
||||||
|
ErrUpdateQuestion = "更新题目失败"
|
||||||
|
ErrQuestionInUse = "题目正在被使用,无法修改"
|
||||||
|
ErrGetQuestionInfoData = "查询题目信息失败"
|
||||||
|
ErrGetQuestionInfoCount = "查询题目信息失败"
|
||||||
|
|
||||||
|
ErrCreateGift = "创建礼品失败"
|
||||||
|
ErrUpdateGift = "更新礼品失败"
|
||||||
|
ErrGetGiftInfoData = "查询礼品信息失败"
|
||||||
|
ErrGetGiftInfoCount = "查询礼品信息失败"
|
||||||
|
|
||||||
|
ErrCreateUserHis = "创建考试成绩失败"
|
||||||
|
ErrQueryUserHis = "查询考试成绩失败"
|
||||||
|
ErrQueryAnswerScore = "查询答案分值失败"
|
||||||
|
ErrQueryAnswer = "查询答案失败"
|
||||||
|
ErrCreateUserAnswerHis = "创建作答记录失败"
|
||||||
|
ErrCreateUserTrainHis = "创建培训记录失败"
|
||||||
|
ErrUpdateUserTrainHis = "更新培训记录失败"
|
||||||
|
ErrCreateUserGiftHis = "创建礼品记录失败"
|
||||||
|
ErrUpdateUserGiftHis = "更新礼品状态失败"
|
||||||
|
ErrCheckAnswer = "答案核对失败"
|
||||||
|
ErrUpdateUserHis = "更新考试成绩失败"
|
||||||
|
ErrUpdateParticipantNum = "更新参与人数失败"
|
||||||
|
ErrUpdateParticipantPassNum = "更新通过人数失败"
|
||||||
|
ErrQueryVideo = "查询视频信息失败"
|
||||||
|
ErrQueryUserAnswerHis = "查询答题记录失败"
|
||||||
|
)
|
4
pkg/service/init.go
Normal file
4
pkg/service/init.go
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
}
|
36
pkg/snowf/snowflake.go
Normal file
36
pkg/snowf/snowflake.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package snowf
|
||||||
|
|
||||||
|
import (
|
||||||
|
exhibitionConfig "exhibition-register/config"
|
||||||
|
"exhibition-register/pkg/app"
|
||||||
|
"github.com/bwmarrin/snowflake"
|
||||||
|
"github.com/google/wire"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Provider = wire.NewSet(NewSf)
|
||||||
|
|
||||||
|
func NewSf() *snowflake.Node {
|
||||||
|
var err error
|
||||||
|
var st time.Time
|
||||||
|
nodeNum, _ := strconv.Atoi(exhibitionConfig.Data.SnowFlake.NodeNum)
|
||||||
|
st, err = time.Parse("2006-01-02", exhibitionConfig.Data.SnowFlake.StartTime)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
snowflake.Epoch = st.UnixNano() / 1000000
|
||||||
|
node, errS := snowflake.NewNode(int64(nodeNum))
|
||||||
|
if errS != nil {
|
||||||
|
panic(errS)
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenIDInt64() int64 {
|
||||||
|
return app.ModuleClients.SfNode.Generate().Int64()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIDBase64() string {
|
||||||
|
return app.ModuleClients.SfNode.Generate().Base64()
|
||||||
|
}
|
51
pkg/tracing/jaeger.go
Normal file
51
pkg/tracing/jaeger.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package tracing
|
||||||
|
|
||||||
|
import (
|
||||||
|
exhibitionConfig "exhibition-register/config"
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/wire"
|
||||||
|
"github.com/opentracing/opentracing-go"
|
||||||
|
"github.com/uber/jaeger-client-go"
|
||||||
|
jaegerConfig "github.com/uber/jaeger-client-go/config"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Provider = wire.NewSet(NewTracing)
|
||||||
|
|
||||||
|
type JaegerProvider struct {
|
||||||
|
Tracer opentracing.Tracer
|
||||||
|
Closer io.Closer
|
||||||
|
}
|
||||||
|
|
||||||
|
//var JaegerPoint *JaegerProvider
|
||||||
|
|
||||||
|
func NewTracing() (jaegerProvider *JaegerProvider) {
|
||||||
|
if exhibitionConfig.Data.Jaeger.Open != "true" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
jaegerProvider = &JaegerProvider{}
|
||||||
|
cfg := jaegerConfig.Configuration{
|
||||||
|
ServiceName: "exhibition-register",
|
||||||
|
Sampler: &jaegerConfig.SamplerConfig{
|
||||||
|
Type: jaeger.SamplerTypeRemote,
|
||||||
|
Param: 1,
|
||||||
|
},
|
||||||
|
Reporter: &jaegerConfig.ReporterConfig{
|
||||||
|
LocalAgentHostPort: exhibitionConfig.Data.Jaeger.Addr,
|
||||||
|
LogSpans: true,
|
||||||
|
BufferFlushInterval: 5 * time.Second,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
nativeTracerIo, closerIo, err := cfg.NewTracer(jaegerConfig.Logger(jaeger.StdLogger))
|
||||||
|
if err != nil {
|
||||||
|
zap.L().Error("nativeTracer err", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
opentracing.SetGlobalTracer(nativeTracerIo)
|
||||||
|
jaegerProvider.Tracer = nativeTracerIo
|
||||||
|
jaegerProvider.Closer = closerIo
|
||||||
|
//JaegerPoint = jaegerProvider
|
||||||
|
return
|
||||||
|
}
|
75
pkg/utils/http.go
Normal file
75
pkg/utils/http.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Post(url string, jsonStr []byte) (statusCode int, result string) {
|
||||||
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
statusCode = resp.StatusCode
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
fmt.Println("post url:", url)
|
||||||
|
fmt.Println("response Headers:", resp.Header)
|
||||||
|
fmt.Println("response Body:", string(body))
|
||||||
|
result = string(body)
|
||||||
|
zap.L().Info("post", zap.Any("url", url), zap.Any("jsonStr", jsonStr), zap.Any("result", result))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Get(url string) (statusCode int, result string) {
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
statusCode = resp.StatusCode
|
||||||
|
fmt.Println("response StatusCode:", resp.StatusCode)
|
||||||
|
fmt.Println("response Status:", resp.Status)
|
||||||
|
fmt.Println("response Headers:", resp.Header)
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
result = string(body)
|
||||||
|
fmt.Println("response Body:", string(body))
|
||||||
|
zap.L().Info("Get", zap.Any("url", url), zap.Any("result", result))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func PutFromFileUrlWithStream(url, fileName, fileUrl string) (statusCode int, result string) {
|
||||||
|
file, err := http.Get(fileUrl)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer file.Body.Close()
|
||||||
|
fileBody, _ := ioutil.ReadAll(file.Body)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("PUT", url, bytes.NewBuffer(fileBody))
|
||||||
|
req.Header.Set("Content-Type", "application/octet-stream")
|
||||||
|
req.Header.Set("x-oss-meta-rawfilename", fileName)
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
//panic(err)
|
||||||
|
return 400, "执行文件上传失败"
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
statusCode = resp.StatusCode
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
result = string(body)
|
||||||
|
fmt.Println("put url:", url)
|
||||||
|
fmt.Println("fileName :", fileName)
|
||||||
|
fmt.Println("response Headers:", resp.Header)
|
||||||
|
//fmt.Println("response Body:", string(body))
|
||||||
|
fmt.Println("response StatusCode:", statusCode)
|
||||||
|
//zap.L().Info("post", zap.Any("url", url), zap.Any("jsonStr", bytes.NewBuffer(fileBody).String()), zap.Any("result", result))
|
||||||
|
return
|
||||||
|
}
|
11
pkg/utils/msg.go
Normal file
11
pkg/utils/msg.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
func SubstrError(err error) (sErr error) {
|
||||||
|
start := strings.Index(err.Error(), ":")
|
||||||
|
msg := err.Error()[start+2:]
|
||||||
|
sErr = errors.New(msg)
|
||||||
|
return
|
||||||
|
}
|
50
pkg/utils/time.go
Normal file
50
pkg/utils/time.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"exhibition-register/pkg/msg"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DateTimeFormat = "2006-01-02 15:04:05"
|
||||||
|
DateFormat = "2006-01-02"
|
||||||
|
DateFormatYmdHisDot = "2006.01.02 15:04"
|
||||||
|
DateFormatMonth = "2006年01月02日 15:04"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DatetimeToTimes(datetime string, dateFormat string) (times int32, err error) {
|
||||||
|
if datetime == "" {
|
||||||
|
times = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loc, _ := time.LoadLocation("Asia/Shanghai")
|
||||||
|
t, err := time.ParseInLocation(dateFormat, datetime, loc)
|
||||||
|
if err != nil {
|
||||||
|
zap.L().Error("DatetimeToTimes err:"+datetime+":", zap.Error(err))
|
||||||
|
err = errors.New(msg.ErrorDatetime)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
times = int32(t.Unix())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TimesToDatetime(times int32, format string) string {
|
||||||
|
if times == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
t := time.Unix(int64(times), 0)
|
||||||
|
if format == "" {
|
||||||
|
format = DateTimeFormat
|
||||||
|
}
|
||||||
|
return t.Format(format)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonthInfo() (startTime int64, endTime int64) {
|
||||||
|
timeNow := time.Now()
|
||||||
|
timeToday := time.Date(timeNow.Year(), timeNow.Month(), timeNow.Day(), 0, 0, 0, 0, timeNow.Location()) // 获取当天0点时间 time类型
|
||||||
|
startTime = timeToday.AddDate(0, 0, -timeToday.Day()+1).Unix() // 获取本月第一天0点 时间戳类型
|
||||||
|
endTime = timeToday.AddDate(0, 1, -timeToday.Day()+1).Unix()
|
||||||
|
return
|
||||||
|
}
|
8
pkg/utils/uuid.go
Normal file
8
pkg/utils/uuid.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import "github.com/nacos-group/nacos-sdk-go/inner/uuid"
|
||||||
|
|
||||||
|
func GetUUID() string {
|
||||||
|
id, _ := uuid.NewV4()
|
||||||
|
return id.String()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user