This commit is contained in:
新亮
2021-01-31 14:51:41 +08:00
parent 106d5b65d7
commit 4ed8b81c57
32 changed files with 3255 additions and 81 deletions
+6 -4
View File
@@ -35,13 +35,15 @@
```cassandraql
├── main.go # 项目入口文件
├── configs # 配置文件统一存放目录
├── docs # Swagger 文档,执行 swag init 生成的
├── init # 项目初始脚本,比如初始化 SQL 语句
├── docs # Swagger 文档
├── init # 项目初始配置,比如初始化 SQL 语句
├── internal # 业务目录
│ ├── api # 业务代码
│ ├── graph # GraphQL 代码
│ ├── pkg # 内部使用的 package
├── logs # 存放日志目录
── pkg # 一些封装好的 package
├── logs # 日志目录
── pkg # 外部使用的 package
└── scripts # 操作脚本
```
## Features
-1
View File
@@ -68,7 +68,6 @@ func init() {
viper.SetConfigName(env.Active().Value() + "_configs")
viper.SetConfigType("toml")
viper.AddConfigPath("./configs")
viper.AddConfigPath("../../configs") // 兼容 cmd/cron/main.go 引用配置文件
if err := viper.ReadInConfig(); err != nil {
panic(err)
+2 -2
View File
@@ -351,11 +351,11 @@ type swaggerInfo struct {
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = swaggerInfo{
Version: "",
Version: "2.0",
Host: "127.0.0.1:9999",
BasePath: "",
Schemes: []string{},
Title: "go-gin-api docs api",
Title: "swagger 接口文档",
Description: "",
}
+3 -2
View File
@@ -1,12 +1,13 @@
{
"swagger": "2.0",
"info": {
"title": "go-gin-api docs api",
"title": "swagger 接口文档",
"contact": {},
"license": {
"name": "MIT",
"url": "https://github.com/xinliangnote/go-gin-api/blob/master/LICENSE"
}
},
"version": "2.0"
},
"host": "127.0.0.1:9999",
"paths": {
+2 -1
View File
@@ -62,7 +62,8 @@ info:
license:
name: MIT
url: https://github.com/xinliangnote/go-gin-api/blob/master/LICENSE
title: go-gin-api docs api
title: swagger 接口文档
version: "2.0"
paths:
/auth/get:
post:
+2
View File
@@ -3,6 +3,7 @@ module github.com/xinliangnote/go-gin-api
go 1.15
require (
github.com/99designs/gqlgen v0.13.0
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gin-contrib/pprof v1.2.1
@@ -19,6 +20,7 @@ require (
github.com/spf13/viper v1.7.1
github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.0
github.com/vektah/gqlparser/v2 v2.1.0
go.uber.org/multierr v1.5.0
go.uber.org/zap v1.16.0
golang.org/x/mod v0.4.0 // indirect
+40
View File
@@ -11,6 +11,8 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/99designs/gqlgen v0.13.0 h1:haLTcUp3Vwp80xMVEg5KRNwzfUrgFdRmtBY8fuB8scA=
github.com/99designs/gqlgen v0.13.0/go.mod h1:NV130r6f4tpRWuAI+zsrSdooO/eWUv+Gyyoi3rEfXIk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@@ -22,10 +24,17 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=
github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
@@ -51,11 +60,14 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c h1:TUuUh0Xgj97tLMNtWtNvI9mIV6isjEb9lBMNv+77IGM=
github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.1 h1:ezvKOL6jH+jlzdHNE4h9h8q8uMpDQjyl0NN0Jd7jozc=
github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w=
@@ -69,6 +81,7 @@ github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@@ -104,6 +117,7 @@ github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRf
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -140,6 +154,9 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
@@ -158,6 +175,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@@ -194,6 +212,7 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -201,7 +220,9 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -217,6 +238,7 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -240,6 +262,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U=
github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@@ -265,14 +289,19 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -292,6 +321,7 @@ github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -316,8 +346,12 @@ github.com/ugorji/go/codec v1.1.13 h1:013LbFhocBoIqgHeIHKlV4JWYhqogATYWZhIcH0WHn
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
github.com/vektah/gqlparser/v2 v2.1.0 h1:uiKJ+T5HMGGQM2kRKQ8Pxw8+Zq9qhhZhz/lieYvCMns=
github.com/vektah/gqlparser/v2 v2.1.0/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -361,6 +395,7 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -440,6 +475,7 @@ golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -447,6 +483,7 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
@@ -459,6 +496,7 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201226215659-b1c90890d22a h1:pdfjQ7VswBeGam3EpuEJ4e8EAb7JgaubV570LO/SIQM=
golang.org/x/tools v0.0.0-20201226215659-b1c90890d22a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -540,3 +578,5 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
+56
View File
@@ -0,0 +1,56 @@
# Where are all the schema files located? globs are supported eg src/**/*.graphqls
schema:
- internal/graph/schemas/*.graphql
# Where should the generated server code go?
exec:
filename: internal/graph/generated/generated.go
package: generated
# Uncomment to enable federation
# federation:
# filename: graph/generated/federation.go
# package: generated
# Where should any generated models go?
model:
filename: internal/graph/model/generated.go
package: model
# Where should the resolver implementations go?
resolver:
filename: internal/graph/resolvers/generated/generated.go
type: Resolver
package: resolvers
# Optional: turn on use `gqlgen:"fieldName"` tags in your models
# struct_tag: json
# Optional: turn on to use []Thing instead of []*Thing
# omit_slice_element_pointers: false
# Optional: set to speed up generation time by not performing a final validation pass.
# skip_validation: true
# gqlgen will search for any type names in the schema in these go packages
# if they match it will use them, otherwise it will generate them.
autobind:
- "github.com/xinliangnote/go-gin-api/internal/graph/model"
# This section declares type mapping between the GraphQL and go type systems
#
# The first line in each type will be used as defaults for resolver arguments and
# modelgen, the others will be allowed when binding to fields. Configure them to
# your liking
models:
ID:
model:
- github.com/99designs/gqlgen/graphql.ID
- github.com/99designs/gqlgen/graphql.Int
- github.com/99designs/gqlgen/graphql.Int64
- github.com/99designs/gqlgen/graphql.Int32
Int:
model:
- github.com/99designs/gqlgen/graphql.Int
- github.com/99designs/gqlgen/graphql.Int64
- github.com/99designs/gqlgen/graphql.Int32
+4 -1
View File
@@ -171,7 +171,10 @@ func (d *Demo) Trace() core.HandlerFunc {
}
// 调试信息
p.Println("res2.Data.Name", res2.Data.Name, p.WithTrace(c.Trace()))
p.Println("res2.Data.Name",
res2.Data.Name,
p.WithTrace(c.Trace()),
)
// 执行 SQL 信息
d.userService.GetUserByUserName(c, "test_user")
@@ -6,6 +6,7 @@ import (
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"github.com/pkg/errors"
"gorm.io/gorm"
)
var _ UserRepo = (*userRepo)(nil)
@@ -42,8 +43,9 @@ func (u *userRepo) Create(ctx core.Context, user user_model.UserDemo) (id uint,
func (u *userRepo) getUserByID(ctx core.Context, id uint) (*user_model.UserDemo, error) {
data := new(user_model.UserDemo)
err := u.db.GetDbR().WithContext(ctx.RequestContext()).First(data, id).Where("is_deleted = ?", -1).Error
if err != nil {
err := u.db.GetDbR().
WithContext(ctx.RequestContext()).First(data, id).Where("is_deleted = ?", -1).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil, errors.Wrap(err, "[user_demo] get user data err")
}
return data, nil
@@ -52,7 +54,7 @@ func (u *userRepo) getUserByID(ctx core.Context, id uint) (*user_model.UserDemo,
func (u *userRepo) UpdateNickNameByID(ctx core.Context, id uint, nickname string) (err error) {
user, err := u.getUserByID(ctx, id)
if err != nil {
return errors.Wrap(err, "[user_demo] update user data err")
return errors.Wrap(err, "[user_demo] get user data err")
}
return u.db.GetDbW().WithContext(ctx.RequestContext()).Model(user).Update("nick_name", nickname).Error
}
@@ -60,7 +62,7 @@ func (u *userRepo) UpdateNickNameByID(ctx core.Context, id uint, nickname string
func (u *userRepo) Delete(ctx core.Context, id uint) (err error) {
user, err := u.getUserByID(ctx, id)
if err != nil {
return errors.Wrap(err, "[user_demo] update user data err")
return errors.Wrap(err, "[user_demo] get user data err")
}
return u.db.GetDbW().WithContext(ctx.RequestContext()).Model(user).Update("is_deleted", 1).Error
}
@@ -72,7 +74,7 @@ func (u *userRepo) GetUserByUserName(ctx core.Context, username string) (*user_m
Select([]string{"id", "user_name", "nick_name", "mobile"}).
Where("user_name = ? and is_deleted = ?", username, -1).
First(data).Error
if err != nil {
if err != nil && err != gorm.ErrRecordNotFound {
return nil, errors.Wrap(err, "[user_demo] get user data err")
}
return data, nil
+8
View File
@@ -4,6 +4,7 @@ import (
"github.com/xinliangnote/go-gin-api/internal/api/controller/demo"
"github.com/xinliangnote/go-gin-api/internal/api/controller/user_handler"
"github.com/xinliangnote/go-gin-api/internal/api/router/middleware/auth"
"github.com/xinliangnote/go-gin-api/internal/graph/handler"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
@@ -33,6 +34,13 @@ func NewHTTPMux(logger *zap.Logger, db db.Repo, cache cache.Repo) (core.Mux, err
demoHandler := demo.NewDemo(logger, db, cache)
userHandler := user_handler.NewUserDemo(logger, db, cache)
gqlHandler := handler.New(logger, db, cache)
gql := mux.Group("/graphql")
{
gql.GET("", gqlHandler.Playground())
gql.POST("/query", gqlHandler.Query())
}
// user_demo CURD
user := mux.Group("/user", core.WrapAuthHandler(auth.AuthHandler))
+24
View File
@@ -0,0 +1,24 @@
## example
```cassandraql
1.
query {
bySex(sex: "男") {
id
name
sex
mobile
}
}
2.
mutation {
updateUserMobile(data: {id: "1", mobile: "13299999999"}) {
id
name
sex
mobile
}
}
```
File diff suppressed because it is too large Load Diff
+102
View File
@@ -0,0 +1,102 @@
package handler
import (
"context"
"time"
"github.com/xinliangnote/go-gin-api/internal/graph/generated"
"github.com/xinliangnote/go-gin-api/internal/graph/resolvers"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/lru"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/99designs/gqlgen/graphql/playground"
"go.uber.org/zap"
)
var _ Gql = (*gql)(nil)
type Gql interface {
i()
Playground() core.HandlerFunc
Query() core.HandlerFunc
}
type gql struct {
logger *zap.Logger
db db.Repo
cache cache.Repo
}
func New(logger *zap.Logger, db db.Repo, cache cache.Repo) Gql {
return &gql{
logger: logger,
cache: cache,
db: db,
}
}
func (g *gql) i() {}
func (g *gql) Query() core.HandlerFunc {
// 定义扩展字段
extensions := make(map[string]interface{})
h := handler.New(generated.NewExecutableSchema(
resolvers.NewRootResolvers(g.logger, g.db, g.cache)),
)
h.AddTransport(transport.Websocket{
KeepAlivePingInterval: 10 * time.Second,
})
// 设置 transport
h.AddTransport(transport.Options{})
h.AddTransport(transport.GET{})
h.AddTransport(transport.POST{})
h.SetQueryCache(lru.New(1000))
// 启用侧边栏文档
h.Use(extension.Introspection{})
h.Use(extension.AutomaticPersistedQuery{
Cache: lru.New(100),
})
return func(c core.Context) {
var responses interface{}
defer func() {
// 设置 core log
c.GraphPayload(responses)
}()
// 设置 core trace_id
extensions["trace_id"] = c.Trace().ID()
h.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
resp := next(ctx)
resp.Extensions = extensions
responses = resp
return resp
})
// 设置 core context
coreContext := context.WithValue(c.Request().Context(), resolvers.CoreContextKey, c)
h.ServeHTTP(c.ResponseWriter(), c.Request().WithContext(coreContext))
}
}
func (g *gql) Playground() core.HandlerFunc {
h := playground.Handler("GraphQL", "/graphql/query")
return func(c core.Context) {
h.ServeHTTP(c.ResponseWriter(), c.Request())
}
}
+15
View File
@@ -0,0 +1,15 @@
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
package model
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Sex string `json:"sex"`
Mobile string `json:"mobile"`
}
type UpdateUserMobileInput struct {
ID string `json:"id"`
Mobile string `json:"mobile"`
}
@@ -0,0 +1,29 @@
package resolvers
// THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.
import (
"context"
"github.com/xinliangnote/go-gin-api/internal/graph/generated"
"github.com/xinliangnote/go-gin-api/internal/graph/model"
)
type Resolver struct{}
func (r *mutationResolver) UpdateUserMobile(ctx context.Context, data model.UpdateUserMobileInput) (*model.User, error) {
panic("not implemented")
}
func (r *queryResolver) BySex(ctx context.Context, sex string) ([]*model.User, error) {
panic("not implemented")
}
// Mutation returns generated.MutationResolver implementation.
func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }
// Query returns generated.QueryResolver implementation.
func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
type mutationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
+51
View File
@@ -0,0 +1,51 @@
package resolvers
import (
"context"
"github.com/xinliangnote/go-gin-api/internal/api/service/user_service"
"github.com/xinliangnote/go-gin-api/internal/graph/generated"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"go.uber.org/zap"
)
type coreCtxKeyType struct{ name string }
var CoreContextKey = coreCtxKeyType{"_core_context"}
type mutationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
type Resolver struct {
logger *zap.Logger
cache cache.Repo
userService user_service.UserService
}
func NewRootResolvers(logger *zap.Logger, db db.Repo, cache cache.Repo) generated.Config {
c := generated.Config{
Resolvers: &Resolver{
logger: logger,
cache: cache,
userService: user_service.NewUserService(db, cache),
},
}
return c
}
func (r *Resolver) Mutation() generated.MutationResolver {
return &mutationResolver{r}
}
func (r *Resolver) Query() generated.QueryResolver {
return &queryResolver{r}
}
// getCoreContextByCtx 获取 core context
func (r *Resolver) getCoreContextByCtx(ctx context.Context) core.Context {
return ctx.Value(CoreContextKey).(core.Context)
}
+47
View File
@@ -0,0 +1,47 @@
package resolvers
import (
"context"
"github.com/xinliangnote/go-gin-api/internal/graph/model"
"github.com/pkg/errors"
)
func (r *queryResolver) BySex(ctx context.Context, sex string) ([]*model.User, error) {
if sex == "" {
return nil, errors.New("sex required")
}
//模拟数据
var users []*model.User
users = append(users, &model.User{ID: "1", Name: "Tom", Sex: sex, Mobile: "13266666666"})
users = append(users, &model.User{ID: "1", Name: "Jack", Sex: sex, Mobile: "13288888888"})
return users, nil
}
func (r *mutationResolver) UpdateUserMobile(ctx context.Context, data model.UpdateUserMobileInput) (*model.User, error) {
if data.ID == "" {
return nil, errors.New("id required")
}
if data.Mobile == "" {
return nil, errors.New("mobile required")
}
//模拟数据
user := new(model.User)
user.ID = data.ID
user.Mobile = data.Mobile
user.Sex = "男"
user.Name = "Jack"
//操作数据库
//userData, err := r.userService.GetUserByUserName(r.getCoreContextByCtx(ctx), "test_user")
//if err != nil {
// return nil, err
//}
return user, nil
}
+22
View File
@@ -0,0 +1,22 @@
type User {
id: String!
name: String!
sex: String!
mobile: String!
}
# 查询 集合
type Query {
bySex(sex: String!): [User!]
}
# 输入类型: 一般用户更改资源中的输入是列表对象,完成复杂任务
input updateUserMobileInput {
id:ID!
mobile: String!
}
# 更改或者创建 集合
type Mutation {
updateUserMobile(data: updateUserMobileInput!): User
}
+7 -1
View File
@@ -75,6 +75,7 @@ func redisConnect() (*redis.Client, error) {
// Set set some <key,value> into redis
func (c *cacheRepo) Set(key, value string, ttl time.Duration, options ...Option) error {
ts := time.Now()
opt := newOption()
defer func() {
if opt.Trace != nil {
@@ -82,7 +83,8 @@ func (c *cacheRepo) Set(key, value string, ttl time.Duration, options ...Option)
opt.Redis.Handle = "set"
opt.Redis.Key = key
opt.Redis.Value = value
opt.Redis.TTL = ttl
opt.Redis.TTL = ttl.Minutes()
opt.Redis.CostSeconds = time.Since(ts).Seconds()
opt.Trace.AppendRedis(opt.Redis)
}
}()
@@ -100,12 +102,14 @@ func (c *cacheRepo) Set(key, value string, ttl time.Duration, options ...Option)
// Get get some key from redis
func (c *cacheRepo) Get(key string, options ...Option) (string, error) {
ts := time.Now()
opt := newOption()
defer func() {
if opt.Trace != nil {
opt.Redis.Timestamp = time_parse.CSTLayoutString()
opt.Redis.Handle = "get"
opt.Redis.Key = key
opt.Redis.CostSeconds = time.Since(ts).Seconds()
opt.Trace.AppendRedis(opt.Redis)
}
}()
@@ -155,12 +159,14 @@ func (c *cacheRepo) Del(keys ...string) bool {
}
func (c *cacheRepo) Incr(key string, options ...Option) int64 {
ts := time.Now()
opt := newOption()
defer func() {
if opt.Trace != nil {
opt.Redis.Timestamp = time_parse.CSTLayoutString()
opt.Redis.Handle = "incr"
opt.Redis.Key = key
opt.Redis.CostSeconds = time.Since(ts).Seconds()
opt.Trace.AppendRedis(opt.Redis)
}
}()
+43 -10
View File
@@ -22,14 +22,15 @@ type HandlerFunc func(c Context)
type Trace = trace.T
const (
_Alias = "_alias_"
_TraceName = "_trace_"
_LoggerName = "_logger_"
_BodyName = "_body_"
_PayloadName = "_payload_"
_UserID = "_user_id_"
_UserName = "_user_name_"
_AbortErrorName = "_abort_error_"
_Alias = "_alias_"
_TraceName = "_trace_"
_LoggerName = "_logger_"
_BodyName = "_body_"
_PayloadName = "_payload_"
_GraphPayloadName = "_graph_payload_"
_UserID = "_user_id_"
_UserName = "_user_name_"
_AbortErrorName = "_abort_error_"
)
var contextPool = &sync.Pool{
@@ -92,6 +93,10 @@ type Context interface {
Payload(payload errno.Error)
getPayload() errno.Error
// GraphPayload GraphQL返回值 与 api 返回结构不同
GraphPayload(payload interface{})
getGraphPayload() interface{}
// AbortWithError 错误返回
AbortWithError(err errno.Error)
abortError() errno.Error
@@ -115,6 +120,8 @@ type Context interface {
Alias() string
setAlias(path string)
// Request 获取 Request 对象
Request() *http.Request
// RawData 获取 Request.Body
RawData() []byte
// Method 获取 Request.Method
@@ -127,6 +134,9 @@ type Context interface {
URI() string
// RequestContext 获取请求的 context (当 client 关闭后,会自动 canceled)
RequestContext() StdContext
// ResponseWriter 获取 ResponseWriter 对象
ResponseWriter() gin.ResponseWriter
}
type context struct {
@@ -216,14 +226,27 @@ func (c *context) setLogger(logger *zap.Logger) {
}
func (c *context) getPayload() errno.Error {
payload, _ := c.ctx.Get(_PayloadName)
return payload.(errno.Error)
if payload, ok := c.ctx.Get(_PayloadName); ok != false {
return payload.(errno.Error)
}
return nil
}
func (c *context) Payload(payload errno.Error) {
c.ctx.Set(_PayloadName, payload)
}
func (c *context) getGraphPayload() interface{} {
if payload, ok := c.ctx.Get(_GraphPayloadName); ok != false {
return payload
}
return nil
}
func (c *context) GraphPayload(payload interface{}) {
c.ctx.Set(_GraphPayloadName, payload)
}
func (c *context) Header() http.Header {
header := c.ctx.Request.Header
@@ -303,6 +326,11 @@ func (c *context) setAlias(path string) {
}
}
// Request 获取 Request
func (c *context) Request() *http.Request {
return c.ctx.Request
}
func (c *context) RawData() []byte {
body, ok := c.ctx.Get(_BodyName)
if !ok {
@@ -341,3 +369,8 @@ func (c *context) RequestContext() StdContext {
c.Logger(),
}
}
// ResponseWriter 获取 ResponseWriter
func (c *context) ResponseWriter() gin.ResponseWriter {
return c.ctx.Writer
}
+26 -7
View File
@@ -353,6 +353,7 @@ func New(logger *zap.Logger, options ...Option) (Mux, error) {
businessCodeMsg string
abortErr error
traceId string
graphResponse interface{}
)
if ctx.IsAborted() {
@@ -382,6 +383,8 @@ func New(logger *zap.Logger, options ...Option) (Mux, error) {
ctx.JSON(response.GetHttpCode(), response)
}
graphResponse = context.getGraphPayload()
if opt.recordMetrics != nil {
uri := context.URI()
if alias := context.Alias(); alias != "" {
@@ -415,24 +418,40 @@ func New(logger *zap.Logger, options ...Option) (Mux, error) {
Body: string(context.RawData()),
})
var responseBody interface{}
if response != nil {
responseBody = response
}
if graphResponse != nil {
responseBody = graphResponse
}
t.WithResponse(&trace.Response{
Header: ctx.Writer.Header(),
HttpCode: ctx.Writer.Status(),
HttpCodeMsg: http.StatusText(ctx.Writer.Status()),
BusinessCode: businessCode,
BusinessCodeMsg: businessCodeMsg,
Body: response,
Body: responseBody,
CostSeconds: time.Since(ts).Seconds(),
})
t.Success = !ctx.IsAborted() && ctx.Writer.Status() == http.StatusOK
t.CostSeconds = time.Since(ts).Seconds()
if abortErr == nil {
logger.Info("core-interceptor", zap.Any("trace", t))
} else {
logger.Info("core-interceptor", zap.Any("trace", t), zap.Error(abortErr))
}
logger.Info("core-interceptor",
zap.Any("method", ctx.Request.Method),
zap.Any("path", decodedURL),
zap.Any("http_code", ctx.Writer.Status()),
zap.Any("business_code", businessCode),
zap.Any("success", t.Success),
zap.Any("cost_seconds", t.CostSeconds),
zap.Any("trace_id", t.Identifier),
zap.Any("trace_info", t),
zap.Error(abortErr),
)
}()
ctx.Next()
+3 -2
View File
@@ -1,6 +1,7 @@
package trace
type Debug struct {
Key string `json:"key"` //标示
Value interface{} `json:"value"` //值
Key string `json:"key"` // 标示
Value interface{} `json:"value"` // 值
CostSeconds float64 `json:"cost_seconds"` // 执行时间(单位秒)
}
+6 -7
View File
@@ -1,11 +1,10 @@
package trace
import "time"
type Redis struct {
Timestamp string `json:"timestamp"` // 时间,格式:2006-01-02 15:04:05
Handle string `json:"handle"` // 操作,function
Key string `json:"key"`
Value string `json:"value,omitempty"`
TTL time.Duration `json:"ttl,omitempty"`
Timestamp string `json:"timestamp"` // 时间,格式:2006-01-02 15:04:05
Handle string `json:"handle"` // 操作,SET/GET 等
Key string `json:"key"` // Key
Value string `json:"value,omitempty"` // Value
TTL float64 `json:"ttl,omitempty"` // 超时时长(单位分)
CostSeconds float64 `json:"cost_seconds"` // 执行时间(单位秒)
}
+1 -1
View File
@@ -3,7 +3,7 @@ package trace
type SQL struct {
Timestamp string `json:"timestamp"` // 时间,格式:2006-01-02 15:04:05
Stack string `json:"stack"` // 文件地址和行号
CostSeconds float64 `json:"cost_seconds"` // 执行时长(单位秒)
SQL string `json:"sql"` // SQL 语句
Rows int64 `json:"rows_affected"` // 影响行数
CostSeconds float64 `json:"cost_seconds"` // 执行时长(单位秒)
}
+35 -15
View File
@@ -10,14 +10,15 @@ import (
"github.com/xinliangnote/go-gin-api/internal/api/router"
"github.com/xinliangnote/go-gin-api/internal/pkg/cache"
"github.com/xinliangnote/go-gin-api/internal/pkg/db"
"github.com/xinliangnote/go-gin-api/pkg/env"
"github.com/xinliangnote/go-gin-api/pkg/logger"
"github.com/xinliangnote/go-gin-api/pkg/shutdown"
"go.uber.org/zap"
)
// @title go-gin-api docs api
// @version
// @title swagger 接口文档
// @version 2.0
// @description
// @contact.name
@@ -30,9 +31,9 @@ import (
// @host 127.0.0.1:9999
// @BasePath
func main() {
// 初始化日志
// 初始化 logger
loggers, err := logger.NewJSONLogger(
logger.WithField("domain", configs.ProjectName()),
logger.WithField("domain", fmt.Sprintf("%s[%s]", configs.ProjectName(), env.Active().Value())),
logger.WithTimeLayout("2006-01-02 15:04:05"),
logger.WithFileP(fmt.Sprintf("./logs/%s-access.log", configs.ProjectName())),
)
@@ -41,13 +42,13 @@ func main() {
}
defer loggers.Sync()
// 初始化数据库
// 初始化 DB
dbRepo, err := db.New()
if err != nil {
loggers.Fatal("new db err", zap.Error(err))
}
// 初始化缓存
// 初始化 Cache
cacheRepo, err := cache.New()
if err != nil {
loggers.Fatal("new cache err", zap.Error(err))
@@ -71,14 +72,33 @@ func main() {
}()
// 优雅关闭
shutdown.NewHook().Close(func() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
shutdown.NewHook().Close(
// 关闭 http server
func() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
loggers.Fatal("shutdown err", zap.Error(err))
} else {
loggers.Info("shutdown success")
}
})
if err := server.Shutdown(ctx); err != nil {
loggers.Error("server shutdown err", zap.Error(err))
} else {
loggers.Info("server shutdown success")
}
},
// 关闭 db
func() {
if err := dbRepo.DbWClose(); err != nil {
loggers.Error("dbw close err", zap.Error(err))
}
if err := dbRepo.DbRClose(); err != nil {
loggers.Error("dbr close err", zap.Error(err))
}
},
// 关闭 cache
func() {
cacheRepo.Close()
},
)
}
+35 -22
View File
@@ -23,10 +23,11 @@ const (
type Option func(*option)
type option struct {
level zapcore.Level
fields map[string]string
file io.Writer
timeLayout string
level zapcore.Level
fields map[string]string
file io.Writer
timeLayout string
disableConsole bool
}
// WithDebugLevel only greater than 'level' will output
@@ -90,11 +91,12 @@ func WithFileRotationP(file string) Option {
return func(opt *option) {
opt.file = &lumberjack.Logger{ // concurrent-safed
Filename: file,
MaxSize: 10, // megabytes
MaxBackups: 100,
MaxAge: 30, // days
LocalTime: true,
Filename: file, // 文件路径
MaxSize: 128, // 单个文件最大尺寸,默认单位 M
MaxBackups: 300, // 最多保留 300 个备份
MaxAge: 30, // 最大时间,默认单位 day
LocalTime: true, // 使用本地时间
Compress: true, // 是否压缩 disabled by default
}
}
}
@@ -106,6 +108,13 @@ func WithTimeLayout(timeLayout string) Option {
}
}
// WithEnableConsole write log to os.Stdout or os.Stderr
func WithDisableConsole() Option {
return func(opt *option) {
opt.disableConsole = true
}
}
// NewJSONLogger return a json-encoder zap logger,
func NewJSONLogger(opts ...Option) (*zap.Logger, error) {
opt := &option{level: DefaultLevel, fields: make(map[string]string)}
@@ -120,19 +129,19 @@ func NewJSONLogger(opts ...Option) (*zap.Logger, error) {
// similar to zap.NewProductionEncoderConfig()
encoderConfig := zapcore.EncoderConfig{
TimeKey: "timestamp",
TimeKey: "time",
LevelKey: "level",
NameKey: "logger", // used by logger.Named(key); optional; useless
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "stacktrace", // use by zap.AddStacktrace; optional; useless
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeLevel: zapcore.LowercaseLevelEncoder, // 小写编码器
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format(timeLayout))
},
EncodeDuration: zapcore.MillisDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeCaller: zapcore.ShortCallerEncoder, // 全路径编码器
}
jsonEncoder := zapcore.NewJSONEncoder(encoderConfig)
@@ -150,16 +159,20 @@ func NewJSONLogger(opts ...Option) (*zap.Logger, error) {
stdout := zapcore.Lock(os.Stdout) // lock for concurrent safe
stderr := zapcore.Lock(os.Stderr) // lock for concurrent safe
core := zapcore.NewTee(
zapcore.NewCore(jsonEncoder,
zapcore.NewMultiWriteSyncer(stdout),
lowPriority,
),
zapcore.NewCore(jsonEncoder,
zapcore.NewMultiWriteSyncer(stderr),
highPriority,
),
)
core := zapcore.NewTee()
if !opt.disableConsole {
core = zapcore.NewTee(
zapcore.NewCore(jsonEncoder,
zapcore.NewMultiWriteSyncer(stdout),
lowPriority,
),
zapcore.NewCore(jsonEncoder,
zapcore.NewMultiWriteSyncer(stderr),
highPriority,
),
)
}
if opt.file != nil {
core = zapcore.NewTee(core,
+3
View File
@@ -2,6 +2,7 @@ package p
import (
"fmt"
"time"
"github.com/xinliangnote/go-gin-api/internal/pkg/trace"
)
@@ -20,11 +21,13 @@ func newOption() *option {
}
func Println(key string, value interface{}, options ...Option) {
ts := time.Now()
opt := newOption()
defer func() {
if opt.Trace != nil {
opt.Debug.Key = key
opt.Debug.Value = value
opt.Debug.CostSeconds = time.Since(ts).Seconds()
opt.Trace.AppendDebug(opt.Debug)
}
}()
+12
View File
@@ -27,7 +27,19 @@ func RFC3339ToCSTLayout(value string) (string, error) {
return ts.In(cst).Format(CSTLayout), nil
}
// CSTLayoutString 格式化时间
// 返回 "2006-01-02 15:04:05" 格式的时间
func CSTLayoutString() string {
ts := time.Now()
return ts.In(cst).Format(CSTLayout)
}
// CSTLayoutStringToUnix 返回 unix 时间戳
// 2020-01-24 21:11:11 => 1579871471
func CSTLayoutStringToUnix(cstLayoutString string) (int64, error) {
stamp, err := time.ParseInLocation(CSTLayout, cstLayoutString, cst)
if err != nil {
return 0, err
}
return stamp.Unix(), nil
}
+15
View File
@@ -0,0 +1,15 @@
package time_parse
import "testing"
func TestRFC3339ToCSTLayout(t *testing.T) {
t.Log(RFC3339ToCSTLayout("2020-11-08T08:18:46+08:00"))
}
func TestCSTLayoutString(t *testing.T) {
t.Log(CSTLayoutString())
}
func TestCSTLayoutStringToUnix(t *testing.T) {
t.Log(CSTLayoutStringToUnix("2020-01-24 21:11:11"))
}
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
printf "\nRegenerating gqlgen files\n"
rm -f internal/graph/generated/generated.go \
internal/graph/model/generated.go \
internal/graph/resolvers/generated/generated.go
time go run -v github.com/99designs/gqlgen $1
printf "\nDone.\n\n"
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
printf "\nRegenerating swagger doc\n\n"
time go run -v github.com/swaggo/swag/cmd/swag init
printf "\nDone.\n\n"