feat: init

This commit is contained in:
micah 2026-03-28 19:29:40 +08:00
commit 36f22a6092
36 changed files with 3173 additions and 0 deletions

37
.gitignore vendored Normal file
View File

@ -0,0 +1,37 @@
*.o
*.a
*.so
_obj
_test
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.exe~
*.test
*.prof
*.rar
*.zip
*.gz
*.psd
*.bmd
*.cfg
*.pptx
*.log
*nohup.out
*settings.pyc
*.sublime-project
*.sublime-workspace
!.gitkeep
.DS_Store
/.idea
/.vscode
/output
/logs
*.local.yml
dumped_hertz_remote_config.json

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# starter
```shell
# 1. 安装插件
go install github.com/cloudwego/hertz/cmd/hz@latest
go install github.com/cloudwego/thriftgo@v0.4.2
# 2. 初始化项目
hz new -module gitea.micah.wiki/pandora/starter -idl idl/api_service.thrift
# 3. 更新项目
hz update -idl idl/api_service.thrift
```

136
app/config/config.go Normal file
View File

@ -0,0 +1,136 @@
package config
import (
"fmt"
"os"
"path/filepath"
"strings"
"sync"
"gopkg.in/yaml.v3"
)
var (
config *Config
once sync.Once
)
func Init(args []string) {
_initConfig(args)
}
type Config struct {
Server struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Env string `yaml:"env"`
} `yaml:"server"`
// 内部加工配置
LogFile string
}
func GetConfig() *Config {
return _initConfig(nil)
}
func _initConfig(args []string) *Config {
if config == nil {
once.Do(func() {
c, err := loadConfig(args)
if err != nil {
panic(err)
}
config = c
})
}
return config
}
// 获取配置文件的绝对路径
func getConfigFile(confFile string) string {
if confFile != "" {
if _, err := os.Stat(confFile); err == nil {
return confFile
}
}
// 方案:优先从工作目录查找(适配 GoLand 直接运行的场景)
workDir, err := os.Getwd()
if err == nil {
workDirConfig := filepath.Join(workDir, "output/conf/conf.yml")
if _, err := os.Stat(workDirConfig); err == nil {
return workDirConfig
}
workDirConfig = filepath.Join(workDir, "conf/conf.yml")
if _, err := os.Stat(workDirConfig); err == nil {
return workDirConfig
}
if strings.Contains(workDirConfig, "starter") {
values := strings.Split(workDirConfig, "/starter")
if len(values) > 1 {
v := filepath.Join(values[0], "starter", "conf/conf.yml")
if _, err := os.Stat(v); err == nil {
return v
}
}
}
}
// 方案:从程序执行路径推导(适配部署环境)
exePath, err := os.Executable()
if err != nil {
panic(fmt.Sprintf("获取程序路径失败: %v", err))
}
exeDir := filepath.Dir(exePath)
// 判断是否是部署环境bin 目录下)
if filepath.Base(exeDir) == "bin" {
// 部署环境output/bin/ -> output/conf/conf.yml
return filepath.Join(exeDir, "../conf/conf.yml")
}
// 兜底:程序目录下的 conf/conf.yaml
return filepath.Join(exeDir, "conf/conf.yml")
}
// 加载配置文件
func loadConfig(args []string) (*Config, error) {
confFile := getValueFromArgs(args, "config")
configFile := getConfigFile(confFile)
fmt.Println("configFile:", configFile)
// 读取配置文件内容
data, err := os.ReadFile(configFile)
if err != nil {
return nil, fmt.Errorf("读取配置文件失败: %v", err)
}
// 解析 YAML 到结构体
var c Config
if err := yaml.Unmarshal(data, &c); err != nil {
return nil, fmt.Errorf("解析 YAML 失败: %v", err)
}
prefix := ""
if !strings.Contains(configFile, "/output/conf/") {
prefix = "/output"
}
pathArr := strings.Split(configFile, "/conf/")
if len(pathArr) == 0 {
panic("配置文件需要在`conf`目录下")
}
logDir := pathArr[0] + prefix + "/logs"
fmt.Println("logDir:", logDir)
// 自动创建日志目录(关键:避免目录不存在导致写入失败)
if err := os.MkdirAll(logDir, 0755); err != nil {
panic(fmt.Sprintf("创建日志目录失败: %v", err))
}
c.LogFile = filepath.Join(logDir, "starter.log")
return &c, nil
}
func getValueFromArgs(args []string, key string) string {
for _, arg := range args {
if strings.HasPrefix(arg, fmt.Sprintf("%s=", key)) {
value := strings.ReplaceAll(arg, fmt.Sprintf("%s=", key), "")
return value
}
}
return ""
}

View File

@ -0,0 +1,14 @@
package initialize
import (
"gitea.micah.wiki/pandora/starter/app/config"
"gitea.micah.wiki/pandora/starter/pkg/logx"
)
func Init(args []string) {
config.Init(args)
logx.Init()
}
func Close() {
logx.Close()
}

View File

@ -0,0 +1,35 @@
// Code generated by hertz generator.
package api_service
import (
"context"
"gitea.micah.wiki/pandora/starter/biz/model/base"
health "gitea.micah.wiki/pandora/starter/biz/model/health"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
// Ping .
// @router /openapi/health/ping [GET]
func Ping(ctx context.Context, c *app.RequestContext) {
var err error
var req health.PingRequest
err = c.BindAndValidate(&req)
if err != nil {
c.String(consts.StatusBadRequest, err.Error())
return
}
resp := &health.PingResponse{
Code: 0,
Message: "pong",
Base: &base.BaseResp{
StatusMessage: "",
StatusCode: 0,
},
}
c.JSON(consts.StatusOK, resp)
}

18
biz/handler/ping.go Normal file
View File

@ -0,0 +1,18 @@
// Code generated by hertz generator.
package handler
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
// Ping .
func Ping(ctx context.Context, c *app.RequestContext) {
c.JSON(consts.StatusOK, utils.H{
"message": "pong",
})
}

24
biz/middleware/cors.go Normal file
View File

@ -0,0 +1,24 @@
package middleware
import (
"context"
"github.com/cloudwego/hertz/pkg/app"
)
func CorsMiddleware() app.HandlerFunc {
return func(c context.Context, ctx *app.RequestContext) {
origin := ctx.Request.Header.Get("Origin")
ctx.Header("Access-Control-Allow-Origin", ctx.Request.Header.Get("origin"))
if origin != "" {
ctx.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
ctx.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token,Authorization,Cookie,FTF-Cookie-accessToken, x-origin")
ctx.Header("Access-Control-Allow-Credentials", "true")
}
method := ctx.Request.Method()
if string(method) == "OPTIONS" {
ctx.AbortWithStatus(200)
}
ctx.Next(c)
}
}

27
biz/middleware/log.go Normal file
View File

@ -0,0 +1,27 @@
package middleware
import (
"context"
"strings"
"time"
"github.com/cloudwego/hertz/pkg/app"
"gitea.micah.wiki/pandora/starter/pkg/logx"
)
func LogMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
start := time.Now()
uri := string(c.Request.URI().Path())
query := string(c.Request.URI().QueryString())
body := string(c.Request.Body())
if len(body) > 0 {
body = strings.ReplaceAll(body, "\n", "\\n")
}
logx.CtxInfo(ctx, "com_request_in uri: `%s`, query: `%s`, body: `%s`", uri, query, body)
c.Next(ctx)
logx.CtxInfo(ctx, "com_request_out uri: `%s`, cost: `%+v`, resp: `%s`", uri, time.Since(start), string(c.Response.Body()))
}
}

View File

@ -0,0 +1,21 @@
package middleware
import (
"context"
"gitea.micah.wiki/pandora/starter/pkg/requestid"
"gitea.micah.wiki/pandora/starter/pkg/uniqueid"
"github.com/cloudwego/hertz/pkg/app"
)
func RequestIDMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
existingID := c.Request.Header.Get(requestid.KLogIDKey)
if existingID == "" {
existingID = uniqueid.GetUniqueID()
c.Request.Header.Set(requestid.KLogIDKey, existingID)
}
ctx = requestid.SaveLogID(ctx, existingID)
c.Next(ctx)
}
}

View File

@ -0,0 +1,431 @@
// Code generated by thriftgo (0.4.2). DO NOT EDIT.
package api_service
import (
"context"
"fmt"
"gitea.micah.wiki/pandora/starter/biz/model/health"
"github.com/apache/thrift/lib/go/thrift"
)
type HealthService interface {
Ping(ctx context.Context, req *health.PingRequest) (r *health.PingResponse, err error)
}
type HealthServiceClient struct {
c thrift.TClient
}
func NewHealthServiceClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *HealthServiceClient {
return &HealthServiceClient{
c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t)),
}
}
func NewHealthServiceClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *HealthServiceClient {
return &HealthServiceClient{
c: thrift.NewTStandardClient(iprot, oprot),
}
}
func NewHealthServiceClient(c thrift.TClient) *HealthServiceClient {
return &HealthServiceClient{
c: c,
}
}
func (p *HealthServiceClient) Client_() thrift.TClient {
return p.c
}
func (p *HealthServiceClient) Ping(ctx context.Context, req *health.PingRequest) (r *health.PingResponse, err error) {
var _args HealthServicePingArgs
_args.Req = req
var _result HealthServicePingResult
if err = p.Client_().Call(ctx, "Ping", &_args, &_result); err != nil {
return
}
return _result.GetSuccess(), nil
}
type HealthServiceProcessor struct {
processorMap map[string]thrift.TProcessorFunction
handler HealthService
}
func (p *HealthServiceProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
p.processorMap[key] = processor
}
func (p *HealthServiceProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
processor, ok = p.processorMap[key]
return processor, ok
}
func (p *HealthServiceProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
return p.processorMap
}
func NewHealthServiceProcessor(handler HealthService) *HealthServiceProcessor {
self := &HealthServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
self.AddToProcessorMap("Ping", &healthServiceProcessorPing{handler: handler})
return self
}
func (p *HealthServiceProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
name, _, seqId, err := iprot.ReadMessageBegin()
if err != nil {
return false, err
}
if processor, ok := p.GetProcessorFunction(name); ok {
return processor.Process(ctx, seqId, iprot, oprot)
}
iprot.Skip(thrift.STRUCT)
iprot.ReadMessageEnd()
x := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return false, x
}
type healthServiceProcessorPing struct {
handler HealthService
}
func (p *healthServiceProcessorPing) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := HealthServicePingArgs{}
if err = args.Read(iprot); err != nil {
iprot.ReadMessageEnd()
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
oprot.WriteMessageBegin("Ping", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return false, err
}
iprot.ReadMessageEnd()
var err2 error
result := HealthServicePingResult{}
var retval *health.PingResponse
if retval, err2 = p.handler.Ping(ctx, args.Req); err2 != nil {
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Ping: "+err2.Error())
oprot.WriteMessageBegin("Ping", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush(ctx)
return true, err2
} else {
result.Success = retval
}
if err2 = oprot.WriteMessageBegin("Ping", thrift.REPLY, seqId); err2 != nil {
err = err2
}
if err2 = result.Write(oprot); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.Flush(ctx); err == nil && err2 != nil {
err = err2
}
if err != nil {
return
}
return true, err
}
type HealthServicePingArgs struct {
Req *health.PingRequest `thrift:"req,1"`
}
func NewHealthServicePingArgs() *HealthServicePingArgs {
return &HealthServicePingArgs{}
}
func (p *HealthServicePingArgs) InitDefault() {
}
var HealthServicePingArgs_Req_DEFAULT *health.PingRequest
func (p *HealthServicePingArgs) GetReq() (v *health.PingRequest) {
if !p.IsSetReq() {
return HealthServicePingArgs_Req_DEFAULT
}
return p.Req
}
var fieldIDToName_HealthServicePingArgs = map[int16]string{
1: "req",
}
func (p *HealthServicePingArgs) IsSetReq() bool {
return p.Req != nil
}
func (p *HealthServicePingArgs) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if fieldTypeId == thrift.STRUCT {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_HealthServicePingArgs[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *HealthServicePingArgs) ReadField1(iprot thrift.TProtocol) error {
_field := health.NewPingRequest()
if err := _field.Read(iprot); err != nil {
return err
}
p.Req = _field
return nil
}
func (p *HealthServicePingArgs) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("Ping_args"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField1(oprot); err != nil {
fieldId = 1
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *HealthServicePingArgs) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("req", thrift.STRUCT, 1); err != nil {
goto WriteFieldBeginError
}
if err := p.Req.Write(oprot); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}
func (p *HealthServicePingArgs) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("HealthServicePingArgs(%+v)", *p)
}
type HealthServicePingResult struct {
Success *health.PingResponse `thrift:"success,0,optional"`
}
func NewHealthServicePingResult() *HealthServicePingResult {
return &HealthServicePingResult{}
}
func (p *HealthServicePingResult) InitDefault() {
}
var HealthServicePingResult_Success_DEFAULT *health.PingResponse
func (p *HealthServicePingResult) GetSuccess() (v *health.PingResponse) {
if !p.IsSetSuccess() {
return HealthServicePingResult_Success_DEFAULT
}
return p.Success
}
var fieldIDToName_HealthServicePingResult = map[int16]string{
0: "success",
}
func (p *HealthServicePingResult) IsSetSuccess() bool {
return p.Success != nil
}
func (p *HealthServicePingResult) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 0:
if fieldTypeId == thrift.STRUCT {
if err = p.ReadField0(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_HealthServicePingResult[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *HealthServicePingResult) ReadField0(iprot thrift.TProtocol) error {
_field := health.NewPingResponse()
if err := _field.Read(iprot); err != nil {
return err
}
p.Success = _field
return nil
}
func (p *HealthServicePingResult) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("Ping_result"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField0(oprot); err != nil {
fieldId = 0
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *HealthServicePingResult) writeField0(oprot thrift.TProtocol) (err error) {
if p.IsSetSuccess() {
if err = oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
goto WriteFieldBeginError
}
if err := p.Success.Write(oprot); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 0 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 0 end error: ", p), err)
}
func (p *HealthServicePingResult) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("HealthServicePingResult(%+v)", *p)
}

895
biz/model/base/base.go Normal file
View File

@ -0,0 +1,895 @@
// Code generated by thriftgo (0.4.2). DO NOT EDIT.
package base
import (
"fmt"
"github.com/apache/thrift/lib/go/thrift"
)
type TrafficEnv struct {
Open bool `thrift:"open,1" form:"open" json:"open" query:"open"`
Env string `thrift:"env,2" form:"env" json:"env" query:"env"`
}
func NewTrafficEnv() *TrafficEnv {
return &TrafficEnv{
Open: false,
Env: "",
}
}
func (p *TrafficEnv) InitDefault() {
p.Open = false
p.Env = ""
}
func (p *TrafficEnv) GetOpen() (v bool) {
return p.Open
}
func (p *TrafficEnv) GetEnv() (v string) {
return p.Env
}
var fieldIDToName_TrafficEnv = map[int16]string{
1: "open",
2: "env",
}
func (p *TrafficEnv) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if fieldTypeId == thrift.BOOL {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 2:
if fieldTypeId == thrift.STRING {
if err = p.ReadField2(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_TrafficEnv[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *TrafficEnv) ReadField1(iprot thrift.TProtocol) error {
var _field bool
if v, err := iprot.ReadBool(); err != nil {
return err
} else {
_field = v
}
p.Open = _field
return nil
}
func (p *TrafficEnv) ReadField2(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.Env = _field
return nil
}
func (p *TrafficEnv) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("TrafficEnv"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField1(oprot); err != nil {
fieldId = 1
goto WriteFieldError
}
if err = p.writeField2(oprot); err != nil {
fieldId = 2
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *TrafficEnv) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("open", thrift.BOOL, 1); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteBool(p.Open); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}
func (p *TrafficEnv) writeField2(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("env", thrift.STRING, 2); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.Env); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 end error: ", p), err)
}
func (p *TrafficEnv) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("TrafficEnv(%+v)", *p)
}
type Base struct {
LogID string `thrift:"log_id,1" form:"log_id" json:"log_id" query:"log_id"`
Caller string `thrift:"caller,2" form:"caller" json:"caller" query:"caller"`
Addr string `thrift:"addr,3" form:"addr" json:"addr" query:"addr"`
Client string `thrift:"client,4" form:"client" json:"client" query:"client"`
TrafficEnv *TrafficEnv `thrift:"traffic_env,5,optional" form:"traffic_env" json:"traffic_env,omitempty" query:"traffic_env"`
Extra map[string]string `thrift:"extra,6,optional" form:"extra" json:"extra,omitempty" query:"extra"`
}
func NewBase() *Base {
return &Base{
LogID: "",
Caller: "",
Addr: "",
Client: "",
}
}
func (p *Base) InitDefault() {
p.LogID = ""
p.Caller = ""
p.Addr = ""
p.Client = ""
}
func (p *Base) GetLogID() (v string) {
return p.LogID
}
func (p *Base) GetCaller() (v string) {
return p.Caller
}
func (p *Base) GetAddr() (v string) {
return p.Addr
}
func (p *Base) GetClient() (v string) {
return p.Client
}
var Base_TrafficEnv_DEFAULT *TrafficEnv
func (p *Base) GetTrafficEnv() (v *TrafficEnv) {
if !p.IsSetTrafficEnv() {
return Base_TrafficEnv_DEFAULT
}
return p.TrafficEnv
}
var Base_Extra_DEFAULT map[string]string
func (p *Base) GetExtra() (v map[string]string) {
if !p.IsSetExtra() {
return Base_Extra_DEFAULT
}
return p.Extra
}
var fieldIDToName_Base = map[int16]string{
1: "log_id",
2: "caller",
3: "addr",
4: "client",
5: "traffic_env",
6: "extra",
}
func (p *Base) IsSetTrafficEnv() bool {
return p.TrafficEnv != nil
}
func (p *Base) IsSetExtra() bool {
return p.Extra != nil
}
func (p *Base) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if fieldTypeId == thrift.STRING {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 2:
if fieldTypeId == thrift.STRING {
if err = p.ReadField2(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 3:
if fieldTypeId == thrift.STRING {
if err = p.ReadField3(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 4:
if fieldTypeId == thrift.STRING {
if err = p.ReadField4(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 5:
if fieldTypeId == thrift.STRUCT {
if err = p.ReadField5(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 6:
if fieldTypeId == thrift.MAP {
if err = p.ReadField6(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_Base[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *Base) ReadField1(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.LogID = _field
return nil
}
func (p *Base) ReadField2(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.Caller = _field
return nil
}
func (p *Base) ReadField3(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.Addr = _field
return nil
}
func (p *Base) ReadField4(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.Client = _field
return nil
}
func (p *Base) ReadField5(iprot thrift.TProtocol) error {
_field := NewTrafficEnv()
if err := _field.Read(iprot); err != nil {
return err
}
p.TrafficEnv = _field
return nil
}
func (p *Base) ReadField6(iprot thrift.TProtocol) error {
_, _, size, err := iprot.ReadMapBegin()
if err != nil {
return err
}
_field := make(map[string]string, size)
for i := 0; i < size; i++ {
var _key string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_key = v
}
var _val string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_val = v
}
_field[_key] = _val
}
if err := iprot.ReadMapEnd(); err != nil {
return err
}
p.Extra = _field
return nil
}
func (p *Base) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("Base"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField1(oprot); err != nil {
fieldId = 1
goto WriteFieldError
}
if err = p.writeField2(oprot); err != nil {
fieldId = 2
goto WriteFieldError
}
if err = p.writeField3(oprot); err != nil {
fieldId = 3
goto WriteFieldError
}
if err = p.writeField4(oprot); err != nil {
fieldId = 4
goto WriteFieldError
}
if err = p.writeField5(oprot); err != nil {
fieldId = 5
goto WriteFieldError
}
if err = p.writeField6(oprot); err != nil {
fieldId = 6
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *Base) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("log_id", thrift.STRING, 1); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.LogID); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}
func (p *Base) writeField2(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("caller", thrift.STRING, 2); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.Caller); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 end error: ", p), err)
}
func (p *Base) writeField3(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("addr", thrift.STRING, 3); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.Addr); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 end error: ", p), err)
}
func (p *Base) writeField4(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("client", thrift.STRING, 4); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.Client); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 4 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 4 end error: ", p), err)
}
func (p *Base) writeField5(oprot thrift.TProtocol) (err error) {
if p.IsSetTrafficEnv() {
if err = oprot.WriteFieldBegin("traffic_env", thrift.STRUCT, 5); err != nil {
goto WriteFieldBeginError
}
if err := p.TrafficEnv.Write(oprot); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 5 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 5 end error: ", p), err)
}
func (p *Base) writeField6(oprot thrift.TProtocol) (err error) {
if p.IsSetExtra() {
if err = oprot.WriteFieldBegin("extra", thrift.MAP, 6); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteMapBegin(thrift.STRING, thrift.STRING, len(p.Extra)); err != nil {
return err
}
for k, v := range p.Extra {
if err := oprot.WriteString(k); err != nil {
return err
}
if err := oprot.WriteString(v); err != nil {
return err
}
}
if err := oprot.WriteMapEnd(); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 6 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 6 end error: ", p), err)
}
func (p *Base) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("Base(%+v)", *p)
}
type BaseResp struct {
StatusMessage string `thrift:"status_message,1" form:"status_message" json:"status_message" query:"status_message"`
StatusCode int32 `thrift:"status_code,2" form:"status_code" json:"status_code" query:"status_code"`
Extra map[string]string `thrift:"extra,3,optional" form:"extra" json:"extra,omitempty" query:"extra"`
}
func NewBaseResp() *BaseResp {
return &BaseResp{
StatusMessage: "",
StatusCode: 0,
}
}
func (p *BaseResp) InitDefault() {
p.StatusMessage = ""
p.StatusCode = 0
}
func (p *BaseResp) GetStatusMessage() (v string) {
return p.StatusMessage
}
func (p *BaseResp) GetStatusCode() (v int32) {
return p.StatusCode
}
var BaseResp_Extra_DEFAULT map[string]string
func (p *BaseResp) GetExtra() (v map[string]string) {
if !p.IsSetExtra() {
return BaseResp_Extra_DEFAULT
}
return p.Extra
}
var fieldIDToName_BaseResp = map[int16]string{
1: "status_message",
2: "status_code",
3: "extra",
}
func (p *BaseResp) IsSetExtra() bool {
return p.Extra != nil
}
func (p *BaseResp) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if fieldTypeId == thrift.STRING {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 2:
if fieldTypeId == thrift.I32 {
if err = p.ReadField2(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 3:
if fieldTypeId == thrift.MAP {
if err = p.ReadField3(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_BaseResp[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *BaseResp) ReadField1(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.StatusMessage = _field
return nil
}
func (p *BaseResp) ReadField2(iprot thrift.TProtocol) error {
var _field int32
if v, err := iprot.ReadI32(); err != nil {
return err
} else {
_field = v
}
p.StatusCode = _field
return nil
}
func (p *BaseResp) ReadField3(iprot thrift.TProtocol) error {
_, _, size, err := iprot.ReadMapBegin()
if err != nil {
return err
}
_field := make(map[string]string, size)
for i := 0; i < size; i++ {
var _key string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_key = v
}
var _val string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_val = v
}
_field[_key] = _val
}
if err := iprot.ReadMapEnd(); err != nil {
return err
}
p.Extra = _field
return nil
}
func (p *BaseResp) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("BaseResp"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField1(oprot); err != nil {
fieldId = 1
goto WriteFieldError
}
if err = p.writeField2(oprot); err != nil {
fieldId = 2
goto WriteFieldError
}
if err = p.writeField3(oprot); err != nil {
fieldId = 3
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *BaseResp) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("status_message", thrift.STRING, 1); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.StatusMessage); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}
func (p *BaseResp) writeField2(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("status_code", thrift.I32, 2); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteI32(p.StatusCode); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 end error: ", p), err)
}
func (p *BaseResp) writeField3(oprot thrift.TProtocol) (err error) {
if p.IsSetExtra() {
if err = oprot.WriteFieldBegin("extra", thrift.MAP, 3); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteMapBegin(thrift.STRING, thrift.STRING, len(p.Extra)); err != nil {
return err
}
for k, v := range p.Extra {
if err := oprot.WriteString(k); err != nil {
return err
}
if err := oprot.WriteString(v); err != nil {
return err
}
}
if err := oprot.WriteMapEnd(); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 3 end error: ", p), err)
}
func (p *BaseResp) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("BaseResp(%+v)", *p)
}

404
biz/model/health/health.go Normal file
View File

@ -0,0 +1,404 @@
// Code generated by thriftgo (0.4.2). DO NOT EDIT.
package health
import (
"fmt"
"gitea.micah.wiki/pandora/starter/biz/model/base"
"github.com/apache/thrift/lib/go/thrift"
)
type PingRequest struct {
Base *base.Base `thrift:"base,255" form:"base" json:"base" query:"base"`
}
func NewPingRequest() *PingRequest {
return &PingRequest{}
}
func (p *PingRequest) InitDefault() {
}
var PingRequest_Base_DEFAULT *base.Base
func (p *PingRequest) GetBase() (v *base.Base) {
if !p.IsSetBase() {
return PingRequest_Base_DEFAULT
}
return p.Base
}
var fieldIDToName_PingRequest = map[int16]string{
255: "base",
}
func (p *PingRequest) IsSetBase() bool {
return p.Base != nil
}
func (p *PingRequest) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 255:
if fieldTypeId == thrift.STRUCT {
if err = p.ReadField255(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_PingRequest[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
func (p *PingRequest) ReadField255(iprot thrift.TProtocol) error {
_field := base.NewBase()
if err := _field.Read(iprot); err != nil {
return err
}
p.Base = _field
return nil
}
func (p *PingRequest) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("PingRequest"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField255(oprot); err != nil {
fieldId = 255
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *PingRequest) writeField255(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("base", thrift.STRUCT, 255); err != nil {
goto WriteFieldBeginError
}
if err := p.Base.Write(oprot); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 255 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 255 end error: ", p), err)
}
func (p *PingRequest) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("PingRequest(%+v)", *p)
}
type PingResponse struct {
Code int32 `thrift:"code,1,required" form:"code,required" json:"code,required" query:"code,required"`
Message string `thrift:"message,2,required" form:"message,required" json:"message,required" query:"message,required"`
Base *base.BaseResp `thrift:"base,255" form:"base" json:"base" query:"base"`
}
func NewPingResponse() *PingResponse {
return &PingResponse{}
}
func (p *PingResponse) InitDefault() {
}
func (p *PingResponse) GetCode() (v int32) {
return p.Code
}
func (p *PingResponse) GetMessage() (v string) {
return p.Message
}
var PingResponse_Base_DEFAULT *base.BaseResp
func (p *PingResponse) GetBase() (v *base.BaseResp) {
if !p.IsSetBase() {
return PingResponse_Base_DEFAULT
}
return p.Base
}
var fieldIDToName_PingResponse = map[int16]string{
1: "code",
2: "message",
255: "base",
}
func (p *PingResponse) IsSetBase() bool {
return p.Base != nil
}
func (p *PingResponse) Read(iprot thrift.TProtocol) (err error) {
var fieldTypeId thrift.TType
var fieldId int16
var issetCode bool = false
var issetMessage bool = false
if _, err = iprot.ReadStructBegin(); err != nil {
goto ReadStructBeginError
}
for {
_, fieldTypeId, fieldId, err = iprot.ReadFieldBegin()
if err != nil {
goto ReadFieldBeginError
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if fieldTypeId == thrift.I32 {
if err = p.ReadField1(iprot); err != nil {
goto ReadFieldError
}
issetCode = true
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 2:
if fieldTypeId == thrift.STRING {
if err = p.ReadField2(iprot); err != nil {
goto ReadFieldError
}
issetMessage = true
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
case 255:
if fieldTypeId == thrift.STRUCT {
if err = p.ReadField255(iprot); err != nil {
goto ReadFieldError
}
} else if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
default:
if err = iprot.Skip(fieldTypeId); err != nil {
goto SkipFieldError
}
}
if err = iprot.ReadFieldEnd(); err != nil {
goto ReadFieldEndError
}
}
if err = iprot.ReadStructEnd(); err != nil {
goto ReadStructEndError
}
if !issetCode {
fieldId = 1
goto RequiredFieldNotSetError
}
if !issetMessage {
fieldId = 2
goto RequiredFieldNotSetError
}
return nil
ReadStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T read struct begin error: ", p), err)
ReadFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T read field %d begin error: ", p, fieldId), err)
ReadFieldError:
return thrift.PrependError(fmt.Sprintf("%T read field %d '%s' error: ", p, fieldId, fieldIDToName_PingResponse[fieldId]), err)
SkipFieldError:
return thrift.PrependError(fmt.Sprintf("%T field %d skip type %d error: ", p, fieldId, fieldTypeId), err)
ReadFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T read field end error", p), err)
ReadStructEndError:
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
RequiredFieldNotSetError:
return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("required field %s is not set", fieldIDToName_PingResponse[fieldId]))
}
func (p *PingResponse) ReadField1(iprot thrift.TProtocol) error {
var _field int32
if v, err := iprot.ReadI32(); err != nil {
return err
} else {
_field = v
}
p.Code = _field
return nil
}
func (p *PingResponse) ReadField2(iprot thrift.TProtocol) error {
var _field string
if v, err := iprot.ReadString(); err != nil {
return err
} else {
_field = v
}
p.Message = _field
return nil
}
func (p *PingResponse) ReadField255(iprot thrift.TProtocol) error {
_field := base.NewBaseResp()
if err := _field.Read(iprot); err != nil {
return err
}
p.Base = _field
return nil
}
func (p *PingResponse) Write(oprot thrift.TProtocol) (err error) {
var fieldId int16
if err = oprot.WriteStructBegin("PingResponse"); err != nil {
goto WriteStructBeginError
}
if p != nil {
if err = p.writeField1(oprot); err != nil {
fieldId = 1
goto WriteFieldError
}
if err = p.writeField2(oprot); err != nil {
fieldId = 2
goto WriteFieldError
}
if err = p.writeField255(oprot); err != nil {
fieldId = 255
goto WriteFieldError
}
}
if err = oprot.WriteFieldStop(); err != nil {
goto WriteFieldStopError
}
if err = oprot.WriteStructEnd(); err != nil {
goto WriteStructEndError
}
return nil
WriteStructBeginError:
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
WriteFieldError:
return thrift.PrependError(fmt.Sprintf("%T write field %d error: ", p, fieldId), err)
WriteFieldStopError:
return thrift.PrependError(fmt.Sprintf("%T write field stop error: ", p), err)
WriteStructEndError:
return thrift.PrependError(fmt.Sprintf("%T write struct end error: ", p), err)
}
func (p *PingResponse) writeField1(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("code", thrift.I32, 1); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteI32(p.Code); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 1 end error: ", p), err)
}
func (p *PingResponse) writeField2(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("message", thrift.STRING, 2); err != nil {
goto WriteFieldBeginError
}
if err := oprot.WriteString(p.Message); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 2 end error: ", p), err)
}
func (p *PingResponse) writeField255(oprot thrift.TProtocol) (err error) {
if err = oprot.WriteFieldBegin("base", thrift.STRUCT, 255); err != nil {
goto WriteFieldBeginError
}
if err := p.Base.Write(oprot); err != nil {
return err
}
if err = oprot.WriteFieldEnd(); err != nil {
goto WriteFieldEndError
}
return nil
WriteFieldBeginError:
return thrift.PrependError(fmt.Sprintf("%T write field 255 begin error: ", p), err)
WriteFieldEndError:
return thrift.PrependError(fmt.Sprintf("%T write field 255 end error: ", p), err)
}
func (p *PingResponse) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("PingResponse(%+v)", *p)
}

View File

@ -0,0 +1,27 @@
// Code generated by hertz generator. DO NOT EDIT.
package api_service
import (
api_service "gitea.micah.wiki/pandora/starter/biz/handler/api_service"
"github.com/cloudwego/hertz/pkg/app/server"
)
/*
This file will register all the routes of the services in the master idl.
And it will update automatically when you use the "update" command for the idl.
So don't modify the contents of the file, or your code will be deleted when it is updated.
*/
// Register register routes based on the IDL 'api.${HTTP Method}' annotation.
func Register(r *server.Hertz) {
root := r.Group("/", rootMw()...)
{
_openapi := root.Group("/openapi", _openapiMw()...)
{
_health := _openapi.Group("/health", _healthMw()...)
_health.GET("/ping", append(_pingMw(), api_service.Ping)...)
}
}
}

View File

@ -0,0 +1,27 @@
// Code generated by hertz generator.
package api_service
import (
"github.com/cloudwego/hertz/pkg/app"
)
func rootMw() []app.HandlerFunc {
// your code...
return nil
}
func _openapiMw() []app.HandlerFunc {
// your code...
return nil
}
func _healthMw() []app.HandlerFunc {
// your code...
return nil
}
func _pingMw() []app.HandlerFunc {
// your code...
return nil
}

14
biz/router/register.go Normal file
View File

@ -0,0 +1,14 @@
// Code generated by hertz generator. DO NOT EDIT.
package router
import (
api_service "gitea.micah.wiki/pandora/starter/biz/router/api_service"
"github.com/cloudwego/hertz/pkg/app/server"
)
// GeneratedRegister registers routers generated by IDL.
func GeneratedRegister(r *server.Hertz) {
//INSERT_POINT: DO NOT DELETE THIS LINE!
api_service.Register(r)
}

8
build.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/bash
RUN_NAME=hertz_service
mkdir -p output/bin
cp script/* output 2>/dev/null
mkdir -p output/conf
cp conf/* output/conf 2>/dev/null
chmod +x output/bootstrap.sh
go build -o output/bin/${RUN_NAME}

4
conf/conf.yml Normal file
View File

@ -0,0 +1,4 @@
server:
host: 127.0.0.1
port: 8888
env: local

4
conf/deploy_conf.yml Normal file
View File

@ -0,0 +1,4 @@
server:
host: 127.0.0.1
port: 8055
env: prod

42
go.mod Normal file
View File

@ -0,0 +1,42 @@
module gitea.micah.wiki/pandora/starter
go 1.24
replace github.com/apache/thrift => github.com/apache/thrift v0.13.0
require (
github.com/apache/thrift v0.22.0
github.com/bytedance/gopkg v0.1.3
github.com/cloudwego/hertz v0.10.3
github.com/go-resty/resty/v2 v2.17.1
github.com/oklog/ulid/v2 v2.1.1
go.uber.org/zap v1.27.1
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/bytedance/sonic v1.14.1 // indirect
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/cloudwego/gopkg v0.1.6 // indirect
github.com/cloudwego/netpoll v0.7.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/nyaruka/phonenumbers v1.0.56 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/tidwall/gjson v1.17.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/arch v0.14.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.28.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/protobuf v1.34.1 // indirect
)

146
go.sum Normal file
View File

@ -0,0 +1,146 @@
github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/bytedance/gopkg v0.1.1/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w=
github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc=
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
github.com/cloudwego/gopkg v0.1.4/go.mod h1:FQuXsRWRsSqJLsMVd5SYzp8/Z1y5gXKnVvRrWUOsCMI=
github.com/cloudwego/gopkg v0.1.6 h1:EMlOHg975CxKX1/BtIVYKGW8hxNptTkjjJ7bvfXu4L4=
github.com/cloudwego/gopkg v0.1.6/go.mod h1:FQuXsRWRsSqJLsMVd5SYzp8/Z1y5gXKnVvRrWUOsCMI=
github.com/cloudwego/hertz v0.10.3 h1:NFcQAjouVJsod79XPLC/PaFfHgjMTYbiErmW+vGBi8A=
github.com/cloudwego/hertz v0.10.3/go.mod h1:W5dUFXZPZkyfjMMo3EQrMQbofuvTsctM9IxmhbkuT18=
github.com/cloudwego/netpoll v0.7.2 h1:4qDBGQ6CG2SvEXhZSDxMdtqt/NLDxjAVk0PC/biKiJo=
github.com/cloudwego/netpoll v0.7.2/go.mod h1:PI+YrmyS7cIr0+SD4seJz3Eo3ckkXdu2ZVKBLhURLNU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-resty/resty/v2 v2.17.1 h1:x3aMpHK1YM9e4va/TMDRlusDDoZiQ+ViDu/WpA6xTM4=
github.com/go-resty/resty/v2 v2.17.1/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/nyaruka/phonenumbers v1.0.56 h1:WdOfLJMyhXibLTBHu1MIrPmZ5eylfGaXZ9vl9h9SB08=
github.com/nyaruka/phonenumbers v1.0.56/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U=
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.17.3 h1:bwWLZU7icoKRG+C+0PNwIKC6FCJO/Q3p2pZvuP0jN94=
github.com/tidwall/gjson v1.17.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4=
golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

7
idl/api_service.thrift Normal file
View File

@ -0,0 +1,7 @@
include "base.thrift"
include "health/health.thrift"
namespace go api_service
service HealthService {
health.PingResponse Ping(1: health.PingRequest req)(api.get='/openapi/health/ping', api.serializer='json', api.category='健康检查')
}(api.service_path="health")

23
idl/base.thrift Normal file
View File

@ -0,0 +1,23 @@
namespace py base
namespace go base
namespace rs base
namespace java com.bytedance.thrift.base
struct TrafficEnv {
1: bool open = false,
2: string env = "",
}
struct Base {
1: string log_id = "",
2: string caller = "",
3: string addr = "",
4: string client = "",
5: optional TrafficEnv traffic_env,
6: optional map<string, string> extra,
}
struct BaseResp {
1: string status_message = "",
2: i32 status_code = 0,
3: optional map<string, string> extra,
}

11
idl/health/health.thrift Normal file
View File

@ -0,0 +1,11 @@
include "../base.thrift"
namespace go health
struct PingRequest{
255: base.Base base
}
struct PingResponse{
1: required i32 code
2: required string message
255: base.BaseResp base
}

37
main.go Normal file
View File

@ -0,0 +1,37 @@
// Code generated by hertz generator.
package main
import (
"fmt"
"os"
"github.com/cloudwego/hertz/pkg/app/server"
"gitea.micah.wiki/pandora/starter/app/config"
"gitea.micah.wiki/pandora/starter/app/initialize"
"gitea.micah.wiki/pandora/starter/biz/middleware"
)
func main() {
var args []string
if len(os.Args) > 1 {
args = os.Args[1:]
}
initialize.Init(args)
defer func() {
initialize.Close()
}()
var h *server.Hertz
conf := config.GetConfig()
if len(conf.Server.Host) > 0 && conf.Server.Port > 0 {
listenAddr := fmt.Sprintf("%s:%d", conf.Server.Host, conf.Server.Port)
h = server.New(server.WithHostPorts(listenAddr))
} else {
h = server.Default()
}
h.Use(middleware.RequestIDMiddleware(), middleware.CorsMiddleware(), middleware.LogMiddleware())
register(h)
h.Spin()
}

10
pkg/env/environment.go vendored Normal file
View File

@ -0,0 +1,10 @@
package env
import "gitea.micah.wiki/pandora/starter/app/config"
func IsProd() bool {
return config.GetConfig().Server.Env == "prod"
}
func IsLocal() bool {
return config.GetConfig().Server.Env == "local"
}

71
pkg/env/system.go vendored Normal file
View File

@ -0,0 +1,71 @@
package env
import (
"runtime"
"strconv"
"syscall"
)
// IsWindows 判断当前系统是否是 Windows
func IsWindows() bool {
return runtime.GOOS == "windows"
}
// IsLinux 判断当前系统是否是 Linux
func IsLinux() bool {
return runtime.GOOS == "linux"
}
// IsMacOS 判断当前系统是否是 macOS
func IsMacOS() bool {
return runtime.GOOS == "darwin"
}
// IsMacIntel 判断当前 macOS 系统是否是 Intel 架构x86_64
// 非 macOS 系统返回 false
func IsMacIntel() bool {
if !IsMacOS() {
return false
}
// 先通过 GOARCH 快速判断,兼容绝大多数场景
if runtime.GOARCH == "amd64" {
// 验证硬件是否真的是 Intel避免 Rosetta 兼容模式误判)
return !isAppleSiliconHardware()
}
return false
}
// IsMacArm 判断当前 macOS 系统是否是 ARM 架构Apple Silicon/M1/M2/M3
// 非 macOS 系统返回 false
func IsMacArm() bool {
if !IsMacOS() {
return false
}
// 场景1原生 ARM 编译运行GOARCH=arm64
if runtime.GOARCH == "arm64" {
return true
}
// 场景2Intel 编译但运行在 ARM macOS 的 Rosetta 兼容模式下
if runtime.GOARCH == "amd64" {
return isAppleSiliconHardware()
}
return false
}
// isAppleSiliconHardware 底层方法:判断 macOS 硬件是否是 Apple SiliconARM
// 仅在 macOS 下调用有效,返回 true 表示 ARM 硬件false 表示 Intel 硬件
func isAppleSiliconHardware() bool {
val, err := syscall.Sysctl("hw.optional.arm64")
if err != nil {
return false
}
num, err := strconv.Atoi(val)
if err != nil {
return false
}
return num == 1
}

43
pkg/jsonx/json.go Normal file
View File

@ -0,0 +1,43 @@
package jsonx
import (
"context"
"encoding/json"
"gitea.micah.wiki/pandora/starter/pkg/logx"
)
var (
Marshal = json.Marshal
Unmarshal = json.Unmarshal
)
func UnsafeMarshal(ctx context.Context, v any) string {
b, err := Marshal(v)
if err != nil {
logx.CtxError(ctx, "Json UnsafeMarshal error, value: %+v, err: %+v.", v, err)
return ""
}
return string(b)
}
func UnsafeUnmarshal(ctx context.Context, data string, v any) {
err := Unmarshal([]byte(data), v)
if err != nil {
logx.CtxError(ctx, "Json UnsafeUnmarshal error, data: %s, err: %+v.", data, err)
return
}
}
func ConvertMarshal(ctx context.Context, from any, to any) {
b, err := Marshal(from)
if err != nil {
logx.CtxError(ctx, "Json ConvertMarshal error, from: %+v, err: %+v.", from, err)
return
}
err = json.Unmarshal(b, to)
if err != nil {
logx.CtxError(ctx, "Json ConvertMarshal error, from: %+v, err: %+v.", from, err)
return
}
}

111
pkg/logx/log.go Normal file
View File

@ -0,0 +1,111 @@
package logx
import (
"context"
"fmt"
"sync"
"gitea.micah.wiki/pandora/starter/app/config"
"gitea.micah.wiki/pandora/starter/pkg/env"
"gitea.micah.wiki/pandora/starter/pkg/requestid"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
)
var (
logger *zap.Logger
once sync.Once
)
func Init() {
_ = _getLogger()
}
func _getLogger() *zap.Logger {
if logger == nil {
once.Do(func() {
logFile := config.GetConfig().LogFile
encoderConfig := zapcore.EncoderConfig{
TimeKey: "time",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
// 自定义控制台输出的字段顺序仅对ConsoleEncoder生效
ConsoleSeparator: " ", // 字段之间的分隔符
}
var writer zapcore.WriteSyncer
var encoder zapcore.Encoder
writer = zapcore.AddSync(&lumberjack.Logger{
Filename: logFile,
MaxSize: 10, // megabytes
MaxBackups: 30,
MaxAge: 7, // days
Compress: true,
})
if env.IsLocal() {
encoder = zapcore.NewConsoleEncoder(encoderConfig)
} else {
// 其他系统保持 JSON 编码器
encoder = zapcore.NewJSONEncoder(encoderConfig)
}
core := zapcore.NewCore(
encoder,
writer,
zap.DebugLevel,
)
logger = zap.New(core)
})
}
return logger
}
func Close() {
if logger != nil {
_ = logger.Sync()
}
}
// 统一封装日志方法根据编码器类型处理logid
func logWithCtx(ctx context.Context, level zapcore.Level, template string, args ...interface{}) {
logid := requestid.GetLogID(ctx)
msg := fmt.Sprintf(template, args...)
// 根据编码器类型决定 logid 的展示方式
if env.IsMacOS() {
// macOS控制台模式将logid嵌入到消息中保证文本可读性
msg = fmt.Sprintf("%s %s", logid, msg)
_getLogger().Log(level, msg)
} else {
// 其他系统JSON模式使用zap字段保证JSON结构清晰
_getLogger().With(zap.String("logid", logid)).Log(level, msg)
}
}
// CtxInfo 带上下文的Info级别日志
func CtxInfo(ctx context.Context, template string, args ...interface{}) {
logWithCtx(ctx, zapcore.InfoLevel, template, args...)
}
// CtxError 带上下文的Error级别日志
func CtxError(ctx context.Context, template string, args ...interface{}) {
logWithCtx(ctx, zapcore.ErrorLevel, template, args...)
}
// CtxWarn 带上下文的Warn级别日志
func CtxWarn(ctx context.Context, template string, args ...interface{}) {
logWithCtx(ctx, zapcore.WarnLevel, template, args...)
}
// CtxDebug 带上下文的Debug级别日志
func CtxDebug(ctx context.Context, template string, args ...interface{}) {
logWithCtx(ctx, zapcore.DebugLevel, template, args...)
}

110
pkg/logx/log_test.go Normal file
View File

@ -0,0 +1,110 @@
package logx
import (
"context"
"testing"
)
func TestCtxError(t *testing.T) {
type args struct {
ctx context.Context
template string
args []interface{}
}
tests := []struct {
name string
args args
}{
{
name: "",
args: args{
ctx: context.Background(),
template: "你好",
args: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
CtxError(tt.args.ctx, tt.args.template, tt.args.args...)
})
}
}
func TestCtxWarn(t *testing.T) {
type args struct {
ctx context.Context
template string
args []interface{}
}
tests := []struct {
name string
args args
}{
{
name: "",
args: args{
ctx: context.Background(),
template: "你好 Warn",
args: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
CtxWarn(tt.args.ctx, tt.args.template, tt.args.args...)
})
}
}
func TestCtxDebug(t *testing.T) {
type args struct {
ctx context.Context
template string
args []interface{}
}
tests := []struct {
name string
args args
}{
{
name: "",
args: args{
ctx: context.Background(),
template: "你好 Debug",
args: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
CtxDebug(tt.args.ctx, tt.args.template, tt.args.args...)
})
}
}
func TestCtxInfo(t *testing.T) {
type args struct {
ctx context.Context
template string
args []interface{}
}
tests := []struct {
name string
args args
}{
{
name: "",
args: args{
ctx: context.Background(),
template: "你好呀",
args: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
CtxInfo(tt.args.ctx, tt.args.template, tt.args.args...)
})
}
}

View File

@ -0,0 +1,27 @@
package requestid
import (
"context"
"github.com/bytedance/gopkg/cloud/metainfo"
)
const (
KLogIDKey = "X_LOGID"
)
func SaveLogID(ctx context.Context, requestID string) context.Context {
ctx = metainfo.WithValue(ctx, KLogIDKey, requestID)
return ctx
}
func GetLogID(ctx context.Context) string {
v, ok := metainfo.GetValue(ctx, KLogIDKey)
if !ok {
return "-"
}
if v == "" {
return "-"
}
return v
}

29
pkg/restyx/basic.go Normal file
View File

@ -0,0 +1,29 @@
package restyx
import (
"bufio"
"context"
)
type Basic struct {
LogID string `json:"log_id"`
}
func (b *Basic) SetLogID(logID string) {
b.LogID = logID
}
type SpecialResponse struct {
Headers string `json:"header"`
Data string `json:"data"`
}
func (r *SpecialResponse) SetData(data string) {
r.Data = data
}
func (r *SpecialResponse) SetHeaders(headers string) {
r.Headers = headers
}
type StreamFunc func(ctx context.Context, scanner *bufio.Scanner) (interface{}, error)

315
pkg/restyx/resty.go Normal file
View File

@ -0,0 +1,315 @@
// Package restyx this is http client wrapper.
package restyx
import (
"bufio"
"context"
"encoding/json"
"fmt"
"reflect"
"runtime"
"time"
"gitea.micah.wiki/pandora/starter/pkg/jsonx"
"gitea.micah.wiki/pandora/starter/pkg/logx"
"gitea.micah.wiki/pandora/starter/pkg/requestid"
"github.com/go-resty/resty/v2"
)
var (
headerKeys []string
)
const (
HeaderJWTTokenKey = "X-Jwt-Token"
HeaderLogIDKey = requestid.KLogIDKey
// PrintLogTypeDefault = 0
PrintLogTypeForce = 1
PrintLogTypeDisable = 2
MaxPrintLogLength = 100000
maxCapacity = 10 * 1024 * 1024
initCapacity = 1024 * 1024
)
func init() {
headerKeys = make([]string, 0)
headerKeys = append(headerKeys, HeaderJWTTokenKey)
}
type Auth struct {
User string
Token string
}
func (a *Auth) String() string {
if a == nil {
return "Auto: {nil}"
}
return fmt.Sprintf("Auth{User: %s, Token: %s}", a.User, a.Token)
}
type Request struct {
Auth *Auth
URL string
Body interface{}
FormData map[string]string
QueryData map[string]string
Header map[string]string
PathParam map[string]string
Timeout int
PrintLogType int // 相见头部var定义 0: 默认; 1: 打印2: 不打印;
}
func (r *Request) String() string {
if r == nil {
return "Request: {nil}"
}
return fmt.Sprintf("Request: {Auth: %s, URL: %s, Body: %+v, FormData: %+v, QueryData: %+v, Header: %+v, PathParm: %+v, Timeout: %d, PrintLogType: %d}",
r.Auth, r.URL, r.Body, r.FormData, r.QueryData, r.Header, r.PathParam, r.Timeout, r.PrintLogType)
}
type Response struct {
LogID string
Header map[string]string
TargetPoint interface{}
}
func (r *Response) String() string {
if r == nil {
return "Response: {nil}"
}
return fmt.Sprintf("Response: {LogID: %s, Header: %+v, TargetPoint: %+v}", r.LogID, r.Header, r.TargetPoint)
}
type StreamResponse struct {
LogID string
Header map[string]string
Target interface{}
}
func PostStream(ctx context.Context, req *Request, streamFunc StreamFunc) (*StreamResponse, error) {
return DoStream(ctx, resty.MethodPost, req, streamFunc)
}
func DoStream(ctx context.Context, method string, req *Request, streamFunc StreamFunc) (*StreamResponse, error) {
start := time.Now()
request := getClient(ctx, req)
request = request.SetDoNotParseResponse(true)
var (
resp *resty.Response
err error
)
switch method {
case resty.MethodGet:
resp, err = request.Get(req.URL)
case resty.MethodPost:
resp, err = request.Post(req.URL)
case resty.MethodHead:
resp, err = request.Head(req.URL)
case resty.MethodDelete:
resp, err = request.Delete(req.URL)
default:
resp, err = request.Get(req.URL)
}
if err != nil {
return nil, err
}
if !resp.IsSuccess() {
logx.CtxError(ctx, "HttpResty Resp IsFail. req: %+v, respCode: %d, respStatus: %s, resp: %+v, cost: %+v.", req, resp.StatusCode(), resp.Status(), resp, time.Since(start))
return nil, err
}
defer func() {
_ = resp.RawResponse.Body.Close() // 记得关闭流,防止资源泄露
}()
scanner := bufio.NewScanner(resp.RawResponse.Body)
buf := make([]byte, initCapacity) // 初始缓冲区1MB
scanner.Buffer(buf, maxCapacity) // 设置最大缓冲区大小,比如 10MB
data, err := streamFunc(ctx, scanner)
if err != nil {
logx.CtxError(ctx, "HttpResty Resp streamFunc error. req: %+v, cost: %+v, err: %+v.", req, time.Since(start), err)
return nil, err
}
if err = scanner.Err(); err != nil {
logx.CtxError(ctx, "HttpResty Resp scanner error. req: %+v, respCode: %d, respStatus: %s, cost: %+v, err: %+v.", req, resp.StatusCode(), resp.Status(), time.Since(start), err)
return nil, err
}
return &StreamResponse{
LogID: resp.Header().Get(HeaderLogIDKey),
Target: data,
}, nil
}
func Post(ctx context.Context, req *Request, targetPoint interface{}) error {
return Do(ctx, resty.MethodPost, req, targetPoint)
}
func Get(ctx context.Context, req *Request, targetPoint interface{}) error {
return Do(ctx, resty.MethodGet, req, targetPoint)
}
func Do(ctx context.Context, method string, req *Request, targetPoint interface{}) error {
restyResp, err := doRemote(ctx, method, req)
response := fillResponse(restyResp)
if err != nil {
return err
}
if targetPoint != nil {
if _, ok := targetPoint.(*SpecialResponse); ok {
v := reflect.ValueOf(targetPoint)
setDataMethod := v.MethodByName("SetData")
if setDataMethod.IsValid() {
args := []reflect.Value{reflect.ValueOf(string(restyResp.Body()))}
setDataMethod.Call(args)
}
setHeadersMethod := v.MethodByName("SetHeaders")
if setHeadersMethod.IsValid() {
args := []reflect.Value{reflect.ValueOf(jsonx.UnsafeMarshal(ctx, response.Header))}
setHeadersMethod.Call(args)
}
return nil
}
err = json.Unmarshal(restyResp.Body(), targetPoint)
if err != nil {
logx.CtxInfo(ctx, "HttpResty Resp Unmarshal Error. req: %+v, targetType: %+v, restyResp: %+v, err: %+v.", req, reflect.TypeOf(targetPoint), string(restyResp.Body()), err)
return err
}
fillTargetBase(ctx, response, targetPoint)
}
return nil
}
func getClient(ctx context.Context, req *Request) *resty.Request {
cli := resty.New()
if req.Timeout > 0 {
cli = cli.SetTimeout(time.Second * time.Duration(req.Timeout))
}
request := cli.R().SetContext(ctx)
if req.Auth != nil && len(req.Auth.User) > 0 && len(req.Auth.Token) > 0 {
request = request.SetBasicAuth(req.Auth.User, req.Auth.Token)
}
headers := getHeaders(ctx, req.Header)
if len(headers) > 0 {
request = request.SetHeaders(headers)
}
if len(req.PathParam) > 0 {
request = request.SetPathParams(req.PathParam)
}
if req.Body != nil {
request = request.SetBody(req.Body)
}
if req.FormData != nil {
request = request.SetFormData(req.FormData)
}
if len(req.QueryData) > 0 {
request = request.SetQueryParams(req.QueryData)
}
return request
}
func doRemote(ctx context.Context, method string, req *Request) (*resty.Response, error) {
start := time.Now()
if req.PrintLogType != PrintLogTypeDisable {
logx.CtxInfo(ctx, "HttpResty start. req: %+v", req)
}
request := getClient(ctx, req)
var (
resp *resty.Response
err error
)
switch method {
case resty.MethodGet:
resp, err = request.Get(req.URL)
case resty.MethodPost:
resp, err = request.Post(req.URL)
case resty.MethodHead:
resp, err = request.Head(req.URL)
case resty.MethodDelete:
resp, err = request.Delete(req.URL)
default:
resp, err = request.Get(req.URL)
}
if err != nil {
logx.CtxError(ctx, "HttpResty Handler Error. req: %+v, err: %+v, cost: %+v.", req, err, time.Since(start))
return nil, err
}
if !resp.IsSuccess() {
logx.CtxError(ctx, "HttpResty Resp IsFail. req: %+v, respCode: %d, respStatus: %s, resp: %+v, cost: %+v.", req, resp.StatusCode(), resp.Status(), resp, time.Since(start))
return resp, err
}
// 如果这里返回结构中过多,不进行日志打印。
if req.PrintLogType != PrintLogTypeDisable {
if req.PrintLogType == PrintLogTypeForce || len(resp.Body()) < MaxPrintLogLength {
logx.CtxInfo(ctx, "HttpResty finish. req: %+v, resp: %+v, cost: %+v.", req, resp, time.Since(start))
} else {
logx.CtxInfo(ctx, "HttpResty finish. req: %+v, resp: too many resp(not print to log), cost: %+v.", req, time.Since(start))
}
}
return resp, nil
}
func fillResponse(resp *resty.Response) *Response {
response := &Response{}
if resp == nil {
return response
}
response.LogID = resp.Header().Get(HeaderLogIDKey)
response.Header = make(map[string]string)
if token := resp.Header().Get(HeaderJWTTokenKey); len(token) > 0 {
response.Header[HeaderJWTTokenKey] = token
}
return response
}
func fillTargetBase(ctx context.Context, response *Response, target interface{}) {
defer func() {
if err := recover(); err != nil {
buf := make([]byte, 1<<16)
runtime.Stack(buf, false)
logx.CtxError(ctx, "HttpResty fillTargetBase panic, response: %+v, err:%+v,\n%s", response, err, buf)
}
}()
if target == nil {
return
}
t := reflect.TypeOf(target)
switch t.Kind() {
case reflect.Ptr:
v := reflect.ValueOf(target)
m := v.MethodByName("SetLogID")
if m.IsValid() {
args := []reflect.Value{reflect.ValueOf(response.LogID)}
m.Call(args)
}
case reflect.Struct:
b, ok := target.(Basic)
if !ok {
return
}
b.LogID = response.LogID
default:
}
}
func getHeaders(ctx context.Context, headers map[string]string) map[string]string {
newHeaders := make(map[string]string)
for key, value := range headers {
newHeaders[key] = value
}
logID := requestid.GetLogID(ctx)
if len(logID) > 0 {
newHeaders[HeaderLogIDKey] = logID
}
return newHeaders
}

16
pkg/uniqueid/unique.go Normal file
View File

@ -0,0 +1,16 @@
package uniqueid
import (
"strings"
"time"
"github.com/oklog/ulid/v2"
)
func GetUniqueID() string {
datePart := time.Now().Format("20060102150405")
machineInfoPart := strings.ToLower(ulid.Make().String())
return datePart + "L" + machineInfoPart
}

15
router.go Normal file
View File

@ -0,0 +1,15 @@
// Code generated by hertz generator.
package main
import (
handler "gitea.micah.wiki/pandora/starter/biz/handler"
"github.com/cloudwego/hertz/pkg/app/server"
)
// customizeRegister registers customize routers.
func customizedRegister(r *server.Hertz) {
r.GET("/ping", handler.Ping)
// your code ...
}

16
router_gen.go Normal file
View File

@ -0,0 +1,16 @@
// Code generated by hertz generator. DO NOT EDIT.
package main
import (
router "gitea.micah.wiki/pandora/starter/biz/router"
"github.com/cloudwego/hertz/pkg/app/server"
)
// register registers all routers.
func register(r *server.Hertz) {
router.GeneratedRegister(r)
customizedRegister(r)
}

5
script/bootstrap.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
CURDIR=$(cd $(dirname $0); pwd)
BinaryName=hertz_service
echo "$CURDIR/bin/${BinaryName}"
exec $CURDIR/bin/${BinaryName} $@