Showing preview only (1,656K chars total). Download the full file or copy to clipboard to get everything.
Repository: Q1mi/goweb_pro
Branch: master
Commit: 5831d6ef43a5
Files: 445
Total size: 147.4 MB
Directory structure:
gitextract_l4ew9fl9/
├── .gitignore
├── README.md
├── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ └── validator.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── mysql.go
│ │ │ └── user.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ └── user.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── docker_demo/
│ ├── Dockerfile
│ ├── Dockerfile.back
│ ├── go.mod
│ └── main.go
├── flag_demo/
│ ├── args_demo.go
│ ├── flag_demo
│ ├── flag_demo.go
│ └── go.mod
├── gin_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── json_demo/
│ ├── go.mod
│ ├── go.sum
│ ├── index.html
│ ├── json_demo.go
│ └── main.go
├── lesson23/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ └── validator.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ └── user.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ └── user.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson28/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ └── validator.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ └── user.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ └── user.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson35/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── bluebell
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson68/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── bluebell
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson69/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── doc_response_models.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson70/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── doc_response_models.go
│ │ ├── post.go
│ │ ├── post_test.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ ├── post_test.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson77/
│ └── bluebell/
│ ├── .air.conf
│ ├── Dockerfile
│ ├── Dockerfile.back
│ ├── Makefile
│ ├── bluebell
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── doc_response_models.go
│ │ ├── post.go
│ │ ├── post_test.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ ├── post_test.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── docker-compose.yml
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── init.sql
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ ├── auth.go
│ │ └── ratelimit.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ ├── setting/
│ │ └── setting.go
│ ├── static/
│ │ ├── css/
│ │ │ └── app.6310b918.css
│ │ └── js/
│ │ ├── app.ea0d453e.js
│ │ └── chunk-vendors.57f9e9d6.js
│ ├── templates/
│ │ └── index.html
│ └── wait-for.sh
├── lesson80/
│ └── bluebell/
│ ├── .air.conf
│ ├── .gitignore
│ ├── Dockerfile
│ ├── Dockerfile.back
│ ├── Makefile
│ ├── README.md
│ ├── bin/
│ │ └── .gitkeep
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── doc_response_models.go
│ │ ├── post.go
│ │ ├── post_test.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ ├── post_test.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── docker-compose.yml
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ ├── auth.go
│ │ └── ratelimit.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── nginx.conf
│ ├── nginx2.conf
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ ├── setting/
│ │ └── setting.go
│ ├── sql/
│ │ ├── bluebell_community.sql
│ │ ├── bluebell_post.sql
│ │ ├── bluebell_user.sql
│ │ └── init.sql
│ ├── static/
│ │ ├── css/
│ │ │ └── app.0afe9dae.css
│ │ └── js/
│ │ ├── app.9f3efa6d.js
│ │ └── chunk-vendors.57f9e9d6.js
│ ├── templates/
│ │ └── index.html
│ └── wait-for.sh
├── mysql_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── ratelimit_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── redis_demo/
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── new.go
├── shutdown_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── sqlx_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── swagger_demo/
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── swagger_demo
├── viper_demo/
│ ├── config.yaml
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── web_app/
│ ├── config.yaml
│ ├── dao/
│ │ ├── mysql/
│ │ │ └── mysql.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── main.go
│ ├── routes/
│ │ └── routes.go
│ ├── settings/
│ │ └── settings.go
│ └── web_app
├── web_app2/
│ ├── config.json
│ ├── config.yaml
│ ├── dao/
│ │ ├── mysql/
│ │ │ └── mysql.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── main.go
│ ├── routes/
│ │ └── routes.go
│ ├── settings/
│ │ └── settings.go
│ └── web_app
└── zap_demo/
├── go.mod
├── go.sum
└── main.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
*.log
.idea/
================================================
FILE: README.md
================================================
# Go Web开发进阶实战课程
## 课程源代码地址
[Github仓库地址](https://github.com/Q1mi/goweb_pro)
## 视频课程地址
- [网易云课堂课程连接](https://study.163.com/course/courseMain.htm?courseId=1210171207&share=2&shareId=480000002229610)
- [51CTO课程链接](https://edu.51cto.com/sd/68c23)
================================================
FILE: bluebell/.air.conf
================================================
# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件
# 工作目录
# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下
root = "."
tmp_dir = "tmp"
[build]
# 只需要写你平常编译使用的shell命令。你也可以使用 `make`
cmd = "go build -o ./tmp/main"
# 由`cmd`命令得到的二进制文件名
bin = "tmp/main"
# 自定义的二进制,可以添加额外的编译标识例如添加 GIN_MODE=release
full_bin = "./tmp/main ./conf/config.yaml"
# 监听以下文件扩展名的文件.
include_ext = ["go", "tpl", "tmpl", "html", "yaml"]
# 忽略这些文件扩展名或目录
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
# 监听以下指定目录的文件
include_dir = []
# 排除以下文件
exclude_file = []
# 如果文件更改过于频繁,则没有必要在每次更改时都触发构建。可以设置触发构建的延迟时间
delay = 1000 # ms
# 发生构建错误时,停止运行旧的二进制文件。
stop_on_error = true
# air的日志文件名,该日志文件放置在你的`tmp_dir`中
log = "air_errors.log"
[log]
# 显示日志时间
time = true
[color]
# 自定义每个部分显示的颜色。如果找不到颜色,使用原始的应用程序日志。
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"
[misc]
# 退出时删除tmp目录
clean_on_exit = true
================================================
FILE: bluebell/Makefile
================================================
.PHONY: all build run gotool clean help
BINARY="xx"
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${BINARY}
run:
@go run ./main.go conf/config.yaml
gotool:
go fmt ./
go vet ./
clean:
@if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
help:
@echo "make - 格式化 Go 代码, 并编译生成二进制文件"
@echo "make build - 编译 Go 代码, 生成二进制文件"
@echo "make run - 直接运行 Go 代码"
@echo "make clean - 移除二进制文件和 vim swap files"
@echo "make gotool - 运行 Go 工具 'fmt' and 'vet'"
================================================
FILE: bluebell/conf/config.yaml
================================================
name: "bluebell"
mode: "dev"
port: 8081
version: "v0.0.1"
start_time: "2020-07-01"
machine_id: 1
log:
level: "debug"
filename: "web_app.log"
max_size: 200
max_age: 30
max_backups: 7
mysql:
host: "127.0.0.1"
port: 13306
user: "root"
password: "root1234"
dbname: "bluebell"
max_open_conns: 200
max_idle_conns: 50
redis:
host: "127.0.0.1"
port: 16379
password: ""
db: 0
pool_size: 100
================================================
FILE: bluebell/controller/code.go
================================================
package controller
type ResCode int64
const (
CodeSuccess ResCode = 1000 + iota
CodeInvalidParam
CodeUserExist
CodeUserNotExist
CodeInvalidPassword
CodeServerBusy
CodeNeedLogin
CodeInvalidToken
)
var codeMsgMap = map[ResCode]string{
CodeSuccess: "success",
CodeInvalidParam: "请求参数错误",
CodeUserExist: "用户名已存在",
CodeUserNotExist: "用户名不存在",
CodeInvalidPassword: "用户名或密码错误",
CodeServerBusy: "服务繁忙",
CodeNeedLogin: "需要登录",
CodeInvalidToken: "无效的token",
}
func (c ResCode) Msg() string {
msg, ok := codeMsgMap[c]
if !ok {
msg = codeMsgMap[CodeServerBusy]
}
return msg
}
================================================
FILE: bluebell/controller/request.go
================================================
package controller
import (
"errors"
"github.com/gin-gonic/gin"
)
const CtxUserIDKey = "userID"
var ErrorUserNotLogin = errors.New("用户未登录")
// getCurrentUser 获取当前登录的用户ID
func getCurrentUser(c *gin.Context) (userID int64, err error) {
uid, ok := c.Get(CtxUserIDKey)
if !ok {
err = ErrorUserNotLogin
return
}
userID, ok = uid.(int64)
if !ok {
err = ErrorUserNotLogin
return
}
return
}
================================================
FILE: bluebell/controller/response.go
================================================
package controller
import (
"net/http"
"github.com/gin-gonic/gin"
)
/*
{
"code": 10000, // 程序中的错误码
"msg": xx, // 提示信息
"data": {}, // 数据
}
*/
type ResponseData struct {
Code ResCode `json:"code"`
Msg interface{} `json:"msg"`
Data interface{} `json:"data"`
}
func ResponseError(c *gin.Context, code ResCode) {
c.JSON(http.StatusOK, &ResponseData{
Code: code,
Msg: code.Msg(),
Data: nil,
})
}
func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
c.JSON(http.StatusOK, &ResponseData{
Code: code,
Msg: msg,
Data: nil,
})
}
func ResponseSuccess(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, &ResponseData{
Code: CodeSuccess,
Msg: CodeSuccess.Msg(),
Data: data,
})
}
================================================
FILE: bluebell/controller/user.go
================================================
package controller
import (
"bluebell/dao/mysql"
"bluebell/logic"
"bluebell/models"
"errors"
"github.com/go-playground/validator/v10"
"go.uber.org/zap"
"github.com/gin-gonic/gin"
)
// SignUpHandler 处理注册请求的函数
func SignUpHandler(c *gin.Context) {
// 1. 获取参数和参数校验
p := new(models.ParamSignUp)
if err := c.ShouldBindJSON(p); err != nil {
// 请求参数有误,直接返回响应
zap.L().Error("SignUp with invalid param", zap.Error(err))
// 判断err是不是validator.ValidationErrors 类型
errs, ok := err.(validator.ValidationErrors)
if !ok {
ResponseError(c, CodeInvalidParam)
return
}
ResponseErrorWithMsg(c, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
// 2. 业务处理
if err := logic.SignUp(p); err != nil {
zap.L().Error("logic.SignUp failed", zap.Error(err))
if errors.Is(err, mysql.ErrorUserExist) {
ResponseError(c, CodeUserExist)
return
}
ResponseError(c, CodeServerBusy)
return
}
// 3. 返回响应
ResponseSuccess(c, nil)
}
func LoginHandler(c *gin.Context) {
// 1.获取请求参数及参数校验
p := new(models.ParamLogin)
if err := c.ShouldBindJSON(p); err != nil {
// 请求参数有误,直接返回响应
zap.L().Error("Login with invalid param", zap.Error(err))
// 判断err是不是validator.ValidationErrors 类型
errs, ok := err.(validator.ValidationErrors)
if !ok {
ResponseError(c, CodeInvalidParam)
return
}
ResponseErrorWithMsg(c, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
// 2.业务逻辑处理
token, err := logic.Login(p)
if err != nil {
zap.L().Error("logic.Login failed", zap.String("username", p.Username), zap.Error(err))
if errors.Is(err, mysql.ErrorUserNotExist) {
ResponseError(c, CodeUserNotExist)
return
}
ResponseError(c, CodeInvalidPassword)
return
}
// 3.返回响应
ResponseSuccess(c, token)
}
================================================
FILE: bluebell/controller/validator.go
================================================
package controller
import (
"bluebell/models"
"fmt"
"reflect"
"strings"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
enTranslations "github.com/go-playground/validator/v10/translations/en"
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)
// 定义一个全局翻译器T
var trans ut.Translator
// InitTrans 初始化翻译器
func InitTrans(locale string) (err error) {
// 修改gin框架中的Validator引擎属性,实现自定制
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
// 注册一个获取json tag的自定义方法
v.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
// 为SignUpParam注册自定义校验方法
v.RegisterStructValidation(SignUpParamStructLevelValidation, models.ParamSignUp{})
zhT := zh.New() // 中文翻译器
enT := en.New() // 英文翻译器
// 第一个参数是备用(fallback)的语言环境
// 后面的参数是应该支持的语言环境(支持多个)
// uni := ut.New(zhT, zhT) 也是可以的
uni := ut.New(enT, zhT, enT)
// locale 通常取决于 http 请求头的 'Accept-Language'
var ok bool
// 也可以使用 uni.FindTranslator(...) 传入多个locale进行查找
trans, ok = uni.GetTranslator(locale)
if !ok {
return fmt.Errorf("uni.GetTranslator(%s) failed", locale)
}
// 注册翻译器
switch locale {
case "en":
err = enTranslations.RegisterDefaultTranslations(v, trans)
case "zh":
err = zhTranslations.RegisterDefaultTranslations(v, trans)
default:
err = enTranslations.RegisterDefaultTranslations(v, trans)
}
return
}
return
}
// removeTopStruct 去除提示信息中的结构体名称
func removeTopStruct(fields map[string]string) map[string]string {
res := map[string]string{}
for field, err := range fields {
res[field[strings.Index(field, ".")+1:]] = err
}
return res
}
// SignUpParamStructLevelValidation 自定义SignUpParam结构体校验函数
func SignUpParamStructLevelValidation(sl validator.StructLevel) {
su := sl.Current().Interface().(models.ParamSignUp)
if su.Password != su.RePassword {
// 输出错误提示信息,最后一个参数就是传递的param
sl.ReportError(su.RePassword, "re_password", "RePassword", "eqfield", "password")
}
}
================================================
FILE: bluebell/dao/mysql/mysql.go
================================================
package mysql
import (
"bluebell/setting"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
var db *sqlx.DB
// Init 初始化MySQL连接
func Init(cfg *setting.MySQLConfig) (err error) {
// "user:password@tcp(host:port)/dbname"
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=true&loc=Local", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DB)
db, err = sqlx.Connect("mysql", dsn)
if err != nil {
return
}
db.SetMaxOpenConns(cfg.MaxOpenConns)
db.SetMaxIdleConns(cfg.MaxIdleConns)
return
}
// Close 关闭MySQL连接
func Close() {
_ = db.Close()
}
================================================
FILE: bluebell/dao/mysql/user.go
================================================
package mysql
import (
"bluebell/models"
"crypto/md5"
"database/sql"
"encoding/hex"
"errors"
)
// 把每一步数据库操作封装成函数
// 待logic层根据业务需求调用
const secret = "liwenzhou.com"
var (
ErrorUserExist = errors.New("用户已存在")
ErrorUserNotExist = errors.New("用户不存在")
ErrorInvalidPassword = errors.New("用户名或密码错误")
)
// CheckUserExist 检查指定用户名的用户是否存在
func CheckUserExist(username string) (err error) {
sqlStr := `select count(user_id) from user where username = ?`
var count int64
if err := db.Get(&count, sqlStr, username); err != nil {
return err
}
if count > 0 {
return ErrorUserExist
}
return
}
// InsertUser 想数据库中插入一条新的用户记录
func InsertUser(user *models.User) (err error) {
// 对密码进行加密
user.Password = encryptPassword(user.Password)
// 执行SQL语句入库
sqlStr := `insert into user(user_id, username, password) values(?,?,?)`
_, err = db.Exec(sqlStr, user.UserID, user.Username, user.Password)
return
}
// encryptPassword 密码加密
func encryptPassword(oPassword string) string {
h := md5.New()
h.Write([]byte(secret))
return hex.EncodeToString(h.Sum([]byte(oPassword)))
}
func Login(user *models.User) (err error) {
oPassword := user.Password // 用户登录的密码
sqlStr := `select user_id, username, password from user where username=?`
err = db.Get(user, sqlStr, user.Username)
if err == sql.ErrNoRows {
return ErrorUserNotExist
}
if err != nil {
// 查询数据库失败
return err
}
// 判断密码是否正确
password := encryptPassword(oPassword)
if password != user.Password {
return ErrorInvalidPassword
}
return
}
================================================
FILE: bluebell/dao/redis/redis.go
================================================
package redis
import (
"bluebell/setting"
"fmt"
"github.com/go-redis/redis"
)
var (
client *redis.Client
Nil = redis.Nil
)
// Init 初始化连接
func Init(cfg *setting.RedisConfig) (err error) {
client = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
Password: cfg.Password, // no password set
DB: cfg.DB, // use default DB
PoolSize: cfg.PoolSize,
MinIdleConns: cfg.MinIdleConns,
})
_, err = client.Ping().Result()
if err != nil {
return err
}
return nil
}
func Close() {
_ = client.Close()
}
================================================
FILE: bluebell/go.mod
================================================
module bluebell
go 1.14
require (
github.com/bwmarrin/snowflake v0.3.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fsnotify/fsnotify v1.4.9
github.com/gin-gonic/gin v1.6.3
github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0
github.com/go-playground/validator/v10 v10.2.0
github.com/go-redis/redis v6.15.8+incompatible
github.com/go-sql-driver/mysql v1.5.0
github.com/jmoiron/sqlx v1.2.0
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/onsi/ginkgo v1.14.0 // indirect
github.com/sony/sonyflake v1.0.0 // indirect
github.com/spf13/viper v1.7.0
go.uber.org/zap v1.15.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
)
================================================
FILE: bluebell/go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
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/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=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
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=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
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/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
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-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=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-redis/redis v6.15.8+incompatible h1:BKZuG6mCnRj5AOaWJXoCgf6rqTYnYJLe4en2hxT7r9o=
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
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.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=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
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/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=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
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/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=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
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 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=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
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=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
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/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/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=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM=
github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
github.com/spf13/viper v1.7.0/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.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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
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/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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-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=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
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-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc h1:NCy3Ohtk6Iny5V/reW2Ktypo4zIpWBdRJ1uFMjBxdg8=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
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=
================================================
FILE: bluebell/logger/logger.go
================================================
package logger
import (
"bluebell/setting"
"net"
"net/http"
"net/http/httputil"
"os"
"runtime/debug"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var lg *zap.Logger
// Init 初始化lg
func Init(cfg *setting.LogConfig, mode string) (err error) {
writeSyncer := getLogWriter(cfg.Filename, cfg.MaxSize, cfg.MaxBackups, cfg.MaxAge)
encoder := getEncoder()
var l = new(zapcore.Level)
err = l.UnmarshalText([]byte(cfg.Level))
if err != nil {
return
}
var core zapcore.Core
if mode == "dev" {
// 进入开发模式,日志输出到终端
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
core = zapcore.NewTee(
zapcore.NewCore(encoder, writeSyncer, l),
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), zapcore.DebugLevel),
)
} else {
core = zapcore.NewCore(encoder, writeSyncer, l)
}
lg = zap.New(core, zap.AddCaller())
zap.ReplaceGlobals(lg)
zap.L().Info("init logger success")
return
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.TimeKey = "time"
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
return zapcore.NewJSONEncoder(encoderConfig)
}
func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: filename,
MaxSize: maxSize,
MaxBackups: maxBackup,
MaxAge: maxAge,
}
return zapcore.AddSync(lumberJackLogger)
}
// GinLogger 接收gin框架默认的日志
func GinLogger() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
query := c.Request.URL.RawQuery
c.Next()
cost := time.Since(start)
lg.Info(path,
zap.Int("status", c.Writer.Status()),
zap.String("method", c.Request.Method),
zap.String("path", path),
zap.String("query", query),
zap.String("ip", c.ClientIP()),
zap.String("user-agent", c.Request.UserAgent()),
zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),
zap.Duration("cost", cost),
)
}
}
// GinRecovery recover掉项目可能出现的panic,并使用zap记录相关日志
func GinRecovery(stack bool) gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
// Check for a broken connection, as it is not really a
// condition that warrants a panic stack trace.
var brokenPipe bool
if ne, ok := err.(*net.OpError); ok {
if se, ok := ne.Err.(*os.SyscallError); ok {
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
brokenPipe = true
}
}
}
httpRequest, _ := httputil.DumpRequest(c.Request, false)
if brokenPipe {
lg.Error(c.Request.URL.Path,
zap.Any("error", err),
zap.String("request", string(httpRequest)),
)
// If the connection is dead, we can't write a status to it.
c.Error(err.(error)) // nolint: errcheck
c.Abort()
return
}
if stack {
lg.Error("[Recovery from panic]",
zap.Any("error", err),
zap.String("request", string(httpRequest)),
zap.String("stack", string(debug.Stack())),
)
} else {
lg.Error("[Recovery from panic]",
zap.Any("error", err),
zap.String("request", string(httpRequest)),
)
}
c.AbortWithStatus(http.StatusInternalServerError)
}
}()
c.Next()
}
}
================================================
FILE: bluebell/logic/user.go
================================================
package logic
import (
"bluebell/dao/mysql"
"bluebell/models"
"bluebell/pkg/jwt"
"bluebell/pkg/snowflake"
)
// 存放业务逻辑的代码
func SignUp(p *models.ParamSignUp) (err error) {
// 1.判断用户存不存在
if err := mysql.CheckUserExist(p.Username); err != nil {
return err
}
// 2.生成UID
userID := snowflake.GenID()
// 构造一个User实例
user := &models.User{
UserID: userID,
Username: p.Username,
Password: p.Password,
}
// 3.保存进数据库
return mysql.InsertUser(user)
}
func Login(p *models.ParamLogin) (token string, err error) {
user := &models.User{
Username: p.Username,
Password: p.Password,
}
// 传递的是指针,就能拿到user.UserID
if err := mysql.Login(user); err != nil {
return "", err
}
// 生成JWT
return jwt.GenToken(user.UserID, user.Username)
}
================================================
FILE: bluebell/main.go
================================================
package main
import (
"bluebell/controller"
"bluebell/dao/mysql"
"bluebell/dao/redis"
"bluebell/logger"
"bluebell/pkg/snowflake"
"bluebell/router"
"bluebell/setting"
"fmt"
"os"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("need config file.eg: bluebell config.yaml")
return
}
// 加载配置
if err := setting.Init(os.Args[1]); err != nil {
fmt.Printf("load config failed, err:%v\n", err)
return
}
if err := logger.Init(setting.Conf.LogConfig, setting.Conf.Mode); err != nil {
fmt.Printf("init logger failed, err:%v\n", err)
return
}
if err := mysql.Init(setting.Conf.MySQLConfig); err != nil {
fmt.Printf("init mysql failed, err:%v\n", err)
return
}
defer mysql.Close() // 程序退出关闭数据库连接
if err := redis.Init(setting.Conf.RedisConfig); err != nil {
fmt.Printf("init redis failed, err:%v\n", err)
return
}
defer redis.Close()
if err := snowflake.Init(setting.Conf.StartTime, setting.Conf.MachineID); err != nil {
fmt.Printf("init snowflake failed, err:%v\n", err)
return
}
// 初始化gin框架内置的校验器使用的翻译器
if err := controller.InitTrans("zh"); err != nil {
fmt.Printf("init validator trans failed, err:%v\n", err)
return
}
// 注册路由
r := router.SetupRouter(setting.Conf.Mode)
err := r.Run(fmt.Sprintf(":%d", setting.Conf.Port))
if err != nil {
fmt.Printf("run server failed, err:%v\n", err)
return
}
}
================================================
FILE: bluebell/middlewares/auth.go
================================================
package middlewares
import (
"bluebell/controller"
"bluebell/pkg/jwt"
"strings"
"github.com/gin-gonic/gin"
)
// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
return func(c *gin.Context) {
// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
// 这里假设Token放在Header的Authorization中,并使用Bearer开头
// Authorization: Bearer xxxxxxx.xxx.xxx / X-TOKEN: xxx.xxx.xx
// 这里的具体实现方式要依据你的实际业务情况决定
authHeader := c.Request.Header.Get("Authorization")
if authHeader == "" {
controller.ResponseError(c, controller.CodeNeedLogin)
c.Abort()
return
}
// 按空格分割
parts := strings.SplitN(authHeader, " ", 2)
if !(len(parts) == 2 && parts[0] == "Bearer") {
controller.ResponseError(c, controller.CodeInvalidToken)
c.Abort()
return
}
// parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
mc, err := jwt.ParseToken(parts[1])
if err != nil {
controller.ResponseError(c, controller.CodeInvalidToken)
c.Abort()
return
}
// 将当前请求的userID信息保存到请求的上下文c上
c.Set(controller.CtxUserIDKey, mc.UserID)
c.Next() // 后续的处理请求的函数中 可以用过c.Get(CtxUserIDKey) 来获取当前请求的用户信息
}
}
================================================
FILE: bluebell/models/create_table.sql
================================================
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL,
`username` varchar(64) COLLATE utf8mb4_general_ci NOT NULL,
`password` varchar(64) COLLATE utf8mb4_general_ci NOT NULL,
`email` varchar(64) COLLATE utf8mb4_general_ci,
`gender` tinyint(4) NOT NULL DEFAULT '0',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`) USING BTREE,
UNIQUE KEY `idx_user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
================================================
FILE: bluebell/models/params.go
================================================
package models
// 定义请求的参数结构体
// ParamSignUp 注册请求参数
type ParamSignUp struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}
// ParamLogin 登录请求参数
type ParamLogin struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
================================================
FILE: bluebell/models/user.go
================================================
package models
type User struct {
UserID int64 `db:"user_id"`
Username string `db:"username"`
Password string `db:"password"`
}
================================================
FILE: bluebell/pkg/jwt/jwt.go
================================================
package jwt
import (
"errors"
"time"
"github.com/dgrijalva/jwt-go"
)
const TokenExpireDuration = time.Hour * 2
var mySecret = []byte("夏天夏天悄悄过去")
// MyClaims 自定义声明结构体并内嵌jwt.StandardClaims
// jwt包自带的jwt.StandardClaims只包含了官方字段
// 我们这里需要额外记录一个username字段,所以要自定义结构体
// 如果想要保存更多信息,都可以添加到这个结构体中
type MyClaims struct {
UserID int64 `json:"user_id"`
Username string `json:"username"`
jwt.StandardClaims
}
// GenToken 生成JWT
func GenToken(userID int64, username string) (string, error) {
// 创建一个我们自己的声明的数据
c := MyClaims{
userID,
"username", // 自定义字段
jwt.StandardClaims{
ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
Issuer: "bluebell", // 签发人
},
}
// 使用指定的签名方法创建签名对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
// 使用指定的secret签名并获得完整的编码后的字符串token
return token.SignedString(mySecret)
}
// ParseToken 解析JWT
func ParseToken(tokenString string) (*MyClaims, error) {
// 解析token
var mc = new(MyClaims)
token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
return mySecret, nil
})
if err != nil {
return nil, err
}
if token.Valid { // 校验token
return mc, nil
}
return nil, errors.New("invalid token")
}
================================================
FILE: bluebell/pkg/snowflake/snowflake.go
================================================
package snowflake
import (
"time"
sf "github.com/bwmarrin/snowflake"
)
var node *sf.Node
func Init(startTime string, machineID int64) (err error) {
var st time.Time
st, err = time.Parse("2006-01-02", startTime)
if err != nil {
return
}
sf.Epoch = st.UnixNano() / 1000000
node, err = sf.NewNode(machineID)
return
}
func GenID() int64 {
return node.Generate().Int64()
}
================================================
FILE: bluebell/router/route.go
================================================
package router
import (
"bluebell/controller"
"bluebell/logger"
"bluebell/middlewares"
"net/http"
"github.com/gin-gonic/gin"
)
func SetupRouter(mode string) *gin.Engine {
if mode == gin.ReleaseMode {
gin.SetMode(gin.ReleaseMode) // gin设置成发布模式
}
r := gin.New()
r.Use(logger.GinLogger(), logger.GinRecovery(true))
// 注册
r.POST("/signup", controller.SignUpHandler)
// 登录
r.POST("/login", controller.LoginHandler)
r.GET("/ping", middlewares.JWTAuthMiddleware(), func(c *gin.Context) {
// 如果是登录的用户,判断请求头中是否有 有效的JWT ?
c.JSON(http.StatusOK, gin.H{
"msg": "ok",
})
})
r.NoRoute(func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "404",
})
})
return r
}
================================================
FILE: bluebell/setting/setting.go
================================================
package setting
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
var Conf = new(AppConfig)
type AppConfig struct {
Name string `mapstructure:"name"`
Mode string `mapstructure:"mode"`
Version string `mapstructure:"version"`
StartTime string `mapstructure:"start_time"`
MachineID int64 `mapstructure:"machine_id"`
Port int `mapstructure:"port"`
*LogConfig `mapstructure:"log"`
*MySQLConfig `mapstructure:"mysql"`
*RedisConfig `mapstructure:"redis"`
}
type MySQLConfig struct {
Host string `mapstructure:"host"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
DB string `mapstructure:"dbname"`
Port int `mapstructure:"port"`
MaxOpenConns int `mapstructure:"max_open_conns"`
MaxIdleConns int `mapstructure:"max_idle_conns"`
}
type RedisConfig struct {
Host string `mapstructure:"host"`
Password string `mapstructure:"password"`
Port int `mapstructure:"port"`
DB int `mapstructure:"db"`
PoolSize int `mapstructure:"pool_size"`
MinIdleConns int `mapstructure:"min_idle_conns"`
}
type LogConfig struct {
Level string `mapstructure:"level"`
Filename string `mapstructure:"filename"`
MaxSize int `mapstructure:"max_size"`
MaxAge int `mapstructure:"max_age"`
MaxBackups int `mapstructure:"max_backups"`
}
func Init(filePath string) (err error) {
// 方式1:直接指定配置文件路径(相对路径或者绝对路径)
// 相对路径:相对执行的可执行文件的相对路径
//viper.SetConfigFile("./conf/config.yaml")
// 绝对路径:系统中实际的文件路径
//viper.SetConfigFile("/Users/liwenzhou/Desktop/bluebell/conf/config.yaml")
// 方式2:指定配置文件名和配置文件的位置,viper自行查找可用的配置文件
// 配置文件名不需要带后缀
// 配置文件位置可配置多个
//viper.SetConfigName("config") // 指定配置文件名(不带后缀)
//viper.AddConfigPath(".") // 指定查找配置文件的路径(这里使用相对路径)
//viper.AddConfigPath("./conf") // 指定查找配置文件的路径(这里使用相对路径)
// 基本上是配合远程配置中心使用的,告诉viper当前的数据使用什么格式去解析
//viper.SetConfigType("json")
viper.SetConfigFile(filePath)
err = viper.ReadInConfig() // 读取配置信息
if err != nil {
// 读取配置信息失败
fmt.Printf("viper.ReadInConfig failed, err:%v\n", err)
return
}
// 把读取到的配置信息反序列化到 Conf 变量中
if err := viper.Unmarshal(Conf); err != nil {
fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
}
viper.WatchConfig()
viper.OnConfigChange(func(in fsnotify.Event) {
fmt.Println("配置文件修改了...")
if err := viper.Unmarshal(Conf); err != nil {
fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
}
})
return
}
================================================
FILE: docker_demo/Dockerfile
================================================
FROM golang:alpine AS builder
# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
# 移动到工作目录:/build
WORKDIR /build
# 将代码复制到容器中
COPY . .
# 将我们的代码编译成二进制可执行文件 app
RUN go build -o app .
###################
# 接下来创建一个小镜像
###################
FROM scratch
# 从builder镜像中把/dist/app 拷贝到当前目录
COPY --from=builder /build/app /
# 需要运行的命令
ENTRYPOINT ["/app"]
================================================
FILE: docker_demo/Dockerfile.back
================================================
FROM golang:alpine
# 为我们的镜像设置必要的环境变量
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
# 移动到工作目录:/build
WORKDIR /build
# 将代码复制到容器中
COPY . .
# 将我们的代码编译成二进制可执行文件app
RUN go build -o app .
# 声明服务端口
EXPOSE 8888
# 启动容器时运行的命令
CMD ["/build/app"]
================================================
FILE: docker_demo/go.mod
================================================
module "docker_demo"
================================================
FILE: docker_demo/main.go
================================================
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", hello)
server := &http.Server{
Addr: ":8888",
}
fmt.Println("server startup...")
if err := server.ListenAndServe(); err != nil {
fmt.Printf("server startup failed, err:%v\n", err)
}
}
func hello(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte("hello liwenzhou.com!"))
}
================================================
FILE: flag_demo/args_demo.go
================================================
package main
import (
"fmt"
"os"
)
//os.Args demo
func main() {
// os.Args是一个[]string
// os.Args[0] 是当前执行的程序
fmt.Println(os.Args)
if len(os.Args) > 0 {
for index, arg := range os.Args {
fmt.Printf("args[%d]=%v\n", index, arg)
}
}
}
================================================
FILE: flag_demo/flag_demo.go
================================================
package main
import (
"flag"
"fmt"
"time"
)
func main() {
//定义命令行参数方式1
var name string
var age int
var married bool
var delay time.Duration
flag.StringVar(&name, "name", "张三", "姓名")
flag.IntVar(&age, "age", 18, "年龄")
flag.BoolVar(&married, "married", false, "婚否")
flag.DurationVar(&delay, "d", 0, "延迟的时间间隔")
//解析命令行参数
flag.Parse()
fmt.Println(name, age, married, delay)
//返回命令行参数后的其他参数
fmt.Println(flag.Args())
//返回命令行参数后的其他参数个数
fmt.Println(flag.NArg())
//返回使用的命令行参数个数
fmt.Println(flag.NFlag())
}
================================================
FILE: flag_demo/go.mod
================================================
module flag_demo
go 1.14
================================================
FILE: gin_demo/go.mod
================================================
module gin_demo
go 1.14
require github.com/gin-gonic/gin v1.6.3
================================================
FILE: gin_demo/go.sum
================================================
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
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-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
================================================
FILE: gin_demo/main.go
================================================
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
func func1(c *gin.Context){
fmt.Println("func1")
}
func func2(c *gin.Context){
fmt.Println("func2 before")
c.Next()
fmt.Println("func2 after")
}
func func3(c *gin.Context){
fmt.Println("func3")
//c.Abort()
}
func func4(c *gin.Context){
fmt.Println("func4")
c.Set("name", "q1mi")
}
func func5(c *gin.Context){
fmt.Println("func5")
v, ok := c.Get("name")
if ok{
vStr := v.(string) // 类型转换
fmt.Println(vStr)
}
}
func main() {
r := gin.Default()
r.GET("/hello", func(c *gin.Context) {
c.String(http.StatusOK, "ok")
})
shopGroup := r.Group("/shop", func1, func2)
shopGroup.Use(func3)
{
shopGroup.GET("/index", func4, func5)
}
r.Run()
}
================================================
FILE: json_demo/go.mod
================================================
module json_demo
go 1.14
require github.com/gin-gonic/gin v1.6.3
================================================
FILE: json_demo/go.sum
================================================
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
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-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
================================================
FILE: json_demo/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>json demo</title>
</head>
<body>
<h1>json demo</h1>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
axios.get('/data')
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
</script>
</body>
</html>
================================================
FILE: json_demo/json_demo.go
================================================
package main
import (
"encoding/json"
"fmt"
"math"
)
type MyData struct {
ID int64 `json:"id,string"`
Name string `json:"name"`
}
//func (d *MyData) Unmarshal() {
//
//}
//
//func (d *MyData) Marshal() {
//
//}
// 第一层:
// 第二层:
// 第五层:
// 第九层:
func main() {
// 序列化: 后端的数据->JSON格式的数据
d1 := MyData{
ID: math.MaxInt64,
Name: "七米",
}
// json序列化
b, err := json.Marshal(d1)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(b))
// 反序列化:JSON格式的数据 -> Go语言中的数据
s := `{"id":"9223372036854775807","name":"七米"}`
var d2 MyData
if err := json.Unmarshal([]byte(s), &d2); err != nil {
fmt.Println(err)
return
}
fmt.Printf("%#v type:%T\n", d2, d2.ID)
}
================================================
FILE: json_demo/main.go
================================================
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
// ???
// 在后端使用的时候还是用int64
// 进行json序列化与反序列化的时候就使用字符串
type Data struct {
ID int64 `json:"id"`
}
func main() {
r := gin.Default()
r.LoadHTMLFiles("index.html")
r.GET("/index", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
r.GET("/data", func(c *gin.Context) {
// int64
// math.MaxInt64 --> 1<<63 -1
// math.MinInt64 --> -1 << 63
// 1234567891234568000
c.JSON(http.StatusOK, Data{1234567891234567889})
})
r.Run(":8990")
}
================================================
FILE: lesson23/bluebell/.air.conf
================================================
# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件
# 工作目录
# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下
root = "."
tmp_dir = "tmp"
[build]
# 只需要写你平常编译使用的shell命令。你也可以使用 `make`
cmd = "go build -o ./tmp/main"
# 由`cmd`命令得到的二进制文件名
bin = "tmp/main"
# 自定义的二进制,可以添加额外的编译标识例如添加 GIN_MODE=release
full_bin = "./tmp/main ./conf/config.yaml"
# 监听以下文件扩展名的文件.
include_ext = ["go", "tpl", "tmpl", "html", "yaml"]
# 忽略这些文件扩展名或目录
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
# 监听以下指定目录的文件
include_dir = []
# 排除以下文件
exclude_file = []
# 如果文件更改过于频繁,则没有必要在每次更改时都触发构建。可以设置触发构建的延迟时间
delay = 1000 # ms
# 发生构建错误时,停止运行旧的二进制文件。
stop_on_error = true
# air的日志文件名,该日志文件放置在你的`tmp_dir`中
log = "air_errors.log"
[log]
# 显示日志时间
time = true
[color]
# 自定义每个部分显示的颜色。如果找不到颜色,使用原始的应用程序日志。
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"
[misc]
# 退出时删除tmp目录
clean_on_exit = true
================================================
FILE: lesson23/bluebell/Makefile
================================================
.PHONY: all build run gotool clean help
BINARY="xx"
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${BINARY}
run:
@go run ./main.go conf/config.yaml
gotool:
go fmt ./
go vet ./
clean:
@if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
help:
@echo "make - 格式化 Go 代码, 并编译生成二进制文件"
@echo "make build - 编译 Go 代码, 生成二进制文件"
@echo "make run - 直接运行 Go 代码"
@echo "make clean - 移除二进制文件和 vim swap files"
@echo "make gotool - 运行 Go 工具 'fmt' and 'vet'"
================================================
FILE: lesson23/bluebell/conf/config.yaml
================================================
name: "bluebell"
mode: "dev"
port: 8084
version: "v0.0.1"
start_time: "2020-07-01"
machine_id: 1
auth:
jwt_expire: 8760
log:
level: "debug"
filename: "web_app.log"
max_size: 200
max_age: 30
max_backups: 7
mysql:
host: "127.0.0.1"
port: 13306
user: "root"
password: "root1234"
dbname: "bluebell"
max_open_conns: 200
max_idle_conns: 50
redis:
host: "127.0.0.1"
port: 16379
password: ""
db: 0
pool_size: 100
================================================
FILE: lesson23/bluebell/controller/code.go
================================================
package controller
type ResCode int64
const (
CodeSuccess ResCode = 1000 + iota
CodeInvalidParam
CodeUserExist
CodeUserNotExist
CodeInvalidPassword
CodeServerBusy
CodeNeedLogin
CodeInvalidToken
)
var codeMsgMap = map[ResCode]string{
CodeSuccess: "success",
CodeInvalidParam: "请求参数错误",
CodeUserExist: "用户名已存在",
CodeUserNotExist: "用户名不存在",
CodeInvalidPassword: "用户名或密码错误",
CodeServerBusy: "服务繁忙",
CodeNeedLogin: "需要登录",
CodeInvalidToken: "无效的token",
}
func (c ResCode) Msg() string {
msg, ok := codeMsgMap[c]
if !ok {
msg = codeMsgMap[CodeServerBusy]
}
return msg
}
================================================
FILE: lesson23/bluebell/controller/community.go
================================================
package controller
import (
"bluebell/logic"
"strconv"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// ---- 跟社区相关的 ----
func CommunityHandler(c *gin.Context) {
// 查询到所有的社区(community_id, community_name) 以列表的形式返回
data, err := logic.GetCommunityList()
if err != nil {
zap.L().Error("logic.GetCommunityList() failed", zap.Error(err))
ResponseError(c, CodeServerBusy) // 不轻易把服务端报错暴露给外面
return
}
ResponseSuccess(c, data)
}
// CommunityDetailHandler 社区分类详情
func CommunityDetailHandler(c *gin.Context) {
// 1. 获取社区id
idStr := c.Param("id") // 获取URL参数
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
ResponseError(c, CodeInvalidParam)
return
}
// 2. 根据id获取社区详情
data, err := logic.GetCommunityDetail(id)
if err != nil {
zap.L().Error("logic.GetCommunityList() failed", zap.Error(err))
ResponseError(c, CodeServerBusy) // 不轻易把服务端报错暴露给外面
return
}
ResponseSuccess(c, data)
}
================================================
FILE: lesson23/bluebell/controller/post.go
================================================
package controller
import "github.com/gin-gonic/gin"
func CreatePostHandler(c *gin.Context) {
// 1. 获取参数及参数的校验
//c.ShouldBindJSON()
// 2. 创建帖子
// 3. 返回响应
}
================================================
FILE: lesson23/bluebell/controller/request.go
================================================
package controller
import (
"errors"
"github.com/gin-gonic/gin"
)
const CtxUserIDKey = "userID"
var ErrorUserNotLogin = errors.New("用户未登录")
// getCurrentUser 获取当前登录的用户ID
func getCurrentUser(c *gin.Context) (userID int64, err error) {
uid, ok := c.Get(CtxUserIDKey)
if !ok {
err = ErrorUserNotLogin
return
}
userID, ok = uid.(int64)
if !ok {
err = ErrorUserNotLogin
return
}
return
}
================================================
FILE: lesson23/bluebell/controller/response.go
================================================
package controller
import (
"net/http"
"github.com/gin-gonic/gin"
)
/*
{
"code": 10000, // 程序中的错误码
"msg": xx, // 提示信息
"data": {}, // 数据
}
*/
type ResponseData struct {
Code ResCode `json:"code"`
Msg interface{} `json:"msg"`
Data interface{} `json:"data"`
}
func ResponseError(c *gin.Context, code ResCode) {
c.JSON(http.StatusOK, &ResponseData{
Code: code,
Msg: code.Msg(),
Data: nil,
})
}
func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
c.JSON(http.StatusOK, &ResponseData{
Code: code,
Msg: msg,
Data: nil,
})
}
func ResponseSuccess(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, &ResponseData{
Code: CodeSuccess,
Msg: CodeSuccess.Msg(),
Data: data,
})
}
================================================
FILE: lesson23/bluebell/controller/user.go
================================================
package controller
import (
"bluebell/dao/mysql"
"bluebell/logic"
"bluebell/models"
"errors"
"github.com/go-playground/validator/v10"
"go.uber.org/zap"
"github.com/gin-gonic/gin"
)
// SignUpHandler 处理注册请求的函数
func SignUpHandler(c *gin.Context) {
// 1. 获取参数和参数校验
p := new(models.ParamSignUp)
if err := c.ShouldBindJSON(p); err != nil {
// 请求参数有误,直接返回响应
zap.L().Error("SignUp with invalid param", zap.Error(err))
// 判断err是不是validator.ValidationErrors 类型
errs, ok := err.(validator.ValidationErrors)
if !ok {
ResponseError(c, CodeInvalidParam)
return
}
ResponseErrorWithMsg(c, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
// 2. 业务处理
if err := logic.SignUp(p); err != nil {
zap.L().Error("logic.SignUp failed", zap.Error(err))
if errors.Is(err, mysql.ErrorUserExist) {
ResponseError(c, CodeUserExist)
return
}
ResponseError(c, CodeServerBusy)
return
}
// 3. 返回响应
ResponseSuccess(c, nil)
}
func LoginHandler(c *gin.Context) {
// 1.获取请求参数及参数校验
p := new(models.ParamLogin)
if err := c.ShouldBindJSON(p); err != nil {
// 请求参数有误,直接返回响应
zap.L().Error("Login with invalid param", zap.Error(err))
// 判断err是不是validator.ValidationErrors 类型
errs, ok := err.(validator.ValidationErrors)
if !ok {
ResponseError(c, CodeInvalidParam)
return
}
ResponseErrorWithMsg(c, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
// 2.业务逻辑处理
token, err := logic.Login(p)
if err != nil {
zap.L().Error("logic.Login failed", zap.String("username", p.Username), zap.Error(err))
if errors.Is(err, mysql.ErrorUserNotExist) {
ResponseError(c, CodeUserNotExist)
return
}
ResponseError(c, CodeInvalidPassword)
return
}
// 3.返回响应
ResponseSuccess(c, token)
}
================================================
FILE: lesson23/bluebell/controller/validator.go
================================================
package controller
import (
"bluebell/models"
"fmt"
"reflect"
"strings"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
enTranslations "github.com/go-playground/validator/v10/translations/en"
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)
// 定义一个全局翻译器T
var trans ut.Translator
// InitTrans 初始化翻译器
func InitTrans(locale string) (err error) {
// 修改gin框架中的Validator引擎属性,实现自定制
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
// 注册一个获取json tag的自定义方法
v.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
// 为SignUpParam注册自定义校验方法
v.RegisterStructValidation(SignUpParamStructLevelValidation, models.ParamSignUp{})
zhT := zh.New() // 中文翻译器
enT := en.New() // 英文翻译器
// 第一个参数是备用(fallback)的语言环境
// 后面的参数是应该支持的语言环境(支持多个)
// uni := ut.New(zhT, zhT) 也是可以的
uni := ut.New(enT, zhT, enT)
// locale 通常取决于 http 请求头的 'Accept-Language'
var ok bool
// 也可以使用 uni.FindTranslator(...) 传入多个locale进行查找
trans, ok = uni.GetTranslator(locale)
if !ok {
return fmt.Errorf("uni.GetTranslator(%s) failed", locale)
}
// 注册翻译器
switch locale {
case "en":
err = enTranslations.RegisterDefaultTranslations(v, trans)
case "zh":
err = zhTranslations.RegisterDefaultTranslations(v, trans)
default:
err = enTranslations.RegisterDefaultTranslations(v, trans)
}
return
}
return
}
// removeTopStruct 去除提示信息中的结构体名称
func removeTopStruct(fields map[string]string) map[string]string {
res := map[string]string{}
for field, err := range fields {
res[field[strings.Index(field, ".")+1:]] = err
}
return res
}
// SignUpParamStructLevelValidation 自定义SignUpParam结构体校验函数
func SignUpParamStructLevelValidation(sl validator.StructLevel) {
su := sl.Current().Interface().(models.ParamSignUp)
if su.Password != su.RePassword {
// 输出错误提示信息,最后一个参数就是传递的param
sl.ReportError(su.RePassword, "re_password", "RePassword", "eqfield", "password")
}
}
================================================
FILE: lesson23/bluebell/dao/mysql/community.go
================================================
package mysql
import (
"bluebell/models"
"database/sql"
"go.uber.org/zap"
)
func GetCommunityList() (communityList []*models.Community, err error) {
sqlStr := "select community_id, community_name from community"
if err := db.Select(&communityList, sqlStr); err != nil {
if err == sql.ErrNoRows {
zap.L().Warn("there is no community in db")
err = nil
}
}
return
}
// GetCommunityDetailByID 根据ID查询社区详情
func GetCommunityDetailByID(id int64) (community *models.CommunityDetail, err error) {
community = new(models.CommunityDetail)
sqlStr := `select
community_id, community_name, introduction, create_time
from community
where community_id = ?
`
if err := db.Get(community, sqlStr, id); err != nil {
if err == sql.ErrNoRows {
err = ErrorInvalidID
}
}
return community, err
}
================================================
FILE: lesson23/bluebell/dao/mysql/error_code.go
================================================
package mysql
import "errors"
var (
ErrorUserExist = errors.New("用户已存在")
ErrorUserNotExist = errors.New("用户不存在")
ErrorInvalidPassword = errors.New("用户名或密码错误")
ErrorInvalidID = errors.New("无效的ID")
)
================================================
FILE: lesson23/bluebell/dao/mysql/mysql.go
================================================
package mysql
import (
"bluebell/setting"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
var db *sqlx.DB
// Init 初始化MySQL连接
func Init(cfg *setting.MySQLConfig) (err error) {
// "user:password@tcp(host:port)/dbname"
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=true&loc=Local", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DB)
db, err = sqlx.Connect("mysql", dsn)
if err != nil {
return
}
db.SetMaxOpenConns(cfg.MaxOpenConns)
db.SetMaxIdleConns(cfg.MaxIdleConns)
return
}
// Close 关闭MySQL连接
func Close() {
_ = db.Close()
}
================================================
FILE: lesson23/bluebell/dao/mysql/user.go
================================================
package mysql
import (
"bluebell/models"
"crypto/md5"
"database/sql"
"encoding/hex"
)
// 把每一步数据库操作封装成函数
// 待logic层根据业务需求调用
const secret = "liwenzhou.com"
// CheckUserExist 检查指定用户名的用户是否存在
func CheckUserExist(username string) (err error) {
sqlStr := `select count(user_id) from user where username = ?`
var count int64
if err := db.Get(&count, sqlStr, username); err != nil {
return err
}
if count > 0 {
return ErrorUserExist
}
return
}
// InsertUser 想数据库中插入一条新的用户记录
func InsertUser(user *models.User) (err error) {
// 对密码进行加密
user.Password = encryptPassword(user.Password)
// 执行SQL语句入库
sqlStr := `insert into user(user_id, username, password) values(?,?,?)`
_, err = db.Exec(sqlStr, user.UserID, user.Username, user.Password)
return
}
// encryptPassword 密码加密
func encryptPassword(oPassword string) string {
h := md5.New()
h.Write([]byte(secret))
return hex.EncodeToString(h.Sum([]byte(oPassword)))
}
func Login(user *models.User) (err error) {
oPassword := user.Password // 用户登录的密码
sqlStr := `select user_id, username, password from user where username=?`
err = db.Get(user, sqlStr, user.Username)
if err == sql.ErrNoRows {
return ErrorUserNotExist
}
if err != nil {
// 查询数据库失败
return err
}
// 判断密码是否正确
password := encryptPassword(oPassword)
if password != user.Password {
return ErrorInvalidPassword
}
return
}
================================================
FILE: lesson23/bluebell/dao/redis/redis.go
================================================
package redis
import (
"bluebell/setting"
"fmt"
"github.com/go-redis/redis"
)
var (
client *redis.Client
Nil = redis.Nil
)
// Init 初始化连接
func Init(cfg *setting.RedisConfig) (err error) {
client = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
Password: cfg.Password, // no password set
DB: cfg.DB, // use default DB
PoolSize: cfg.PoolSize,
MinIdleConns: cfg.MinIdleConns,
})
_, err = client.Ping().Result()
if err != nil {
return err
}
return nil
}
func Close() {
_ = client.Close()
}
================================================
FILE: lesson23/bluebell/go.mod
================================================
module bluebell
go 1.14
require (
github.com/bwmarrin/snowflake v0.3.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fsnotify/fsnotify v1.4.9
github.com/gin-gonic/gin v1.6.3
github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0
github.com/go-playground/validator/v10 v10.2.0
github.com/go-redis/redis v6.15.8+incompatible
github.com/go-sql-driver/mysql v1.5.0
github.com/jmoiron/sqlx v1.2.0
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/onsi/ginkgo v1.14.0 // indirect
github.com/sony/sonyflake v1.0.0 // indirect
github.com/spf13/viper v1.7.0
go.uber.org/zap v1.15.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
)
================================================
FILE: lesson23/bluebell/go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
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/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=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
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=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
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/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
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-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=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-redis/redis v6.15.8+incompatible h1:BKZuG6mCnRj5AOaWJXoCgf6rqTYnYJLe4en2hxT7r9o=
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
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.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=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
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/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=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
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/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=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
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 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=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
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=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
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/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/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=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM=
github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
github.com/spf13/viper v1.7.0/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.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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
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/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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-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=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
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-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc h1:NCy3Ohtk6Iny5V/reW2Ktypo4zIpWBdRJ1uFMjBxdg8=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
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=
================================================
FILE: lesson23/bluebell/logger/logger.go
================================================
package logger
import (
"bluebell/setting"
"net"
"net/http"
"net/http/httputil"
"os"
"runtime/debug"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var lg *zap.Logger
// Init 初始化lg
func Init(cfg *setting.LogConfig, mode string) (err error) {
writeSyncer := getLogWriter(cfg.Filename, cfg.MaxSize, cfg.MaxBackups, cfg.MaxAge)
encoder := getEncoder()
var l = new(zapcore.Level)
err = l.UnmarshalText([]byte(cfg.Level))
if err != nil {
return
}
var core zapcore.Core
if mode == "dev" {
// 进入开发模式,日志输出到终端
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
core = zapcore.NewTee(
zapcore.NewCore(encoder, writeSyncer, l),
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), zapcore.DebugLevel),
)
} else {
core = zapcore.NewCore(encoder, writeSyncer, l)
}
lg = zap.New(core, zap.AddCaller())
zap.ReplaceGlobals(lg)
zap.L().Info("init logger success")
return
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.TimeKey = "time"
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
return zapcore.NewJSONEncoder(encoderConfig)
}
func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: filename,
MaxSize: maxSize,
MaxBackups: maxBackup,
MaxAge: maxAge,
}
return zapcore.AddSync(lumberJackLogger)
}
// GinLogger 接收gin框架默认的日志
func GinLogger() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
query := c.Request.URL.RawQuery
c.Next()
cost := time.Since(start)
lg.Info(path,
zap.Int("status", c.Writer.Status()),
zap.String("method", c.Request.Method),
zap.String("path", path),
zap.String("query", query),
zap.String("ip", c.ClientIP()),
zap.String("user-agent", c.Request.UserAgent()),
zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),
zap.Duration("cost", cost),
)
}
}
// GinRecovery recover掉项目可能出现的panic,并使用zap记录相关日志
func GinRecovery(stack bool) gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if err := recover(); err != nil {
// Check for a broken connection, as it is not really a
// condition that warrants a panic stack trace.
var brokenPipe bool
if ne, ok := err.(*net.OpError); ok {
if se, ok := ne.Err.(*os.SyscallError); ok {
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
brokenPipe = true
}
}
}
httpRequest, _ := httputil.DumpRequest(c.Request, false)
if brokenPipe {
lg.Error(c.Request.URL.Path,
zap.Any("error", err),
zap.String("request", string(httpRequest)),
)
// If the connection is dead, we can't write a status to it.
c.Error(err.(error)) // nolint: errcheck
c.Abort()
return
}
if stack {
lg.Error("[Recovery from panic]",
zap.Any("error", err),
zap.String("request", string(httpRequest)),
zap.String("stack", string(debug.Stack())),
)
} else {
lg.Error("[Recovery from panic]",
zap.Any("error", err),
zap.String("request", string(httpRequest)),
)
}
c.AbortWithStatus(http.StatusInternalServerError)
}
}()
c.Next()
}
}
================================================
FILE: lesson23/bluebell/logic/community.go
================================================
package logic
import (
"bluebell/dao/mysql"
"bluebell/models"
)
func GetCommunityList() ([]*models.Community, error) {
// 查数据库 查找到所有的community 并返回
return mysql.GetCommunityList()
}
func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
return mysql.GetCommunityDetailByID(id)
}
================================================
FILE: lesson23/bluebell/logic/user.go
================================================
package logic
import (
"bluebell/dao/mysql"
"bluebell/models"
"bluebell/pkg/jwt"
"bluebell/pkg/snowflake"
)
// 存放业务逻辑的代码
func SignUp(p *models.ParamSignUp) (err error) {
// 1.判断用户存不存在
if err := mysql.CheckUserExist(p.Username); err != nil {
return err
}
// 2.生成UID
userID := snowflake.GenID()
// 构造一个User实例
user := &models.User{
UserID: userID,
Username: p.Username,
Password: p.Password,
}
// 3.保存进数据库
return mysql.InsertUser(user)
}
func Login(p *models.ParamLogin) (token string, err error) {
user := &models.User{
Username: p.Username,
Password: p.Password,
}
// 传递的是指针,就能拿到user.UserID
if err := mysql.Login(user); err != nil {
return "", err
}
// 生成JWT
return jwt.GenToken(user.UserID, user.Username)
}
================================================
FILE: lesson23/bluebell/main.go
================================================
package main
import (
"bluebell/controller"
"bluebell/dao/mysql"
"bluebell/dao/redis"
"bluebell/logger"
"bluebell/pkg/snowflake"
"bluebell/router"
"bluebell/setting"
"fmt"
"os"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("need config file.eg: bluebell config.yaml")
return
}
// 加载配置
if err := setting.Init(os.Args[1]); err != nil {
fmt.Printf("load config failed, err:%v\n", err)
return
}
if err := logger.Init(setting.Conf.LogConfig, setting.Conf.Mode); err != nil {
fmt.Printf("init logger failed, err:%v\n", err)
return
}
if err := mysql.Init(setting.Conf.MySQLConfig); err != nil {
fmt.Printf("init mysql failed, err:%v\n", err)
return
}
defer mysql.Close() // 程序退出关闭数据库连接
if err := redis.Init(setting.Conf.RedisConfig); err != nil {
fmt.Printf("init redis failed, err:%v\n", err)
return
}
defer redis.Close()
if err := snowflake.Init(setting.Conf.StartTime, setting.Conf.MachineID); err != nil {
fmt.Printf("init snowflake failed, err:%v\n", err)
return
}
// 初始化gin框架内置的校验器使用的翻译器
if err := controller.InitTrans("zh"); err != nil {
fmt.Printf("init validator trans failed, err:%v\n", err)
return
}
// 注册路由
r := router.SetupRouter(setting.Conf.Mode)
err := r.Run(fmt.Sprintf(":%d", setting.Conf.Port))
if err != nil {
fmt.Printf("run server failed, err:%v\n", err)
return
}
}
================================================
FILE: lesson23/bluebell/middlewares/auth.go
================================================
package middlewares
import (
"bluebell/controller"
"bluebell/pkg/jwt"
"strings"
"github.com/gin-gonic/gin"
)
// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
return func(c *gin.Context) {
// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
// 这里假设Token放在Header的Authorization中,并使用Bearer开头
// Authorization: Bearer xxxxxxx.xxx.xxx / X-TOKEN: xxx.xxx.xx
// 这里的具体实现方式要依据你的实际业务情况决定
authHeader := c.Request.Header.Get("Authorization")
if authHeader == "" {
controller.ResponseError(c, controller.CodeNeedLogin)
c.Abort()
return
}
// 按空格分割
parts := strings.SplitN(authHeader, " ", 2)
if !(len(parts) == 2 && parts[0] == "Bearer") {
controller.ResponseError(c, controller.CodeInvalidToken)
c.Abort()
return
}
// parts[1]是获取到的tokenString,我们使用之前定义好的解析JWT的函数来解析它
mc, err := jwt.ParseToken(parts[1])
if err != nil {
controller.ResponseError(c, controller.CodeInvalidToken)
c.Abort()
return
}
// 将当前请求的userID信息保存到请求的上下文c上
c.Set(controller.CtxUserIDKey, mc.UserID)
c.Next() // 后续的处理请求的函数中 可以用过c.Get(CtxUserIDKey) 来获取当前请求的用户信息
}
}
================================================
FILE: lesson23/bluebell/models/community.go
================================================
package models
import "time"
type Community struct {
ID int64 `json:"id" db:"community_id"`
Name string `json:"name" db:"community_name"`
}
type CommunityDetail struct {
ID int64 `json:"id" db:"community_id"`
Name string `json:"name" db:"community_name"`
Introduction string `json:"introduction,omitempty" db:"introduction"`
CreateTime time.Time `json:"create_time" db:"create_time"`
}
================================================
FILE: lesson23/bluebell/models/create_table.sql
================================================
--
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL,
`username` varchar(64) COLLATE utf8mb4_general_ci NOT NULL,
`password` varchar(64) COLLATE utf8mb4_general_ci NOT NULL,
`email` varchar(64) COLLATE utf8mb4_general_ci,
`gender` tinyint(4) NOT NULL DEFAULT '0',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`) USING BTREE,
UNIQUE KEY `idx_user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `community`;
CREATE TABLE `community` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`community_id` int(10) unsigned NOT NULL,
`community_name` varchar(128) COLLATE utf8mb4_general_ci NOT NULL,
`introduction` varchar(256) COLLATE utf8mb4_general_ci NOT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_community_id` (`community_id`),
UNIQUE KEY `idx_community_name` (`community_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
INSERT INTO `community` VALUES ('1', '1', 'Go', 'Golang', '2016-11-01 08:10:10', '2016-11-01 08:10:10');
INSERT INTO `community` VALUES ('2', '2', 'leetcode', '刷题刷题刷题', '2020-01-01 08:00:00', '2020-01-01 08:00:00');
INSERT INTO `community` VALUES ('3', '3', 'CS:GO', 'Rush B。。。', '2018-08-07 08:30:00', '2018-08-07 08:30:00');
INSERT INTO `community` VALUES ('4', '4', 'LOL', '欢迎来到英雄联盟!', '2016-01-01 08:00:00', '2016-01-01 08:00:00');
DROP TABLE IF EXISTS `post`;
CREATE TABLE `post` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`post_id` bigint(20) NOT NULL COMMENT '帖子id',
`title` varchar(128) COLLATE utf8mb4_general_ci NOT NULL COMMENT '标题',
`content` varchar(8192) COLLATE utf8mb4_general_ci NOT NULL COMMENT '内容',
`author_id` bigint(20) NOT NULL COMMENT '作者的用户id',
`community_id` bigint(20) NOT NULL COMMENT '所属社区',
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '帖子状态',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_post_id` (`post_id`),
KEY `idx_author_id` (`author_id`),
KEY `idx_community_id` (`community_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
================================================
FILE: lesson23/bluebell/models/params.go
================================================
package models
// 定义请求的参数结构体
// ParamSignUp 注册请求参数
type ParamSignUp struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}
// ParamLogin 登录请求参数
type ParamLogin struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
================================================
FILE: lesson23/bluebell/models/post.go
================================================
package models
import "time"
// 内存对齐概念
type Post struct {
ID int64 `json:"id" db:"post_id"`
AuthorID int64 `json:"author_id" db:"author_id"`
CommunityID int64 `json:"community_id" db:"community_id"`
Status int32 `json:"status" db:"status"`
Title string `json:"title" db:"title"`
Content string `json:"content" db:"content"`
CreateTime time.Time `json:"create_time" db:"create_time"`
}
================================================
FILE: lesson23/bluebell/models/struct_test.go
================================================
package models
import (
"fmt"
"testing"
"unsafe"
)
// Go 内存对齐
type s1 struct {
a int8
b string
c int8
}
type s2 struct {
a int8
c int8
b string
}
func TestStruct(t *testing.T) {
v1 := s1{
a: 1,
b: "七米",
c: 2,
}
v2 := s2{
a: 1,
b: "七米",
c: 2,
}
fmt.Println(unsafe.Sizeof(v1), unsafe.Sizeof(v2))
}
================================================
FILE: lesson23/bluebell/models/user.go
================================================
package models
type User struct {
UserID int64 `db:"user_id"`
Username string `db:"username"`
Password string `db:"password"`
}
================================================
FILE: lesson23/bluebell/pkg/jwt/jwt.go
================================================
package jwt
import (
"errors"
"time"
"github.com/spf13/viper"
"github.com/dgrijalva/jwt-go"
)
var mySecret = []byte("夏天夏天悄悄过去")
// MyClaims 自定义声明结构体并内嵌jwt.StandardClaims
// jwt包自带的jwt.StandardClaims只包含了官方字段
// 我们这里需要额外记录一个username字段,所以要自定义结构体
// 如果想要保存更多信息,都可以添加到这个结构体中
type MyClaims struct {
UserID int64 `json:"user_id"`
Username string `json:"username"`
jwt.StandardClaims
}
// GenToken 生成JWT
func GenToken(userID int64, username string) (string, error) {
// 创建一个我们自己的声明的数据
c := MyClaims{
userID,
"username", // 自定义字段
jwt.StandardClaims{
ExpiresAt: time.Now().Add(
time.Duration(viper.GetInt("auth.jwt_expire")) * time.Hour).Unix(), // 过期时间
Issuer: "bluebell", // 签发人
},
}
// 使用指定的签名方法创建签名对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
// 使用指定的secret签名并获得完整的编码后的字符串token
return token.SignedString(mySecret)
}
// ParseToken 解析JWT
func ParseToken(tokenString string) (*MyClaims, error) {
// 解析token
var mc = new(MyClaims)
token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
return mySecret, nil
})
if err != nil {
return nil, err
}
if token.Valid { // 校验token
return mc, nil
}
return nil, errors.New("invalid token")
}
================================================
FILE: lesson23/bluebell/pkg/snowflake/snowflake.go
================================================
package snowflake
import (
"time"
sf "github.com/bwmarrin/snowflake"
)
var node *sf.Node
func Init(startTime string, machineID int64) (err error) {
var st time.Time
st, err = time.Parse("2006-01-02", startTime)
if err != nil {
return
}
sf.Epoch = st.UnixNano() / 1000000
node, err = sf.NewNode(machineID)
return
}
func GenID() int64 {
return node.Generate().Int64()
}
================================================
FILE: lesson23/bluebell/router/route.go
================================================
package router
import (
"bluebell/controller"
"bluebell/logger"
"bluebell/middlewares"
"net/http"
"github.com/gin-gonic/gin"
)
func SetupRouter(mode string) *gin.Engine {
if mode == gin.ReleaseMode {
gin.SetMode(gin.ReleaseMode) // gin设置成发布模式
}
r := gin.New()
r.Use(logger.GinLogger(), logger.GinRecovery(true))
v1 := r.Group("/api/v1")
// 注册
v1.POST("/signup", controller.SignUpHandler)
// 登录
v1.POST("/login", controller.LoginHandler)
v1.Use(middlewares.JWTAuthMiddleware()) // 应用JWT认证中间件
{
v1.GET("/community", controller.CommunityHandler)
v1.GET("/community/:id", controller.CommunityDetailHandler)
v1.POST("/post", controller.CreatePostHandler)
}
r.NoRoute(func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"msg": "404",
})
})
return r
}
================================================
FILE: lesson23/bluebell/setting/setting.go
================================================
package setting
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
var Conf = new(AppConfig)
type AppConfig struct {
Name string `mapstructure:"name"`
Mode string `mapstructure:"mode"`
Version string `mapstructure:"version"`
StartTime string `mapstructure:"start_time"`
MachineID int64 `mapstructure:"machine_id"`
Port int `mapstructure:"port"`
*LogConfig `mapstructure:"log"`
*MySQLConfig `mapstructure:"mysql"`
*RedisConfig `mapstructure:"redis"`
}
type MySQLConfig struct {
Host string `mapstructure:"host"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
DB string `mapstructure:"dbname"`
Port int `mapstructure:"port"`
MaxOpenConns int `mapstructure:"max_open_conns"`
MaxIdleConns int `mapstructure:"max_idle_conns"`
}
type RedisConfig struct {
Host string `mapstructure:"host"`
Password string `mapstructure:"password"`
Port int `mapstructure:"port"`
DB int `mapstructure:"db"`
PoolSize int `mapstructure:"pool_size"`
MinIdleConns int `mapstructure:"min_idle_conns"`
}
type LogConfig struct {
Level string `mapstructure:"level"`
Filename string `mapstructure:"filename"`
MaxSize int `mapstructure:"max_size"`
MaxAge int `mapstructure:"max_age"`
MaxBackups int `mapstructure:"max_backups"`
}
func Init(filePath string) (err error) {
// 方式1:直接指定配置文件路径(相对路径或者绝对路径)
// 相对路径:相对执行的可执行文件的相对路径
//viper.SetConfigFile("./conf/config.yaml")
// 绝对路径:系统中实际的文件路径
//viper.SetConfigFile("/Users/liwenzhou/Desktop/bluebell/conf/config.yaml")
// 方式2:指定配置文件名和配置文件的位置,viper自行查找可用的配置文件
// 配置文件名不需要带后缀
// 配置文件位置可配置多个
//viper.SetConfigName("config") // 指定配置文件名(不带后缀)
//viper.AddConfigPath(".") // 指定查找配置文件的路径(这里使用相对路径)
//viper.AddConfigPath("./conf") // 指定查找配置文件的路径(这里使用相对路径)
// 基本上是配合远程配置中心使用的,告诉viper当前的数据使用什么格式去解析
//viper.SetConfigType("json")
viper.SetConfigFile(filePath)
err = viper.ReadInConfig() // 读取配置信息
if err != nil {
// 读取配置信息失败
fmt.Printf("viper.ReadInConfig failed, err:%v\n", err)
return
}
// 把读取到的配置信息反序列化到 Conf 变量中
if err := viper.Unmarshal(Conf); err != nil {
fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
}
viper.WatchConfig()
viper.OnConfigChange(func(in fsnotify.Event) {
fmt.Println("配置文件修改了...")
if err := viper.Unmarshal(Conf); err != nil {
fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
}
})
return
}
================================================
FILE: lesson28/bluebell/.air.conf
================================================
# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件
# 工作目录
# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下
root = "."
tmp_dir = "tmp"
[build]
# 只需要写你平常编译使用的shell命令。你也可以使用 `make`
cmd = "go build -o ./tmp/main"
# 由`cmd`命令得到的二进制文件名
bin = "tmp/main"
# 自定义的二进制,可以添加额外的编译标识例如添加 GIN_MODE=release
full_bin = "./tmp/main ./conf/config.yaml"
# 监听以下文件扩展名的文件.
include_ext = ["go", "tpl", "tmpl", "html", "yaml"]
# 忽略这些文件扩展名或目录
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
# 监听以下指定目录的文件
include_dir = []
# 排除以下文件
exclude_file = []
# 如果文件更改过于频繁,则没有必要在每次更改时都触发构建。可以设置触发构建的延迟时间
delay = 1000 # ms
# 发生构建错误时,停止运行旧的二进制文件。
stop_on_error = true
# air的日志文件名,该日志文件放置在你的`tmp_dir`中
log = "air_errors.log"
[log]
# 显示日志时间
time = true
[color]
# 自定义每个部分显示的颜色。如果找不到颜色,使用原始的应用程序日志。
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"
[misc]
# 退出时删除tmp目录
clean_on_exit = true
================================================
FILE: lesson28/bluebell/Makefile
================================================
.PHONY: all build run gotool clean help
BINARY="xx"
all: gotool build
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ${BINARY}
run:
@go run ./main.go conf/config.yaml
gotool:
go fmt ./
go vet ./
clean:
@if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
help:
@echo "make - 格式化 Go 代码, 并编译生成二进制文件"
@echo "make build - 编译 Go 代码, 生成二进制文件"
@echo "make run - 直接运行 Go 代码"
@echo "make clean - 移除二进制文件和 vim swap files"
@echo "make gotool - 运行 Go 工具 'fmt' and 'vet'"
================================================
FILE: lesson28/bluebell/conf/config.yaml
================================================
name: "bluebell"
mode: "dev"
port: 8084
version: "v0.0.1"
start_time: "2020-07-01"
machine_id: 1
auth:
jwt_expire: 8760
log:
level: "debug"
filename: "web_app.log"
max_size: 200
max_age: 30
max_backups: 7
mysql:
host: "127.0.0.1"
port: 13306
user: "root"
password: "root1234"
dbname: "bluebell"
max_open_conns: 200
max_idle_conns: 50
redis:
host: "127.0.0.1"
port: 16379
password: ""
db: 0
pool_size: 100
================================================
FILE: lesson28/bluebell/controller/code.go
================================================
package controller
type ResCode int64
const (
CodeSuccess ResCode = 1000 + iota
CodeInvalidParam
CodeUserExist
CodeUserNotExist
CodeInvalidPassword
CodeServerBusy
CodeNeedLogin
CodeInvalidToken
)
var codeMsgMap = map[ResCode]string{
CodeSuccess: "success",
CodeInvalidParam: "请求参数错误",
CodeUserExist: "用户名已存在",
CodeUserNotExist: "用户名不存在",
CodeInvalidPassword: "用户名或密码错误",
CodeServerBusy: "服务繁忙",
CodeNeedLogin: "需要登录",
CodeInvalidToken: "无效的token",
}
func (c ResCode) Msg() string {
msg, ok := codeMsgMap[c]
if !ok {
msg = codeMsgMap[CodeServerBusy]
}
return msg
}
================================================
FILE: lesson28/bluebell/controller/community.go
================================================
package controller
import (
"bluebell/logic"
"strconv"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// ---- 跟社区相关的 ----
func CommunityHandler(c *gin.Context) {
// 查询到所有的社区(community_id, community_name) 以列表的形式返回
data, err := logic.GetCommunityList()
if err != nil {
zap.L().Error("logic.GetCommunityList() failed", zap.Error(err))
ResponseError(c, CodeServerBusy) // 不轻易把服务端报错暴露给外面
return
}
ResponseSuccess(c, data)
}
// CommunityDetailHandler 社区分类详情
func CommunityDetailHandler(c *gin.Context) {
// 1. 获取社区id
idStr := c.Param("id") // 获取URL参数
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
ResponseError(c, CodeInvalidParam)
return
}
// 2. 根据id获取社区详情
data, err := logic.GetCommunityDetail(id)
if err != nil {
zap.L().Error("logic.GetCommunityList() failed", zap.Error(err))
ResponseError(c, CodeServerBusy) // 不轻易把服务端报错暴露给外面
return
}
ResponseSuccess(c, data)
}
================================================
FILE: lesson28/bluebell/controller/post.go
================================================
package controller
import (
"bluebell/logic"
"bluebell/models"
"strconv"
"go.uber.org/zap"
"github.com/gin-gonic/gin"
)
// CreatePostHandler 创建帖子的处理函数
func CreatePostHandler(c *gin.Context) {
// 1. 获取参数及参数的校验
//c.ShouldBindJSON() // validator --> binding tag
p := new(models.Post)
if err := c.ShouldBindJSON(p); err != nil {
zap.L().Debug("c.ShouldBindJSON(p) error", zap.Any("err", err))
zap.L().Error("create post with invalid param")
ResponseError(c, CodeInvalidParam)
return
}
// 从 c 取到当前发请求的用户的ID
userID, err := getCurrentUserID(c)
if err != nil {
ResponseError(c, CodeNeedLogin)
return
}
p.AuthorID = userID
// 2. 创建帖子
if err := logic.CreatePost(p); err != nil {
zap.L().Error("logic.CreatePost(p) failed", zap.Error(err))
ResponseError(c, CodeServerBusy)
return
}
// 3. 返回响应
ResponseSuccess(c, nil)
}
// GetPostDetailHandler 获取帖子详情的处理函数
func GetPostDetailHandler(c *gin.Context) {
// 1. 获取参数(从URL中获取帖子的id)
pidStr := c.Param("id")
pid, err := strconv.ParseInt(pidStr, 10, 64)
if err != nil {
zap.L().Error("get post detail with invalid param", zap.Error(err))
ResponseError(c, CodeInvalidParam)
return
}
// 2. 根据id取出帖子数据(查数据库)
data, err := logic.GetPostById(pid)
if err != nil {
zap.L().Error("logic.GetPostById(pid) failed", zap.Error(err))
ResponseError(c, CodeServerBusy)
return
}
// 3. 返回响应
ResponseSuccess(c, data)
}
// GetPostListHandler 获取帖子列表的处理函数
func GetPostListHandler(c *gin.Context) {
// 获取分页参数
page, size := getPageInfo(c)
// 获取数据
data, err := logic.GetPostList(page, size)
if err != nil {
zap.L().Error("logic.GetPostList() failed", zap.Error(err))
ResponseError(c, CodeServerBusy)
return
}
ResponseSuccess(c, data)
// 返回响应
}
================================================
FILE: lesson28/bluebell/controller/request.go
================================================
package controller
import (
"errors"
"strconv"
"github.com/gin-gonic/gin"
)
const CtxUserIDKey = "userID"
var ErrorUserNotLogin = errors.New("用户未登录")
// getCurrentUserID 获取当前登录的用户ID
func getCurrentUserID(c *gin.Context) (userID int64, err error) {
uid, ok := c.Get(CtxUserIDKey)
if !ok {
err = ErrorUserNotLogin
return
}
userID, ok = uid.(int64)
if !ok {
err = ErrorUserNotLogin
return
}
return
}
func getPageInfo(c *gin.Context) (int64, int64) {
pageStr := c.Query("page")
sizeStr := c.Query("size")
var (
page int64
size int64
err error
)
page, err = strconv.ParseInt(pageStr, 10, 64)
if err != nil {
page = 1
}
size, err = strconv.ParseInt(sizeStr, 10, 64)
if err != nil {
size = 10
}
return page, size
}
================================================
FILE: lesson28/bluebell/controller/response.go
================================================
package controller
import (
"net/http"
"github.com/gin-gonic/gin"
)
/*
{
"code": 10000, // 程序中的错误码
"msg": xx, // 提示信息
"data": {}, // 数据
}
*/
type ResponseData struct {
Code ResCode `json:"code"`
Msg interface{} `json:"msg"`
Data interface{} `json:"data"`
}
func ResponseError(c *gin.Context, code ResCode) {
c.JSON(http.StatusOK, &ResponseData{
Code: code,
Msg: code.Msg(),
Data: nil,
})
}
func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
c.JSON(http.StatusOK, &ResponseData{
Code: code,
Msg: msg,
Data: nil,
})
}
func ResponseSuccess(c *gin.Context, data interface{}) {
c.JSON(http.StatusOK, &ResponseData{
Code: CodeSuccess,
Msg: CodeSuccess.Msg(),
Data: data,
})
}
================================================
FILE: lesson28/bluebell/controller/user.go
================================================
package controller
import (
"bluebell/dao/mysql"
"bluebell/logic"
"bluebell/models"
"errors"
"github.com/go-playground/validator/v10"
"go.uber.org/zap"
"github.com/gin-gonic/gin"
)
// SignUpHandler 处理注册请求的函数
func SignUpHandler(c *gin.Context) {
// 1. 获取参数和参数校验
p := new(models.ParamSignUp)
if err := c.ShouldBindJSON(p); err != nil {
// 请求参数有误,直接返回响应
zap.L().Error("SignUp with invalid param", zap.Error(err))
// 判断err是不是validator.ValidationErrors 类型
errs, ok := err.(validator.ValidationErrors)
if !ok {
ResponseError(c, CodeInvalidParam)
return
}
ResponseErrorWithMsg(c, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
// 2. 业务处理
if err := logic.SignUp(p); err != nil {
zap.L().Error("logic.SignUp failed", zap.Error(err))
if errors.Is(err, mysql.ErrorUserExist) {
ResponseError(c, CodeUserExist)
return
}
ResponseError(c, CodeServerBusy)
return
}
// 3. 返回响应
ResponseSuccess(c, nil)
}
func LoginHandler(c *gin.Context) {
// 1.获取请求参数及参数校验
p := new(models.ParamLogin)
if err := c.ShouldBindJSON(p); err != nil {
// 请求参数有误,直接返回响应
zap.L().Error("Login with invalid param", zap.Error(err))
// 判断err是不是validator.ValidationErrors 类型
errs, ok := err.(validator.ValidationErrors)
if !ok {
ResponseError(c, CodeInvalidParam)
return
}
ResponseErrorWithMsg(c, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))
return
}
// 2.业务逻辑处理
token, err := logic.Login(p)
if err != nil {
zap.L().Error("logic.Login failed", zap.String("username", p.Username), zap.Error(err))
if errors.Is(err, mysql.ErrorUserNotExist) {
ResponseError(c, CodeUserNotExist)
return
}
ResponseError(c, CodeInvalidPassword)
return
}
// 3.返回响应
ResponseSuccess(c, token)
}
================================================
FILE: lesson28/bluebell/controller/validator.go
================================================
package controller
import (
"bluebell/models"
"fmt"
"reflect"
"strings"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
enTranslations "github.com/go-playground/validator/v10/translations/en"
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
)
// 定义一个全局翻译器T
var trans ut.Translator
// InitTrans 初始化翻译器
func InitTrans(locale string) (err error) {
// 修改gin框架中的Validator引擎属性,实现自定制
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
// 注册一个获取json tag的自定义方法
v.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
// 为SignUpParam注册自定义校验方法
v.RegisterStructValidation(SignUpParamStructLevelValidation, models.ParamSignUp{})
zhT := zh.New() // 中文翻译器
enT := en.New() // 英文翻译器
// 第一个参数是备用(fallback)的语言环境
// 后面的参数是应该支持的语言环境(支持多个)
// uni := ut.New(zhT, zhT) 也是可以的
uni := ut.New(enT, zhT, enT)
// locale 通常取决于 http 请求头的 'Accept-Language'
var ok bool
// 也可以使用 uni.FindTranslator(...) 传入多个locale进行查找
trans, ok = uni.GetTranslator(locale)
if !ok {
return fmt.Errorf("uni.GetTranslator(%s) failed", locale)
}
// 注册翻译器
switch locale {
case "en":
err = enTranslations.RegisterDefaultTranslations(v, trans)
case "zh":
err = zhTranslations.RegisterDefaultTranslations(v, trans)
default:
err = enTranslations.RegisterDefaultTranslations(v, trans)
}
return
}
return
}
// removeTopStruct 去除提示信息中的结构体名称
func removeTopStruct(fields map[string]string) map[string]string {
res := map[string]string{}
for field, err := range fields {
res[field[strings.Index(field, ".")+1:]] = err
}
return res
}
// SignUpParamStructLevelValidation 自定义SignUpParam结构体校验函数
func SignUpParamStructLevelValidation(sl validator.StructLevel) {
su := sl.Current().Interface().(models.ParamSignUp)
if su.Password != su.RePassword {
// 输出错误提示信息,最后一个参数就是传递的param
sl.ReportError(su.RePassword, "re_password", "RePassword", "eqfield", "password")
}
}
================================================
FILE: lesson28/bluebell/dao/mysql/community.go
================================================
package mysql
import (
"bluebell/models"
"database/sql"
"go.uber.org/zap"
)
func GetCommunityList() (communityList []*models.Community, err error) {
sqlStr := "select community_id, community_name from community"
if err := db.Select(&communityList, sqlStr); err != nil {
if err == sql.ErrNoRows {
zap.L().Warn("there is no community in db")
err = nil
}
}
return
}
// GetCommunityDetailByID 根据ID查询社区详情
func GetCommunityDetailByID(id int64) (community *models.CommunityDetail, err error) {
community = new(models.CommunityDetail)
sqlStr := `select
community_id, community_name, introduction, create_time
from community
where community_id = ?
`
if err := db.Get(community, sqlStr, id); err != nil {
if err == sql.ErrNoRows {
err = ErrorInvalidID
}
}
return community, err
}
================================================
FILE: lesson28/bluebell/dao/mysql/error_code.go
================================================
package mysql
import "errors"
var (
ErrorUserExist = errors.New("用户已存在")
ErrorUserNotExist = errors.New("用户不存在")
ErrorInvalidPassword = errors.New("用户名或密码错误")
ErrorInvalidID = errors.New("无效的ID")
)
================================================
FILE: lesson28/bluebell/dao/mysql/mysql.go
================================================
package mysql
import (
"bluebell/setting"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
var db *sqlx.DB
// Init 初始化MySQL连接
func Init(cfg *setting.MySQLConfig) (err error) {
// "user:password@tcp(host:port)/dbname"
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?parseTime=true&loc=Local", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DB)
db, err = sqlx.Connect("mysql", dsn)
if err != nil {
return
}
db.SetMaxOpenConns(cfg.MaxOpenConns)
db.SetMaxIdleConns(cfg.MaxIdleConns)
return
}
// Close 关闭MySQL连接
func Close() {
_ = db.Close()
}
================================================
FILE: lesson28/bluebell/dao/mysql/post.go
================================================
package mysql
import "bluebell/models"
func CreatePost(p *models.Post) (err error) {
sqlStr := `insert into post(
post_id, title, content, author_id, community_id)
values (?, ?, ?, ?, ?)
`
_, err = db.Exec(sqlStr, p.ID, p.Title, p.Content, p.AuthorID, p.CommunityID)
return
}
func GetPostById(pid int64) (post *models.Post, err error) {
post = new(models.Post)
sqlStr := `select
post_id, title, content, author_id, community_id, create_time
from post
where post_id = ?
`
err = db.Get(post, sqlStr, pid)
return
}
func GetPostList(page, size int64) (posts []*models.Post, err error) {
sqlStr := `select
post_id, title, content, author_id, community_id, create_time
from post
limit ?,?
`
posts = make([]*models.Post, 0, 2) // 不要写成make([]*models.Post, 2)
err = db.Select(&posts, sqlStr, (page-1)*size, size)
return
}
================================================
FILE: lesson28/bluebell/dao/mysql/user.go
================================================
package mysql
import (
"bluebell/models"
"crypto/md5"
"database/sql"
"encoding/hex"
)
// 把每一步数据库操作封装成函数
// 待logic层根据业务需求调用
const secret = "liwenzhou.com"
// CheckUserExist 检查指定用户名的用户是否存在
func CheckUserExist(username string) (err error) {
sqlStr := `select count(user_id) from user where username = ?`
var count int64
if err := db.Get(&count, sqlStr, username); err != nil {
return err
}
if count > 0 {
return ErrorUserExist
}
return
}
// InsertUser 想数据库中插入一条新的用户记录
func InsertUser(user *models.User) (err error) {
// 对密码进行加密
user.Password = encryptPassword(user.Password)
// 执行SQL语句入库
sqlStr := `insert into user(user_id, username, password) values(?,?,?)`
_, err = db.Exec(sqlStr, user.UserID, user.Username, user.Password)
return
}
// encryptPassword 密码加密
func encryptPassword(oPassword string) string {
h := md5.New()
h.Write([]byte(secret))
return hex.EncodeToString(h.Sum([]byte(oPassword)))
}
func Login(user *models.User) (err error) {
oPassword := user.Password // 用户登录的密码
sqlStr := `select user_id, username, password from user where username=?`
err = db.Get(user, sqlStr, user.Username)
if err == sql.ErrNoRows {
return ErrorUserNotExist
}
if err != nil {
// 查询数据库失败
return err
}
// 判断密码是否正确
password := encryptPassword(oPassword)
if password != user.Password {
return ErrorInvalidPassword
}
return
}
// GetUserById 根据id获取用户信息
func GetUserById(uid int64) (user *models.User, err error) {
user = new(models.User)
sqlStr := `select user_id, username from user where user_id = ?`
err = db.Get(user, sqlStr, uid)
return
}
================================================
FILE: lesson28/bluebell/dao/redis/redis.go
================================================
package redis
import (
"bluebell/setting"
"fmt"
"github.com/go-redis/redis"
)
var (
client *redis.Client
Nil = redis.Nil
)
// Init 初始化连接
func Init(cfg *setting.RedisConfig) (err error) {
client = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
Password: cfg.Password, // no password set
DB: cfg.DB, // use default DB
PoolSize: cfg.PoolSize,
MinIdleConns: cfg.MinIdleConns,
})
_, err = client.Ping().Result()
if err != nil {
return err
}
return nil
}
func Close() {
_ = client.Close()
}
================================================
FILE: lesson28/bluebell/go.mod
================================================
module bluebell
go 1.14
require (
github.com/bwmarrin/snowflake v0.3.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fsnotify/fsnotify v1.4.9
github.com/gin-gonic/gin v1.6.3
github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0
github.com/go-playground/validator/v10 v10.2.0
github.com/go-redis/redis v6.15.8+incompatible
github.com/go-sql-driver/mysql v1.5.0
github.com/jmoiron/sqlx v1.2.0
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/onsi/ginkgo v1.14.0 // indirect
github.com/sony/sonyflake v1.0.0 // indirect
github.com/spf13/viper v1.7.0
go.uber.org/zap v1.15.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
)
================================================
FILE: lesson28/bluebell/go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
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/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=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
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=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
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/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
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/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
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-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=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-redis/redis v6.15.8+incompatible h1:BKZuG6mCnRj5AOaWJXoCgf6rqTYnYJLe4en2hxT7r9o=
github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
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.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=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
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/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=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
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/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=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
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/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
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 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=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
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=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
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/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/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=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM=
github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
github.com/spf13/viper v1.7.0/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.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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI
gitextract_l4ew9fl9/
├── .gitignore
├── README.md
├── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ └── validator.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── mysql.go
│ │ │ └── user.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ └── user.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── docker_demo/
│ ├── Dockerfile
│ ├── Dockerfile.back
│ ├── go.mod
│ └── main.go
├── flag_demo/
│ ├── args_demo.go
│ ├── flag_demo
│ ├── flag_demo.go
│ └── go.mod
├── gin_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── json_demo/
│ ├── go.mod
│ ├── go.sum
│ ├── index.html
│ ├── json_demo.go
│ └── main.go
├── lesson23/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ └── validator.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ └── user.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ └── user.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson28/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ └── validator.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ └── user.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ └── user.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson35/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── bluebell
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson68/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── bluebell
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson69/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── doc_response_models.go
│ │ ├── post.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson70/
│ └── bluebell/
│ ├── .air.conf
│ ├── Makefile
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── doc_response_models.go
│ │ ├── post.go
│ │ ├── post_test.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ ├── post_test.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ └── auth.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ └── setting/
│ └── setting.go
├── lesson77/
│ └── bluebell/
│ ├── .air.conf
│ ├── Dockerfile
│ ├── Dockerfile.back
│ ├── Makefile
│ ├── bluebell
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── doc_response_models.go
│ │ ├── post.go
│ │ ├── post_test.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ ├── post_test.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── docker-compose.yml
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── init.sql
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ ├── auth.go
│ │ └── ratelimit.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ ├── setting/
│ │ └── setting.go
│ ├── static/
│ │ ├── css/
│ │ │ └── app.6310b918.css
│ │ └── js/
│ │ ├── app.ea0d453e.js
│ │ └── chunk-vendors.57f9e9d6.js
│ ├── templates/
│ │ └── index.html
│ └── wait-for.sh
├── lesson80/
│ └── bluebell/
│ ├── .air.conf
│ ├── .gitignore
│ ├── Dockerfile
│ ├── Dockerfile.back
│ ├── Makefile
│ ├── README.md
│ ├── bin/
│ │ └── .gitkeep
│ ├── conf/
│ │ └── config.yaml
│ ├── controller/
│ │ ├── code.go
│ │ ├── community.go
│ │ ├── doc_response_models.go
│ │ ├── post.go
│ │ ├── post_test.go
│ │ ├── request.go
│ │ ├── response.go
│ │ ├── user.go
│ │ ├── validator.go
│ │ └── vote.go
│ ├── dao/
│ │ ├── mysql/
│ │ │ ├── community.go
│ │ │ ├── error_code.go
│ │ │ ├── mysql.go
│ │ │ ├── post.go
│ │ │ ├── post_test.go
│ │ │ └── user.go
│ │ └── redis/
│ │ ├── keys.go
│ │ ├── post.go
│ │ ├── redis.go
│ │ └── vote.go
│ ├── docker-compose.yml
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── logic/
│ │ ├── community.go
│ │ ├── post.go
│ │ ├── user.go
│ │ └── vote.go
│ ├── main.go
│ ├── middlewares/
│ │ ├── auth.go
│ │ └── ratelimit.go
│ ├── models/
│ │ ├── community.go
│ │ ├── create_table.sql
│ │ ├── params.go
│ │ ├── post.go
│ │ ├── struct_test.go
│ │ └── user.go
│ ├── nginx.conf
│ ├── nginx2.conf
│ ├── pkg/
│ │ ├── jwt/
│ │ │ └── jwt.go
│ │ └── snowflake/
│ │ └── snowflake.go
│ ├── router/
│ │ └── route.go
│ ├── setting/
│ │ └── setting.go
│ ├── sql/
│ │ ├── bluebell_community.sql
│ │ ├── bluebell_post.sql
│ │ ├── bluebell_user.sql
│ │ └── init.sql
│ ├── static/
│ │ ├── css/
│ │ │ └── app.0afe9dae.css
│ │ └── js/
│ │ ├── app.9f3efa6d.js
│ │ └── chunk-vendors.57f9e9d6.js
│ ├── templates/
│ │ └── index.html
│ └── wait-for.sh
├── mysql_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── ratelimit_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── redis_demo/
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── new.go
├── shutdown_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── sqlx_demo/
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── swagger_demo/
│ ├── docs/
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── swagger_demo
├── viper_demo/
│ ├── config.yaml
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── web_app/
│ ├── config.yaml
│ ├── dao/
│ │ ├── mysql/
│ │ │ └── mysql.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── main.go
│ ├── routes/
│ │ └── routes.go
│ ├── settings/
│ │ └── settings.go
│ └── web_app
├── web_app2/
│ ├── config.json
│ ├── config.yaml
│ ├── dao/
│ │ ├── mysql/
│ │ │ └── mysql.go
│ │ └── redis/
│ │ └── redis.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger/
│ │ └── logger.go
│ ├── main.go
│ ├── routes/
│ │ └── routes.go
│ ├── settings/
│ │ └── settings.go
│ └── web_app
└── zap_demo/
├── go.mod
├── go.sum
└── main.go
SYMBOL INDEX (1754 symbols across 320 files)
FILE: bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: bluebell/controller/request.go
constant CtxUserIDKey (line 9) | CtxUserIDKey = "userID"
function getCurrentUser (line 14) | func getCurrentUser(c *gin.Context) (userID int64, err error) {
FILE: bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: bluebell/dao/mysql/user.go
constant secret (line 14) | secret = "liwenzhou.com"
function CheckUserExist (line 23) | func CheckUserExist(username string) (err error) {
function InsertUser (line 36) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 46) | func encryptPassword(oPassword string) string {
function Login (line 52) | func Login(user *models.User) (err error) {
FILE: bluebell/dao/redis/redis.go
function Init (line 16) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 32) | func Close() {
FILE: bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (token string, err error) {
FILE: bluebell/main.go
function main (line 15) | func main() {
FILE: bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
FILE: bluebell/models/params.go
type ParamSignUp (line 6) | type ParamSignUp struct
type ParamLogin (line 13) | type ParamLogin struct
FILE: bluebell/models/user.go
type User (line 3) | type User struct
FILE: bluebell/pkg/jwt/jwt.go
constant TokenExpireDuration (line 10) | TokenExpireDuration = time.Hour * 2
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 42) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: bluebell/router/route.go
function SetupRouter (line 12) | func SetupRouter(mode string) *gin.Engine {
FILE: bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: docker_demo/main.go
function main (line 8) | func main() {
function hello (line 19) | func hello(w http.ResponseWriter, _ *http.Request) {
FILE: flag_demo/args_demo.go
function main (line 10) | func main() {
FILE: flag_demo/flag_demo.go
function main (line 9) | func main() {
FILE: gin_demo/main.go
function func1 (line 9) | func func1(c *gin.Context){
function func2 (line 12) | func func2(c *gin.Context){
function func3 (line 17) | func func3(c *gin.Context){
function func4 (line 21) | func func4(c *gin.Context){
function func5 (line 25) | func func5(c *gin.Context){
function main (line 35) | func main() {
FILE: json_demo/json_demo.go
type MyData (line 9) | type MyData struct
function main (line 27) | func main() {
FILE: json_demo/main.go
type Data (line 13) | type Data struct
function main (line 17) | func main() {
FILE: lesson23/bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: lesson23/bluebell/controller/community.go
function CommunityHandler (line 13) | func CommunityHandler(c *gin.Context) {
function CommunityDetailHandler (line 25) | func CommunityDetailHandler(c *gin.Context) {
FILE: lesson23/bluebell/controller/post.go
function CreatePostHandler (line 5) | func CreatePostHandler(c *gin.Context) {
FILE: lesson23/bluebell/controller/request.go
constant CtxUserIDKey (line 9) | CtxUserIDKey = "userID"
function getCurrentUser (line 14) | func getCurrentUser(c *gin.Context) (userID int64, err error) {
FILE: lesson23/bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: lesson23/bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: lesson23/bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: lesson23/bluebell/dao/mysql/community.go
function GetCommunityList (line 10) | func GetCommunityList() (communityList []*models.Community, err error) {
function GetCommunityDetailByID (line 22) | func GetCommunityDetailByID(id int64) (community *models.CommunityDetail...
FILE: lesson23/bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: lesson23/bluebell/dao/mysql/user.go
constant secret (line 13) | secret = "liwenzhou.com"
function CheckUserExist (line 16) | func CheckUserExist(username string) (err error) {
function InsertUser (line 29) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 39) | func encryptPassword(oPassword string) string {
function Login (line 45) | func Login(user *models.User) (err error) {
FILE: lesson23/bluebell/dao/redis/redis.go
function Init (line 16) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 32) | func Close() {
FILE: lesson23/bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: lesson23/bluebell/logic/community.go
function GetCommunityList (line 8) | func GetCommunityList() ([]*models.Community, error) {
function GetCommunityDetail (line 13) | func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
FILE: lesson23/bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (token string, err error) {
FILE: lesson23/bluebell/main.go
function main (line 15) | func main() {
FILE: lesson23/bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: lesson23/bluebell/models/community.go
type Community (line 5) | type Community struct
type CommunityDetail (line 10) | type CommunityDetail struct
FILE: lesson23/bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
type `community` (line 18) | CREATE TABLE `community` (
type `post` (line 37) | CREATE TABLE `post` (
FILE: lesson23/bluebell/models/params.go
type ParamSignUp (line 6) | type ParamSignUp struct
type ParamLogin (line 13) | type ParamLogin struct
FILE: lesson23/bluebell/models/post.go
type Post (line 7) | type Post struct
FILE: lesson23/bluebell/models/struct_test.go
type s1 (line 11) | type s1 struct
type s2 (line 17) | type s2 struct
function TestStruct (line 23) | func TestStruct(t *testing.T) {
FILE: lesson23/bluebell/models/user.go
type User (line 3) | type User struct
FILE: lesson23/bluebell/pkg/jwt/jwt.go
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 43) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: lesson23/bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: lesson23/bluebell/router/route.go
function SetupRouter (line 12) | func SetupRouter(mode string) *gin.Engine {
FILE: lesson23/bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: lesson28/bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: lesson28/bluebell/controller/community.go
function CommunityHandler (line 13) | func CommunityHandler(c *gin.Context) {
function CommunityDetailHandler (line 25) | func CommunityDetailHandler(c *gin.Context) {
FILE: lesson28/bluebell/controller/post.go
function CreatePostHandler (line 14) | func CreatePostHandler(c *gin.Context) {
function GetPostDetailHandler (line 43) | func GetPostDetailHandler(c *gin.Context) {
function GetPostListHandler (line 65) | func GetPostListHandler(c *gin.Context) {
FILE: lesson28/bluebell/controller/request.go
constant CtxUserIDKey (line 10) | CtxUserIDKey = "userID"
function getCurrentUserID (line 15) | func getCurrentUserID(c *gin.Context) (userID int64, err error) {
function getPageInfo (line 29) | func getPageInfo(c *gin.Context) (int64, int64) {
FILE: lesson28/bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: lesson28/bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: lesson28/bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: lesson28/bluebell/dao/mysql/community.go
function GetCommunityList (line 10) | func GetCommunityList() (communityList []*models.Community, err error) {
function GetCommunityDetailByID (line 22) | func GetCommunityDetailByID(id int64) (community *models.CommunityDetail...
FILE: lesson28/bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: lesson28/bluebell/dao/mysql/post.go
function CreatePost (line 5) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 14) | func GetPostById(pid int64) (post *models.Post, err error) {
function GetPostList (line 25) | func GetPostList(page, size int64) (posts []*models.Post, err error) {
FILE: lesson28/bluebell/dao/mysql/user.go
constant secret (line 13) | secret = "liwenzhou.com"
function CheckUserExist (line 16) | func CheckUserExist(username string) (err error) {
function InsertUser (line 29) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 39) | func encryptPassword(oPassword string) string {
function Login (line 45) | func Login(user *models.User) (err error) {
function GetUserById (line 65) | func GetUserById(uid int64) (user *models.User, err error) {
FILE: lesson28/bluebell/dao/redis/redis.go
function Init (line 16) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 32) | func Close() {
FILE: lesson28/bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: lesson28/bluebell/logic/community.go
function GetCommunityList (line 8) | func GetCommunityList() ([]*models.Community, error) {
function GetCommunityDetail (line 13) | func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
FILE: lesson28/bluebell/logic/post.go
function CreatePost (line 11) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 20) | func GetPostById(pid int64) (data *models.ApiPostDetail, err error) {
function GetPostList (line 55) | func GetPostList(page, size int64) (data []*models.ApiPostDetail, err er...
FILE: lesson28/bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (token string, err error) {
FILE: lesson28/bluebell/main.go
function main (line 15) | func main() {
FILE: lesson28/bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: lesson28/bluebell/models/community.go
type Community (line 5) | type Community struct
type CommunityDetail (line 10) | type CommunityDetail struct
FILE: lesson28/bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
type `community` (line 18) | CREATE TABLE `community` (
type `post` (line 37) | CREATE TABLE `post` (
FILE: lesson28/bluebell/models/params.go
type ParamSignUp (line 6) | type ParamSignUp struct
type ParamLogin (line 13) | type ParamLogin struct
FILE: lesson28/bluebell/models/post.go
type Post (line 7) | type Post struct
type ApiPostDetail (line 18) | type ApiPostDetail struct
FILE: lesson28/bluebell/models/struct_test.go
type s1 (line 11) | type s1 struct
type s2 (line 17) | type s2 struct
function TestStruct (line 23) | func TestStruct(t *testing.T) {
FILE: lesson28/bluebell/models/user.go
type User (line 3) | type User struct
FILE: lesson28/bluebell/pkg/jwt/jwt.go
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 43) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: lesson28/bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: lesson28/bluebell/router/route.go
function SetupRouter (line 12) | func SetupRouter(mode string) *gin.Engine {
FILE: lesson28/bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: lesson35/bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: lesson35/bluebell/controller/community.go
function CommunityHandler (line 13) | func CommunityHandler(c *gin.Context) {
function CommunityDetailHandler (line 25) | func CommunityDetailHandler(c *gin.Context) {
FILE: lesson35/bluebell/controller/post.go
function CreatePostHandler (line 13) | func CreatePostHandler(c *gin.Context) {
function GetPostDetailHandler (line 42) | func GetPostDetailHandler(c *gin.Context) {
function GetPostListHandler (line 64) | func GetPostListHandler(c *gin.Context) {
FILE: lesson35/bluebell/controller/request.go
constant CtxUserIDKey (line 10) | CtxUserIDKey = "userID"
function getCurrentUserID (line 15) | func getCurrentUserID(c *gin.Context) (userID int64, err error) {
function getPageInfo (line 29) | func getPageInfo(c *gin.Context) (int64, int64) {
FILE: lesson35/bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: lesson35/bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: lesson35/bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: lesson35/bluebell/controller/vote.go
function PostVoteController (line 22) | func PostVoteController(c *gin.Context) {
FILE: lesson35/bluebell/dao/mysql/community.go
function GetCommunityList (line 10) | func GetCommunityList() (communityList []*models.Community, err error) {
function GetCommunityDetailByID (line 22) | func GetCommunityDetailByID(id int64) (community *models.CommunityDetail...
FILE: lesson35/bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: lesson35/bluebell/dao/mysql/post.go
function CreatePost (line 5) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 14) | func GetPostById(pid int64) (post *models.Post, err error) {
function GetPostList (line 25) | func GetPostList(page, size int64) (posts []*models.Post, err error) {
FILE: lesson35/bluebell/dao/mysql/user.go
constant secret (line 13) | secret = "liwenzhou.com"
function CheckUserExist (line 16) | func CheckUserExist(username string) (err error) {
function InsertUser (line 29) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 39) | func encryptPassword(oPassword string) string {
function Login (line 45) | func Login(user *models.User) (err error) {
function GetUserById (line 65) | func GetUserById(uid int64) (user *models.User, err error) {
FILE: lesson35/bluebell/dao/redis/keys.go
constant Prefix (line 8) | Prefix = "bluebell:"
constant KeyPostTimeZSet (line 9) | KeyPostTimeZSet = "post:time"
constant KeyPostScoreZSet (line 10) | KeyPostScoreZSet = "post:score"
constant KeyPostVotedZSetPF (line 11) | KeyPostVotedZSetPF = "post:voted:"
function getRedisKey (line 15) | func getRedisKey(key string) string {
FILE: lesson35/bluebell/dao/redis/redis.go
function Init (line 16) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 32) | func Close() {
FILE: lesson35/bluebell/dao/redis/vote.go
constant oneWeekInSeconds (line 35) | oneWeekInSeconds = 7 * 24 * 3600
constant scorePerVote (line 36) | scorePerVote = 432
function CreatePost (line 43) | func CreatePost(postID int64) error {
function VoteForPost (line 60) | func VoteForPost(userID, postID string, value float64) error {
FILE: lesson35/bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: lesson35/bluebell/logic/community.go
function GetCommunityList (line 8) | func GetCommunityList() ([]*models.Community, error) {
function GetCommunityDetail (line 13) | func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
FILE: lesson35/bluebell/logic/post.go
function CreatePost (line 12) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 26) | func GetPostById(pid int64) (data *models.ApiPostDetail, err error) {
function GetPostList (line 61) | func GetPostList(page, size int64) (data []*models.ApiPostDetail, err er...
FILE: lesson35/bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (user *models.User, err error) {
FILE: lesson35/bluebell/logic/vote.go
function VoteForPost (line 35) | func VoteForPost(userID int64, p *models.ParamVoteData) error {
FILE: lesson35/bluebell/main.go
function main (line 15) | func main() {
FILE: lesson35/bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: lesson35/bluebell/models/community.go
type Community (line 5) | type Community struct
type CommunityDetail (line 10) | type CommunityDetail struct
FILE: lesson35/bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
type `community` (line 18) | CREATE TABLE `community` (
type `post` (line 37) | CREATE TABLE `post` (
FILE: lesson35/bluebell/models/params.go
type ParamSignUp (line 6) | type ParamSignUp struct
type ParamLogin (line 13) | type ParamLogin struct
type ParamVoteData (line 19) | type ParamVoteData struct
FILE: lesson35/bluebell/models/post.go
type Post (line 7) | type Post struct
type ApiPostDetail (line 18) | type ApiPostDetail struct
FILE: lesson35/bluebell/models/struct_test.go
type s1 (line 11) | type s1 struct
type s2 (line 17) | type s2 struct
function TestStruct (line 23) | func TestStruct(t *testing.T) {
FILE: lesson35/bluebell/models/user.go
type User (line 3) | type User struct
FILE: lesson35/bluebell/pkg/jwt/jwt.go
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 43) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: lesson35/bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: lesson35/bluebell/router/route.go
function SetupRouter (line 12) | func SetupRouter(mode string) *gin.Engine {
FILE: lesson35/bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: lesson68/bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: lesson68/bluebell/controller/community.go
function CommunityHandler (line 13) | func CommunityHandler(c *gin.Context) {
function CommunityDetailHandler (line 25) | func CommunityDetailHandler(c *gin.Context) {
FILE: lesson68/bluebell/controller/post.go
function CreatePostHandler (line 13) | func CreatePostHandler(c *gin.Context) {
function GetPostDetailHandler (line 42) | func GetPostDetailHandler(c *gin.Context) {
function GetPostListHandler (line 64) | func GetPostListHandler(c *gin.Context) {
function GetPostListHandler2 (line 84) | func GetPostListHandler2(c *gin.Context) {
FILE: lesson68/bluebell/controller/request.go
constant CtxUserIDKey (line 10) | CtxUserIDKey = "userID"
function getCurrentUserID (line 15) | func getCurrentUserID(c *gin.Context) (userID int64, err error) {
function getPageInfo (line 29) | func getPageInfo(c *gin.Context) (int64, int64) {
FILE: lesson68/bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: lesson68/bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: lesson68/bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: lesson68/bluebell/controller/vote.go
function PostVoteController (line 22) | func PostVoteController(c *gin.Context) {
FILE: lesson68/bluebell/dao/mysql/community.go
function GetCommunityList (line 10) | func GetCommunityList() (communityList []*models.Community, err error) {
function GetCommunityDetailByID (line 22) | func GetCommunityDetailByID(id int64) (community *models.CommunityDetail...
FILE: lesson68/bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: lesson68/bluebell/dao/mysql/post.go
function CreatePost (line 11) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 21) | func GetPostById(pid int64) (post *models.Post, err error) {
function GetPostList (line 33) | func GetPostList(page, size int64) (posts []*models.Post, err error) {
function GetPostListByIDs (line 47) | func GetPostListByIDs(ids []string) (postList []*models.Post, err error) {
FILE: lesson68/bluebell/dao/mysql/user.go
constant secret (line 13) | secret = "liwenzhou.com"
function CheckUserExist (line 16) | func CheckUserExist(username string) (err error) {
function InsertUser (line 29) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 39) | func encryptPassword(oPassword string) string {
function Login (line 45) | func Login(user *models.User) (err error) {
function GetUserById (line 65) | func GetUserById(uid int64) (user *models.User, err error) {
FILE: lesson68/bluebell/dao/redis/keys.go
constant Prefix (line 8) | Prefix = "bluebell:"
constant KeyPostTimeZSet (line 9) | KeyPostTimeZSet = "post:time"
constant KeyPostScoreZSet (line 10) | KeyPostScoreZSet = "post:score"
constant KeyPostVotedZSetPF (line 11) | KeyPostVotedZSetPF = "post:voted:"
constant KeyCommunitySetPF (line 13) | KeyCommunitySetPF = "community:"
function getRedisKey (line 17) | func getRedisKey(key string) string {
FILE: lesson68/bluebell/dao/redis/post.go
function getIDsFormKey (line 11) | func getIDsFormKey(key string, page, size int64) ([]string, error) {
function GetPostIDsInOrder (line 18) | func GetPostIDsInOrder(p *models.ParamPostList) ([]string, error) {
function GetPostVoteData (line 30) | func GetPostVoteData(ids []string) (data []int64, err error) {
function GetCommunityPostIDsInOrder (line 57) | func GetCommunityPostIDsInOrder(p *models.ParamCommunityPostList) ([]str...
FILE: lesson68/bluebell/dao/redis/redis.go
function Init (line 16) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 32) | func Close() {
FILE: lesson68/bluebell/dao/redis/vote.go
constant oneWeekInSeconds (line 36) | oneWeekInSeconds = 7 * 24 * 3600
constant scorePerVote (line 37) | scorePerVote = 432
function CreatePost (line 45) | func CreatePost(postID, communityID int64) error {
function VoteForPost (line 65) | func VoteForPost(userID, postID string, value float64) error {
FILE: lesson68/bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: lesson68/bluebell/logic/community.go
function GetCommunityList (line 8) | func GetCommunityList() ([]*models.Community, error) {
function GetCommunityDetail (line 13) | func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
FILE: lesson68/bluebell/logic/post.go
function CreatePost (line 12) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 26) | func GetPostById(pid int64) (data *models.ApiPostDetail, err error) {
function GetPostList (line 61) | func GetPostList(page, size int64) (data []*models.ApiPostDetail, err er...
function GetPostList2 (line 95) | func GetPostList2(p *models.ParamPostList) (data []*models.ApiPostDetail...
function GetCommunityPostList (line 149) | func GetCommunityPostList(p *models.ParamPostList) (data []*models.ApiPo...
function GetPostListNew (line 203) | func GetPostListNew(p *models.ParamPostList) (data []*models.ApiPostDeta...
FILE: lesson68/bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (user *models.User, err error) {
FILE: lesson68/bluebell/logic/vote.go
function VoteForPost (line 35) | func VoteForPost(userID int64, p *models.ParamVoteData) error {
FILE: lesson68/bluebell/main.go
function main (line 15) | func main() {
FILE: lesson68/bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: lesson68/bluebell/models/community.go
type Community (line 5) | type Community struct
type CommunityDetail (line 10) | type CommunityDetail struct
FILE: lesson68/bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
type `community` (line 18) | CREATE TABLE `community` (
type `post` (line 37) | CREATE TABLE `post` (
FILE: lesson68/bluebell/models/params.go
constant OrderTime (line 6) | OrderTime = "time"
constant OrderScore (line 7) | OrderScore = "score"
type ParamSignUp (line 11) | type ParamSignUp struct
type ParamLogin (line 18) | type ParamLogin struct
type ParamVoteData (line 24) | type ParamVoteData struct
type ParamPostList (line 31) | type ParamPostList struct
FILE: lesson68/bluebell/models/post.go
type Post (line 7) | type Post struct
type ApiPostDetail (line 18) | type ApiPostDetail struct
FILE: lesson68/bluebell/models/struct_test.go
type s1 (line 11) | type s1 struct
type s2 (line 17) | type s2 struct
function TestStruct (line 23) | func TestStruct(t *testing.T) {
FILE: lesson68/bluebell/models/user.go
type User (line 3) | type User struct
FILE: lesson68/bluebell/pkg/jwt/jwt.go
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 43) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: lesson68/bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: lesson68/bluebell/router/route.go
function SetupRouter (line 12) | func SetupRouter(mode string) *gin.Engine {
FILE: lesson68/bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: lesson69/bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: lesson69/bluebell/controller/community.go
function CommunityHandler (line 13) | func CommunityHandler(c *gin.Context) {
function CommunityDetailHandler (line 25) | func CommunityDetailHandler(c *gin.Context) {
FILE: lesson69/bluebell/controller/doc_response_models.go
type _ResponsePostList (line 8) | type _ResponsePostList struct
FILE: lesson69/bluebell/controller/post.go
function CreatePostHandler (line 14) | func CreatePostHandler(c *gin.Context) {
function GetPostDetailHandler (line 43) | func GetPostDetailHandler(c *gin.Context) {
function GetPostListHandler (line 65) | func GetPostListHandler(c *gin.Context) {
function GetPostListHandler2 (line 90) | func GetPostListHandler2(c *gin.Context) {
FILE: lesson69/bluebell/controller/request.go
constant CtxUserIDKey (line 10) | CtxUserIDKey = "userID"
function getCurrentUserID (line 15) | func getCurrentUserID(c *gin.Context) (userID int64, err error) {
function getPageInfo (line 29) | func getPageInfo(c *gin.Context) (int64, int64) {
FILE: lesson69/bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: lesson69/bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: lesson69/bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: lesson69/bluebell/controller/vote.go
function PostVoteController (line 22) | func PostVoteController(c *gin.Context) {
FILE: lesson69/bluebell/dao/mysql/community.go
function GetCommunityList (line 10) | func GetCommunityList() (communityList []*models.Community, err error) {
function GetCommunityDetailByID (line 22) | func GetCommunityDetailByID(id int64) (community *models.CommunityDetail...
FILE: lesson69/bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: lesson69/bluebell/dao/mysql/post.go
function CreatePost (line 11) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 21) | func GetPostById(pid int64) (post *models.Post, err error) {
function GetPostList (line 33) | func GetPostList(page, size int64) (posts []*models.Post, err error) {
function GetPostListByIDs (line 47) | func GetPostListByIDs(ids []string) (postList []*models.Post, err error) {
FILE: lesson69/bluebell/dao/mysql/user.go
constant secret (line 13) | secret = "liwenzhou.com"
function CheckUserExist (line 16) | func CheckUserExist(username string) (err error) {
function InsertUser (line 29) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 39) | func encryptPassword(oPassword string) string {
function Login (line 45) | func Login(user *models.User) (err error) {
function GetUserById (line 65) | func GetUserById(uid int64) (user *models.User, err error) {
FILE: lesson69/bluebell/dao/redis/keys.go
constant Prefix (line 8) | Prefix = "bluebell:"
constant KeyPostTimeZSet (line 9) | KeyPostTimeZSet = "post:time"
constant KeyPostScoreZSet (line 10) | KeyPostScoreZSet = "post:score"
constant KeyPostVotedZSetPF (line 11) | KeyPostVotedZSetPF = "post:voted:"
constant KeyCommunitySetPF (line 13) | KeyCommunitySetPF = "community:"
function getRedisKey (line 17) | func getRedisKey(key string) string {
FILE: lesson69/bluebell/dao/redis/post.go
function getIDsFormKey (line 11) | func getIDsFormKey(key string, page, size int64) ([]string, error) {
function GetPostIDsInOrder (line 18) | func GetPostIDsInOrder(p *models.ParamPostList) ([]string, error) {
function GetPostVoteData (line 30) | func GetPostVoteData(ids []string) (data []int64, err error) {
function GetCommunityPostIDsInOrder (line 57) | func GetCommunityPostIDsInOrder(p *models.ParamPostList) ([]string, erro...
FILE: lesson69/bluebell/dao/redis/redis.go
function Init (line 16) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 32) | func Close() {
FILE: lesson69/bluebell/dao/redis/vote.go
constant oneWeekInSeconds (line 36) | oneWeekInSeconds = 7 * 24 * 3600
constant scorePerVote (line 37) | scorePerVote = 432
function CreatePost (line 45) | func CreatePost(postID, communityID int64) error {
function VoteForPost (line 65) | func VoteForPost(userID, postID string, value float64) error {
FILE: lesson69/bluebell/docs/docs.go
type swaggerInfo (line 190) | type swaggerInfo struct
type s (line 209) | type s struct
method ReadDoc (line 211) | func (s *s) ReadDoc() string {
function init (line 233) | func init() {
FILE: lesson69/bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: lesson69/bluebell/logic/community.go
function GetCommunityList (line 8) | func GetCommunityList() ([]*models.Community, error) {
function GetCommunityDetail (line 13) | func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
FILE: lesson69/bluebell/logic/post.go
function CreatePost (line 12) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 26) | func GetPostById(pid int64) (data *models.ApiPostDetail, err error) {
function GetPostList (line 61) | func GetPostList(page, size int64) (data []*models.ApiPostDetail, err er...
function GetPostList2 (line 95) | func GetPostList2(p *models.ParamPostList) (data []*models.ApiPostDetail...
function GetCommunityPostList (line 149) | func GetCommunityPostList(p *models.ParamPostList) (data []*models.ApiPo...
function GetPostListNew (line 203) | func GetPostListNew(p *models.ParamPostList) (data []*models.ApiPostDeta...
FILE: lesson69/bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (user *models.User, err error) {
FILE: lesson69/bluebell/logic/vote.go
function VoteForPost (line 35) | func VoteForPost(userID int64, p *models.ParamVoteData) error {
FILE: lesson69/bluebell/main.go
function main (line 24) | func main() {
FILE: lesson69/bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: lesson69/bluebell/models/community.go
type Community (line 5) | type Community struct
type CommunityDetail (line 10) | type CommunityDetail struct
FILE: lesson69/bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
type `community` (line 18) | CREATE TABLE `community` (
type `post` (line 37) | CREATE TABLE `post` (
FILE: lesson69/bluebell/models/params.go
constant OrderTime (line 6) | OrderTime = "time"
constant OrderScore (line 7) | OrderScore = "score"
type ParamSignUp (line 11) | type ParamSignUp struct
type ParamLogin (line 18) | type ParamLogin struct
type ParamVoteData (line 24) | type ParamVoteData struct
type ParamPostList (line 31) | type ParamPostList struct
FILE: lesson69/bluebell/models/post.go
type Post (line 7) | type Post struct
type ApiPostDetail (line 18) | type ApiPostDetail struct
FILE: lesson69/bluebell/models/struct_test.go
type s1 (line 11) | type s1 struct
type s2 (line 17) | type s2 struct
function TestStruct (line 23) | func TestStruct(t *testing.T) {
FILE: lesson69/bluebell/models/user.go
type User (line 3) | type User struct
FILE: lesson69/bluebell/pkg/jwt/jwt.go
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 43) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: lesson69/bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: lesson69/bluebell/router/route.go
function SetupRouter (line 17) | func SetupRouter(mode string) *gin.Engine {
FILE: lesson69/bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: lesson70/bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: lesson70/bluebell/controller/community.go
function CommunityHandler (line 13) | func CommunityHandler(c *gin.Context) {
function CommunityDetailHandler (line 25) | func CommunityDetailHandler(c *gin.Context) {
FILE: lesson70/bluebell/controller/doc_response_models.go
type _ResponsePostList (line 9) | type _ResponsePostList struct
FILE: lesson70/bluebell/controller/post.go
function CreatePostHandler (line 14) | func CreatePostHandler(c *gin.Context) {
function GetPostDetailHandler (line 43) | func GetPostDetailHandler(c *gin.Context) {
function GetPostListHandler (line 65) | func GetPostListHandler(c *gin.Context) {
function GetPostListHandler2 (line 90) | func GetPostListHandler2(c *gin.Context) {
FILE: lesson70/bluebell/controller/post_test.go
function TestCreatePostHandler (line 14) | func TestCreatePostHandler(t *testing.T) {
FILE: lesson70/bluebell/controller/request.go
constant CtxUserIDKey (line 10) | CtxUserIDKey = "userID"
function getCurrentUserID (line 15) | func getCurrentUserID(c *gin.Context) (userID int64, err error) {
function getPageInfo (line 29) | func getPageInfo(c *gin.Context) (int64, int64) {
FILE: lesson70/bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: lesson70/bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: lesson70/bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: lesson70/bluebell/controller/vote.go
function PostVoteController (line 22) | func PostVoteController(c *gin.Context) {
FILE: lesson70/bluebell/dao/mysql/community.go
function GetCommunityList (line 10) | func GetCommunityList() (communityList []*models.Community, err error) {
function GetCommunityDetailByID (line 22) | func GetCommunityDetailByID(id int64) (community *models.CommunityDetail...
FILE: lesson70/bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: lesson70/bluebell/dao/mysql/post.go
function CreatePost (line 11) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 21) | func GetPostById(pid int64) (post *models.Post, err error) {
function GetPostList (line 33) | func GetPostList(page, size int64) (posts []*models.Post, err error) {
function GetPostListByIDs (line 47) | func GetPostListByIDs(ids []string) (postList []*models.Post, err error) {
FILE: lesson70/bluebell/dao/mysql/post_test.go
function init (line 9) | func init() {
function TestCreatePost (line 25) | func TestCreatePost(t *testing.T) {
FILE: lesson70/bluebell/dao/mysql/user.go
constant secret (line 13) | secret = "liwenzhou.com"
function CheckUserExist (line 16) | func CheckUserExist(username string) (err error) {
function InsertUser (line 29) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 39) | func encryptPassword(oPassword string) string {
function Login (line 45) | func Login(user *models.User) (err error) {
function GetUserById (line 65) | func GetUserById(uid int64) (user *models.User, err error) {
FILE: lesson70/bluebell/dao/redis/keys.go
constant Prefix (line 8) | Prefix = "bluebell:"
constant KeyPostTimeZSet (line 9) | KeyPostTimeZSet = "post:time"
constant KeyPostScoreZSet (line 10) | KeyPostScoreZSet = "post:score"
constant KeyPostVotedZSetPF (line 11) | KeyPostVotedZSetPF = "post:voted:"
constant KeyCommunitySetPF (line 13) | KeyCommunitySetPF = "community:"
function getRedisKey (line 17) | func getRedisKey(key string) string {
FILE: lesson70/bluebell/dao/redis/post.go
function getIDsFormKey (line 11) | func getIDsFormKey(key string, page, size int64) ([]string, error) {
function GetPostIDsInOrder (line 18) | func GetPostIDsInOrder(p *models.ParamPostList) ([]string, error) {
function GetPostVoteData (line 30) | func GetPostVoteData(ids []string) (data []int64, err error) {
function GetCommunityPostIDsInOrder (line 57) | func GetCommunityPostIDsInOrder(p *models.ParamPostList) ([]string, erro...
FILE: lesson70/bluebell/dao/redis/redis.go
function Init (line 16) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 32) | func Close() {
FILE: lesson70/bluebell/dao/redis/vote.go
constant oneWeekInSeconds (line 36) | oneWeekInSeconds = 7 * 24 * 3600
constant scorePerVote (line 37) | scorePerVote = 432
function CreatePost (line 45) | func CreatePost(postID, communityID int64) error {
function VoteForPost (line 65) | func VoteForPost(userID, postID string, value float64) error {
FILE: lesson70/bluebell/docs/docs.go
type swaggerInfo (line 190) | type swaggerInfo struct
type s (line 209) | type s struct
method ReadDoc (line 211) | func (s *s) ReadDoc() string {
function init (line 233) | func init() {
FILE: lesson70/bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: lesson70/bluebell/logic/community.go
function GetCommunityList (line 8) | func GetCommunityList() ([]*models.Community, error) {
function GetCommunityDetail (line 13) | func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
FILE: lesson70/bluebell/logic/post.go
function CreatePost (line 12) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 26) | func GetPostById(pid int64) (data *models.ApiPostDetail, err error) {
function GetPostList (line 61) | func GetPostList(page, size int64) (data []*models.ApiPostDetail, err er...
function GetPostList2 (line 95) | func GetPostList2(p *models.ParamPostList) (data []*models.ApiPostDetail...
function GetCommunityPostList (line 149) | func GetCommunityPostList(p *models.ParamPostList) (data []*models.ApiPo...
function GetPostListNew (line 203) | func GetPostListNew(p *models.ParamPostList) (data []*models.ApiPostDeta...
FILE: lesson70/bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (user *models.User, err error) {
FILE: lesson70/bluebell/logic/vote.go
function VoteForPost (line 35) | func VoteForPost(userID int64, p *models.ParamVoteData) error {
FILE: lesson70/bluebell/main.go
function main (line 24) | func main() {
FILE: lesson70/bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: lesson70/bluebell/models/community.go
type Community (line 5) | type Community struct
type CommunityDetail (line 10) | type CommunityDetail struct
FILE: lesson70/bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
type `community` (line 18) | CREATE TABLE `community` (
type `post` (line 37) | CREATE TABLE `post` (
FILE: lesson70/bluebell/models/params.go
constant OrderTime (line 6) | OrderTime = "time"
constant OrderScore (line 7) | OrderScore = "score"
type ParamSignUp (line 11) | type ParamSignUp struct
type ParamLogin (line 18) | type ParamLogin struct
type ParamVoteData (line 24) | type ParamVoteData struct
type ParamPostList (line 31) | type ParamPostList struct
FILE: lesson70/bluebell/models/post.go
type Post (line 7) | type Post struct
type ApiPostDetail (line 18) | type ApiPostDetail struct
FILE: lesson70/bluebell/models/struct_test.go
type s1 (line 11) | type s1 struct
type s2 (line 17) | type s2 struct
function TestStruct (line 23) | func TestStruct(t *testing.T) {
FILE: lesson70/bluebell/models/user.go
type User (line 3) | type User struct
FILE: lesson70/bluebell/pkg/jwt/jwt.go
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 43) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: lesson70/bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: lesson70/bluebell/router/route.go
function SetupRouter (line 17) | func SetupRouter(mode string) *gin.Engine {
FILE: lesson70/bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: lesson77/bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: lesson77/bluebell/controller/community.go
function CommunityHandler (line 13) | func CommunityHandler(c *gin.Context) {
function CommunityDetailHandler (line 25) | func CommunityDetailHandler(c *gin.Context) {
FILE: lesson77/bluebell/controller/doc_response_models.go
type _ResponsePostList (line 9) | type _ResponsePostList struct
FILE: lesson77/bluebell/controller/post.go
function CreatePostHandler (line 14) | func CreatePostHandler(c *gin.Context) {
function GetPostDetailHandler (line 43) | func GetPostDetailHandler(c *gin.Context) {
function GetPostListHandler (line 65) | func GetPostListHandler(c *gin.Context) {
function GetPostListHandler2 (line 90) | func GetPostListHandler2(c *gin.Context) {
FILE: lesson77/bluebell/controller/post_test.go
function TestCreatePostHandler (line 14) | func TestCreatePostHandler(t *testing.T) {
FILE: lesson77/bluebell/controller/request.go
constant CtxUserIDKey (line 10) | CtxUserIDKey = "userID"
function getCurrentUserID (line 15) | func getCurrentUserID(c *gin.Context) (userID int64, err error) {
function getPageInfo (line 29) | func getPageInfo(c *gin.Context) (int64, int64) {
FILE: lesson77/bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: lesson77/bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: lesson77/bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: lesson77/bluebell/controller/vote.go
function PostVoteController (line 22) | func PostVoteController(c *gin.Context) {
FILE: lesson77/bluebell/dao/mysql/community.go
function GetCommunityList (line 10) | func GetCommunityList() (communityList []*models.Community, err error) {
function GetCommunityDetailByID (line 22) | func GetCommunityDetailByID(id int64) (community *models.CommunityDetail...
FILE: lesson77/bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: lesson77/bluebell/dao/mysql/post.go
function CreatePost (line 11) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 21) | func GetPostById(pid int64) (post *models.Post, err error) {
function GetPostList (line 33) | func GetPostList(page, size int64) (posts []*models.Post, err error) {
function GetPostListByIDs (line 47) | func GetPostListByIDs(ids []string) (postList []*models.Post, err error) {
FILE: lesson77/bluebell/dao/mysql/post_test.go
function init (line 9) | func init() {
function TestCreatePost (line 25) | func TestCreatePost(t *testing.T) {
FILE: lesson77/bluebell/dao/mysql/user.go
constant secret (line 13) | secret = "liwenzhou.com"
function CheckUserExist (line 16) | func CheckUserExist(username string) (err error) {
function InsertUser (line 29) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 39) | func encryptPassword(oPassword string) string {
function Login (line 45) | func Login(user *models.User) (err error) {
function GetUserById (line 65) | func GetUserById(uid int64) (user *models.User, err error) {
FILE: lesson77/bluebell/dao/redis/keys.go
constant Prefix (line 8) | Prefix = "bluebell:"
constant KeyPostTimeZSet (line 9) | KeyPostTimeZSet = "post:time"
constant KeyPostScoreZSet (line 10) | KeyPostScoreZSet = "post:score"
constant KeyPostVotedZSetPF (line 11) | KeyPostVotedZSetPF = "post:voted:"
constant KeyCommunitySetPF (line 13) | KeyCommunitySetPF = "community:"
function getRedisKey (line 17) | func getRedisKey(key string) string {
FILE: lesson77/bluebell/dao/redis/post.go
function getIDsFormKey (line 11) | func getIDsFormKey(key string, page, size int64) ([]string, error) {
function GetPostIDsInOrder (line 18) | func GetPostIDsInOrder(p *models.ParamPostList) ([]string, error) {
function GetPostVoteData (line 30) | func GetPostVoteData(ids []string) (data []int64, err error) {
function GetCommunityPostIDsInOrder (line 57) | func GetCommunityPostIDsInOrder(p *models.ParamPostList) ([]string, erro...
FILE: lesson77/bluebell/dao/redis/redis.go
function Init (line 16) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 32) | func Close() {
FILE: lesson77/bluebell/dao/redis/vote.go
constant oneWeekInSeconds (line 36) | oneWeekInSeconds = 7 * 24 * 3600
constant scorePerVote (line 37) | scorePerVote = 432
function CreatePost (line 45) | func CreatePost(postID, communityID int64) error {
function VoteForPost (line 65) | func VoteForPost(userID, postID string, value float64) error {
FILE: lesson77/bluebell/docs/docs.go
type swaggerInfo (line 194) | type swaggerInfo struct
type s (line 213) | type s struct
method ReadDoc (line 215) | func (s *s) ReadDoc() string {
function init (line 237) | func init() {
FILE: lesson77/bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: lesson77/bluebell/logic/community.go
function GetCommunityList (line 8) | func GetCommunityList() ([]*models.Community, error) {
function GetCommunityDetail (line 13) | func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
FILE: lesson77/bluebell/logic/post.go
function CreatePost (line 12) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 26) | func GetPostById(pid int64) (data *models.ApiPostDetail, err error) {
function GetPostList (line 61) | func GetPostList(page, size int64) (data []*models.ApiPostDetail, err er...
function GetPostList2 (line 95) | func GetPostList2(p *models.ParamPostList) (data []*models.ApiPostDetail...
function GetCommunityPostList (line 149) | func GetCommunityPostList(p *models.ParamPostList) (data []*models.ApiPo...
function GetPostListNew (line 203) | func GetPostListNew(p *models.ParamPostList) (data []*models.ApiPostDeta...
FILE: lesson77/bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (user *models.User, err error) {
FILE: lesson77/bluebell/logic/vote.go
function VoteForPost (line 35) | func VoteForPost(userID int64, p *models.ParamVoteData) error {
FILE: lesson77/bluebell/main.go
function main (line 24) | func main() {
FILE: lesson77/bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: lesson77/bluebell/middlewares/ratelimit.go
function RateLimitMiddleware (line 11) | func RateLimitMiddleware(fillInterval time.Duration, cap int64) func(c *...
FILE: lesson77/bluebell/models/community.go
type Community (line 5) | type Community struct
type CommunityDetail (line 10) | type CommunityDetail struct
FILE: lesson77/bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
type `community` (line 18) | CREATE TABLE `community` (
type `post` (line 37) | CREATE TABLE `post` (
FILE: lesson77/bluebell/models/params.go
constant OrderTime (line 6) | OrderTime = "time"
constant OrderScore (line 7) | OrderScore = "score"
type ParamSignUp (line 11) | type ParamSignUp struct
type ParamLogin (line 18) | type ParamLogin struct
type ParamVoteData (line 24) | type ParamVoteData struct
type ParamPostList (line 31) | type ParamPostList struct
FILE: lesson77/bluebell/models/post.go
type Post (line 7) | type Post struct
type ApiPostDetail (line 18) | type ApiPostDetail struct
FILE: lesson77/bluebell/models/struct_test.go
type s1 (line 11) | type s1 struct
type s2 (line 17) | type s2 struct
function TestStruct (line 23) | func TestStruct(t *testing.T) {
FILE: lesson77/bluebell/models/user.go
type User (line 3) | type User struct
FILE: lesson77/bluebell/pkg/jwt/jwt.go
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 43) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: lesson77/bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: lesson77/bluebell/router/route.go
function SetupRouter (line 18) | func SetupRouter(mode string) *gin.Engine {
FILE: lesson77/bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: lesson77/bluebell/static/js/app.ea0d453e.js
function s (line 1) | function s(s){for(var n,o,c=s[0],r=s[1],l=s[2],m=0,p=[];m<c.length;m++)o...
function e (line 1) | function e(){for(var t,s=0;s<a.length;s++){for(var e=a[s],n=!0,c=1;c<e.l...
function o (line 1) | function o(s){if(n[s])return n[s].exports;var e=n[s]={i:s,l:!1,exports:{...
FILE: lesson77/bluebell/static/js/chunk-vendors.57f9e9d6.js
function c (line 1) | function c(t){this.defaults=t,this.interceptors={request:new i,response:...
function a (line 1) | function a(t,e){!r.isUndefined(t)&&r.isUndefined(t["Content-Type"])&&(t[...
function s (line 1) | function s(){var t;return("undefined"!==typeof XMLHttpRequest||"undefine...
function r (line 1) | function r(t,e,n,r,o,i,a,s){var c,u="function"===typeof t?t.options:t;if...
function r (line 7) | function r(t){return void 0===t||null===t}
function o (line 7) | function o(t){return void 0!==t&&null!==t}
function i (line 7) | function i(t){return!0===t}
function a (line 7) | function a(t){return!1===t}
function s (line 7) | function s(t){return"string"===typeof t||"number"===typeof t||"symbol"==...
function c (line 7) | function c(t){return null!==t&&"object"===typeof t}
function f (line 7) | function f(t){return"[object Object]"===u.call(t)}
function l (line 7) | function l(t){return"[object RegExp]"===u.call(t)}
function p (line 7) | function p(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e...
function d (line 7) | function d(t){return o(t)&&"function"===typeof t.then&&"function"===type...
function h (line 7) | function h(t){return null==t?"":Array.isArray(t)||f(t)&&t.toString===u?J...
function v (line 7) | function v(t){var e=parseFloat(t);return isNaN(e)?t:e}
function y (line 7) | function y(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o<r.len...
function g (line 7) | function g(t,e){if(t.length){var n=t.indexOf(e);if(n>-1)return t.splice(...
function _ (line 7) | function _(t,e){return b.call(t,e)}
function w (line 7) | function w(t){var e=Object.create(null);return function(n){var r=e[n];re...
function j (line 7) | function j(t,e){function n(n){var r=arguments.length;return r?r>1?t.appl...
function S (line 7) | function S(t,e){return t.bind(e)}
function E (line 7) | function E(t,e){e=e||0;var n=t.length-e,r=new Array(n);while(n--)r[n]=t[...
function T (line 7) | function T(t,e){for(var n in e)t[n]=e[n];return t}
function P (line 7) | function P(t){for(var e={},n=0;n<t.length;n++)t[n]&&T(e,t[n]);return e}
function R (line 7) | function R(t,e,n){}
function N (line 7) | function N(t,e){if(t===e)return!0;var n=c(t),r=c(e);if(!n||!r)return!n&&...
function L (line 7) | function L(t,e){for(var n=0;n<t.length;n++)if(N(t[n],e))return n;return-1}
function D (line 7) | function D(t){var e=!1;return function(){e||(e=!0,t.apply(this,arguments...
function V (line 7) | function V(t){var e=(t+"").charCodeAt(0);return 36===e||95===e}
function z (line 7) | function z(t,e,n,r){Object.defineProperty(t,e,{value:n,enumerable:!!r,wr...
function W (line 7) | function W(t){if(!G.test(t)){var e=t.split(".");return function(t){for(v...
function ft (line 7) | function ft(t){return"function"===typeof t&&/native code/.test(t.toStrin...
function t (line 7) | function t(){this.set=Object.create(null)}
function mt (line 7) | function mt(t){yt.push(t),vt.target=t}
function gt (line 7) | function gt(){yt.pop(),vt.target=yt[yt.length-1]}
function xt (line 7) | function xt(t){return new bt(void 0,void 0,void 0,String(t))}
function Ct (line 7) | function Ct(t){var e=new bt(t.tag,t.data,t.children&&t.children.slice(),...
function $t (line 7) | function $t(t){St=t}
function Tt (line 7) | function Tt(t,e){t.__proto__=e}
function Pt (line 7) | function Pt(t,e,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];z(t,i,e[i])}}
function Rt (line 7) | function Rt(t,e){var n;if(c(t)&&!(t instanceof bt))return _(t,"__ob__")&...
function It (line 7) | function It(t,e,n,r,o){var i=new vt,a=Object.getOwnPropertyDescriptor(t,...
function Mt (line 7) | function Mt(t,e,n){if(Array.isArray(t)&&p(e))return t.length=Math.max(t....
function Nt (line 7) | function Nt(t,e){if(Array.isArray(t)&&p(e))t.splice(e,1);else{var n=t.__...
function Lt (line 7) | function Lt(t){for(var e=void 0,n=0,r=t.length;n<r;n++)e=t[n],e&&e.__ob_...
function Ft (line 7) | function Ft(t,e){if(!e)return t;for(var n,r,o,i=pt?Reflect.ownKeys(e):Ob...
function Ut (line 7) | function Ut(t,e,n){return n?function(){var r="function"===typeof e?e.cal...
function Bt (line 7) | function Bt(t,e){var n=e?t?t.concat(e):Array.isArray(e)?e:[e]:t;return n...
function qt (line 7) | function qt(t){for(var e=[],n=0;n<t.length;n++)-1===e.indexOf(t[n])&&e.p...
function Ht (line 7) | function Ht(t,e,n,r){var o=Object.create(t||null);return e?T(o,e):o}
function zt (line 7) | function zt(t,e){var n=t.props;if(n){var r,o,i,a={};if(Array.isArray(n))...
function Gt (line 7) | function Gt(t,e){var n=t.inject;if(n){var r=t.inject={};if(Array.isArray...
function Wt (line 7) | function Wt(t){var e=t.directives;if(e)for(var n in e){var r=e[n];"funct...
function Kt (line 7) | function Kt(t,e,n){if("function"===typeof e&&(e=e.options),zt(e,n),Gt(e,...
function Xt (line 7) | function Xt(t,e,n,r){if("string"===typeof n){var o=t[e];if(_(o,n))return...
function Jt (line 7) | function Jt(t,e,n,r){var o=e[t],i=!_(n,t),a=n[t],s=te(Boolean,o.type);if...
function Yt (line 7) | function Yt(t,e,n){if(_(e,"default")){var r=e.default;return t&&t.$optio...
function Qt (line 7) | function Qt(t){var e=t&&t.toString().match(/^\s*function (\w+)/);return ...
function Zt (line 7) | function Zt(t,e){return Qt(t)===Qt(e)}
function te (line 7) | function te(t,e){if(!Array.isArray(e))return Zt(e,t)?0:-1;for(var n=0,r=...
function ee (line 7) | function ee(t,e,n){mt();try{if(e){var r=e;while(r=r.$parent){var o=r.$op...
function ne (line 7) | function ne(t,e,n,r,o){var i;try{i=n?t.apply(e,n):t.call(e),i&&!i._isVue...
function re (line 7) | function re(t,e,n){if(q.errorHandler)try{return q.errorHandler.call(null...
function oe (line 7) | function oe(t,e,n){if(!J&&!Y||"undefined"===typeof console)throw t;conso...
function ue (line 7) | function ue(){ce=!1;var t=se.slice(0);se.length=0;for(var e=0;e<t.length...
function he (line 7) | function he(t,e){var n;if(se.push((function(){if(t)try{t.call(e)}catch(C...
function ye (line 7) | function ye(t){me(t,ve),ve.clear()}
function me (line 7) | function me(t,e){var n,r,o=Array.isArray(t);if(!(!o&&!c(t)||Object.isFro...
function be (line 7) | function be(t,e){function n(){var t=arguments,r=n.fns;if(!Array.isArray(...
function _e (line 7) | function _e(t,e,n,o,a,s){var c,u,f,l;for(c in t)u=t[c],f=e[c],l=ge(c),r(...
function we (line 7) | function we(t,e,n){var a;t instanceof bt&&(t=t.data.hook||(t.data.hook={...
function xe (line 7) | function xe(t,e,n){var i=e.options.props;if(!r(i)){var a={},s=t.attrs,c=...
function Ce (line 7) | function Ce(t,e,n,r,i){if(o(e)){if(_(e,n))return t[n]=e[n],i||delete e[n...
function Oe (line 7) | function Oe(t){for(var e=0;e<t.length;e++)if(Array.isArray(t[e]))return ...
function Ae (line 7) | function Ae(t){return s(t)?[xt(t)]:Array.isArray(t)?je(t):void 0}
function ke (line 7) | function ke(t){return o(t)&&o(t.text)&&a(t.isComment)}
function je (line 7) | function je(t,e){var n,a,c,u,f=[];for(n=0;n<t.length;n++)a=t[n],r(a)||"b...
function Se (line 7) | function Se(t){var e=t.$options.provide;e&&(t._provided="function"===typ...
function $e (line 7) | function $e(t){var e=Ee(t.$options.inject,t);e&&($t(!1),Object.keys(e).f...
function Ee (line 7) | function Ee(t,e){if(t){for(var n=Object.create(null),r=pt?Reflect.ownKey...
function Te (line 7) | function Te(t,e){if(!t||!t.length)return{};for(var n={},r=0,o=t.length;r...
function Pe (line 7) | function Pe(t){return t.isComment&&!t.asyncFactory||" "===t.text}
function Re (line 7) | function Re(t,e,r){var o,i=Object.keys(e).length>0,a=t?!!t.$stable:!i,s=...
function Ie (line 7) | function Ie(t,e,n){var r=function(){var t=arguments.length?n.apply(null,...
function Me (line 7) | function Me(t,e){return function(){return t[e]}}
function Ne (line 7) | function Ne(t,e){var n,r,i,a,s;if(Array.isArray(t)||"string"===typeof t)...
function Le (line 7) | function Le(t,e,n,r){var o,i=this.$scopedSlots[t];i?(n=n||{},r&&(n=T(T({...
function De (line 7) | function De(t){return Xt(this.$options,"filters",t,!0)||M}
function Fe (line 7) | function Fe(t,e){return Array.isArray(t)?-1===t.indexOf(e):t!==e}
function Ue (line 7) | function Ue(t,e,n,r,o){var i=q.keyCodes[e]||n;return o&&r&&!q.keyCodes[e...
function Be (line 7) | function Be(t,e,n,r,o){if(n)if(c(n)){var i;Array.isArray(n)&&(n=P(n));va...
function qe (line 7) | function qe(t,e){var n=this._staticTrees||(this._staticTrees=[]),r=n[t];...
function He (line 7) | function He(t,e,n){return Ve(t,"__once__"+e+(n?"_"+n:""),!0),t}
function Ve (line 7) | function Ve(t,e,n){if(Array.isArray(t))for(var r=0;r<t.length;r++)t[r]&&...
function ze (line 7) | function ze(t,e,n){t.isStatic=!0,t.key=e,t.isOnce=n}
function Ge (line 7) | function Ge(t,e){if(e)if(f(e)){var n=t.on=t.on?T({},t.on):{};for(var r i...
function We (line 7) | function We(t,e,n,r){e=e||{$stable:!n};for(var o=0;o<t.length;o++){var i...
function Ke (line 7) | function Ke(t,e){for(var n=0;n<e.length;n+=2){var r=e[n];"string"===type...
function Xe (line 7) | function Xe(t,e){return"string"===typeof t?e+t:t}
function Je (line 7) | function Je(t){t._o=He,t._n=v,t._s=h,t._l=Ne,t._t=Le,t._q=N,t._i=L,t._m=...
function Ye (line 7) | function Ye(t,e,r,o,a){var s,c=this,u=a.options;_(o,"_uid")?(s=Object.cr...
function Qe (line 7) | function Qe(t,e,r,i,a){var s=t.options,c={},u=s.props;if(o(u))for(var f ...
function Ze (line 7) | function Ze(t,e,n,r,o){var i=Ct(t);return i.fnContext=n,i.fnOptions=r,e....
function tn (line 7) | function tn(t,e){for(var n in e)t[C(n)]=e[n]}
function rn (line 7) | function rn(t,e,n,a,s){if(!r(t)){var u=n.$options._base;if(c(t)&&(t=u.ex...
function on (line 7) | function on(t,e){var n={_isComponent:!0,_parentVnode:t,parent:e},r=t.dat...
function an (line 7) | function an(t){for(var e=t.hook||(t.hook={}),n=0;n<nn.length;n++){var r=...
function sn (line 7) | function sn(t,e){var n=function(n,r){t(n,r),e(n,r)};return n._merged=!0,n}
function cn (line 7) | function cn(t,e){var n=t.model&&t.model.prop||"value",r=t.model&&t.model...
function ln (line 7) | function ln(t,e,n,r,o,a){return(Array.isArray(n)||s(n))&&(o=r,r=n,n=void...
function pn (line 7) | function pn(t,e,n,r,i){if(o(n)&&o(n.__ob__))return wt();if(o(n)&&o(n.is)...
function dn (line 7) | function dn(t,e,n){if(t.ns=e,"foreignObject"===t.tag&&(e=void 0,n=!0),o(...
function hn (line 7) | function hn(t){c(t.style)&&ye(t.style),c(t.class)&&ye(t.class)}
function vn (line 7) | function vn(t){t._vnode=null,t._staticTrees=null;var e=t.$options,r=t.$v...
function gn (line 7) | function gn(t){Je(t.prototype),t.prototype.$nextTick=function(t){return ...
function bn (line 7) | function bn(t,e){return(t.__esModule||pt&&"Module"===t[Symbol.toStringTa...
function _n (line 7) | function _n(t,e,n,r,o){var i=wt();return i.asyncFactory=t,i.asyncMeta={d...
function wn (line 7) | function wn(t,e){if(i(t.error)&&o(t.errorComp))return t.errorComp;if(o(t...
function xn (line 7) | function xn(t){return t.isComment&&t.asyncFactory}
function Cn (line 7) | function Cn(t){if(Array.isArray(t))for(var e=0;e<t.length;e++){var n=t[e...
function On (line 7) | function On(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t....
function An (line 7) | function An(t,e){yn.$on(t,e)}
function kn (line 7) | function kn(t,e){yn.$off(t,e)}
function jn (line 7) | function jn(t,e){var n=yn;return function r(){var o=e.apply(null,argumen...
function Sn (line 7) | function Sn(t,e,n){yn=t,_e(e,n||{},An,kn,jn,t),yn=void 0}
function $n (line 7) | function $n(t){var e=/^hook:/;t.prototype.$on=function(t,n){var r=this;i...
function Tn (line 7) | function Tn(t){var e=En;return En=t,function(){En=e}}
function Pn (line 7) | function Pn(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){while(n.$o...
function Rn (line 7) | function Rn(t){t.prototype._update=function(t,e){var n=this,r=n.$el,o=n....
function In (line 7) | function In(t,e,n){var r;return t.$el=e,t.$options.render||(t.$options.r...
function Mn (line 7) | function Mn(t,e,r,o,i){var a=o.data.scopedSlots,s=t.$scopedSlots,c=!!(a&...
function Nn (line 7) | function Nn(t){while(t&&(t=t.$parent))if(t._inactive)return!0;return!1}
function Ln (line 7) | function Ln(t,e){if(e){if(t._directInactive=!1,Nn(t))return}else if(t._d...
function Dn (line 7) | function Dn(t,e){if((!e||(t._directInactive=!0,!Nn(t)))&&!t._inactive){t...
function Fn (line 7) | function Fn(t,e){mt();var n=t.$options[e],r=e+" hook";if(n)for(var o=0,i...
function Gn (line 7) | function Gn(){zn=Un.length=Bn.length=0,qn={},Hn=Vn=!1}
function Jn (line 7) | function Jn(){var t,e;for(Wn=Kn(),Vn=!0,Un.sort((function(t,e){return t....
function Yn (line 7) | function Yn(t){var e=t.length;while(e--){var n=t[e],r=n.vm;r._watcher===...
function Qn (line 7) | function Qn(t){t._inactive=!1,Bn.push(t)}
function Zn (line 7) | function Zn(t){for(var e=0;e<t.length;e++)t[e]._inactive=!0,Ln(t[e],!0)}
function tr (line 7) | function tr(t){var e=t.id;if(null==qn[e]){if(qn[e]=!0,Vn){var n=Un.lengt...
function or (line 7) | function or(t,e,n){rr.get=function(){return this[e][n]},rr.set=function(...
function ir (line 7) | function ir(t){t._watchers=[];var e=t.$options;e.props&&ar(t,e.props),e....
function ar (line 7) | function ar(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$optio...
function sr (line 7) | function sr(t){var e=t.$options.data;e=t._data="function"===typeof e?cr(...
function cr (line 7) | function cr(t,e){mt();try{return t.call(e,e)}catch(Ca){return ee(Ca,e,"d...
function fr (line 7) | function fr(t,e){var n=t._computedWatchers=Object.create(null),r=ct();fo...
function lr (line 7) | function lr(t,e,n){var r=!ct();"function"===typeof n?(rr.get=r?pr(e):dr(...
function pr (line 7) | function pr(t){return function(){var e=this._computedWatchers&&this._com...
function dr (line 7) | function dr(t){return function(){return t.call(this,this)}}
function hr (line 7) | function hr(t,e){t.$options.props;for(var n in e)t[n]="function"!==typeo...
function vr (line 7) | function vr(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var ...
function yr (line 7) | function yr(t,e,n,r){return f(n)&&(r=n,n=n.handler),"string"===typeof n&...
function mr (line 7) | function mr(t){var e={get:function(){return this._data}},n={get:function...
function br (line 7) | function br(t){t.prototype._init=function(t){var e=this;e._uid=gr++,e._i...
function _r (line 7) | function _r(t,e){var n=t.$options=Object.create(t.constructor.options),r...
function wr (line 7) | function wr(t){var e=t.options;if(t.super){var n=wr(t.super),r=t.superOp...
function xr (line 7) | function xr(t){var e,n=t.options,r=t.sealedOptions;for(var o in n)n[o]!=...
function Cr (line 7) | function Cr(t){this._init(t)}
function Or (line 7) | function Or(t){t.use=function(t){var e=this._installedPlugins||(this._in...
function Ar (line 7) | function Ar(t){t.mixin=function(t){return this.options=Kt(this.options,t...
function kr (line 7) | function kr(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r...
function jr (line 7) | function jr(t){var e=t.options.props;for(var n in e)or(t.prototype,"_pro...
function Sr (line 7) | function Sr(t){var e=t.options.computed;for(var n in e)lr(t.prototype,n,...
function $r (line 7) | function $r(t){U.forEach((function(e){t[e]=function(t,n){return n?("comp...
function Er (line 7) | function Er(t){return t&&(t.Ctor.options.name||t.tag)}
function Tr (line 7) | function Tr(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"===type...
function Pr (line 7) | function Pr(t,e){var n=t.cache,r=t.keys,o=t._vnode;for(var i in n){var a...
function Rr (line 7) | function Rr(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstanc...
function Lr (line 7) | function Lr(t){var e={get:function(){return q}};Object.defineProperty(t,...
function Xr (line 7) | function Xr(t){var e=t.data,n=t,r=t;while(o(r.componentInstance))r=r.com...
function Jr (line 7) | function Jr(t,e){return{staticClass:Qr(t.staticClass,e.staticClass),clas...
function Yr (line 7) | function Yr(t,e){return o(t)||o(e)?Qr(t,Zr(e)):""}
function Qr (line 7) | function Qr(t,e){return t?e?t+" "+e:t:e||""}
function Zr (line 7) | function Zr(t){return Array.isArray(t)?to(t):c(t)?eo(t):"string"===typeo...
function to (line 7) | function to(t){for(var e,n="",r=0,i=t.length;r<i;r++)o(e=Zr(t[r]))&&""!=...
function eo (line 7) | function eo(t){var e="";for(var n in t)t[n]&&(e&&(e+=" "),e+=n);return e}
function ao (line 7) | function ao(t){return oo(t)?"svg":"math"===t?"math":void 0}
function co (line 7) | function co(t){if(!J)return!0;if(io(t))return!1;if(t=t.toLowerCase(),nul...
function fo (line 7) | function fo(t){if("string"===typeof t){var e=document.querySelector(t);r...
function lo (line 7) | function lo(t,e){var n=document.createElement(t);return"select"!==t||e.d...
function po (line 7) | function po(t,e){return document.createElementNS(no[t],e)}
function ho (line 7) | function ho(t){return document.createTextNode(t)}
function vo (line 7) | function vo(t){return document.createComment(t)}
function yo (line 7) | function yo(t,e,n){t.insertBefore(e,n)}
function mo (line 7) | function mo(t,e){t.removeChild(e)}
function go (line 7) | function go(t,e){t.appendChild(e)}
function bo (line 7) | function bo(t){return t.parentNode}
function _o (line 7) | function _o(t){return t.nextSibling}
function wo (line 7) | function wo(t){return t.tagName}
function xo (line 7) | function xo(t,e){t.textContent=e}
function Co (line 7) | function Co(t,e){t.setAttribute(e,"")}
function ko (line 7) | function ko(t,e){var n=t.data.ref;if(o(n)){var r=t.context,i=t.component...
function $o (line 7) | function $o(t,e){return t.key===e.key&&(t.tag===e.tag&&t.isComment===e.i...
function Eo (line 7) | function Eo(t,e){if("input"!==t.tag)return!0;var n,r=o(n=t.data)&&o(n=n....
function To (line 7) | function To(t,e,n){var r,i,a={};for(r=e;r<=n;++r)i=t[r].key,o(i)&&(a[i]=...
function Po (line 7) | function Po(t){var e,n,a={},c=t.modules,u=t.nodeOps;for(e=0;e<So.length;...
function Io (line 7) | function Io(t,e){(t.data.directives||e.data.directives)&&Mo(t,e)}
function Mo (line 7) | function Mo(t,e){var n,r,o,i=t===jo,a=e===jo,s=Lo(t.data.directives,t.co...
function Lo (line 7) | function Lo(t,e){var n,r,o=Object.create(null);if(!t)return o;for(n=0;n<...
function Do (line 7) | function Do(t){return t.rawName||t.name+"."+Object.keys(t.modifiers||{})...
function Fo (line 7) | function Fo(t,e,n,r,o){var i=t.def&&t.def[e];if(i)try{i(n.elm,t,n,r,o)}c...
function Bo (line 7) | function Bo(t,e){var n=e.componentOptions;if((!o(n)||!1!==n.Ctor.options...
function qo (line 7) | function qo(t,e,n){t.tagName.indexOf("-")>-1?Ho(t,e,n):Vr(e)?Kr(n)?t.rem...
function Ho (line 7) | function Ho(t,e,n){if(Kr(n))t.removeAttribute(e);else{if(tt&&!et&&"TEXTA...
function zo (line 7) | function zo(t,e){var n=e.elm,i=e.data,a=t.data;if(!(r(i.staticClass)&&r(...
function Jo (line 7) | function Jo(t){if(o(t[Ko])){var e=tt?"change":"input";t[e]=[].concat(t[K...
function Yo (line 7) | function Yo(t,e,n){var r=Go;return function o(){var i=e.apply(null,argum...
function Zo (line 7) | function Zo(t,e,n,r){if(Qo){var o=Wn,i=e;e=i._wrapper=function(t){if(t.t...
function ti (line 7) | function ti(t,e,n,r){(r||Go).removeEventListener(t,e._wrapper||e,n)}
function ei (line 7) | function ei(t,e){if(!r(t.data.on)||!r(e.data.on)){var n=e.data.on||{},o=...
function oi (line 7) | function oi(t,e){if(!r(t.data.domProps)||!r(e.data.domProps)){var n,i,a=...
function ii (line 7) | function ii(t,e){return!t.composing&&("OPTION"===t.tagName||ai(t,e)||si(...
function ai (line 7) | function ai(t,e){var n=!0;try{n=document.activeElement!==t}catch(Ca){}re...
function si (line 7) | function si(t,e){var n=t.value,r=t._vModifiers;if(o(r)){if(r.number)retu...
function fi (line 7) | function fi(t){var e=li(t.style);return t.staticStyle?T(t.staticStyle,e):e}
function li (line 7) | function li(t){return Array.isArray(t)?P(t):"string"===typeof t?ui(t):t}
function pi (line 7) | function pi(t,e){var n,r={};if(e){var o=t;while(o.componentInstance)o=o....
function bi (line 7) | function bi(t,e){var n=e.data,i=t.data;if(!(r(n.staticStyle)&&r(n.style)...
function xi (line 7) | function xi(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.s...
function Ci (line 7) | function Ci(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.s...
function Oi (line 7) | function Oi(t){if(t){if("object"===typeof t){var e={};return!1!==t.css&&...
function Ii (line 7) | function Ii(t){Ri((function(){Ri(t)}))}
function Mi (line 7) | function Mi(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n...
function Ni (line 7) | function Ni(t,e){t._transitionClasses&&g(t._transitionClasses,e),Ci(t,e)}
function Li (line 7) | function Li(t,e,n){var r=Fi(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!...
function Fi (line 7) | function Fi(t,e){var n,r=window.getComputedStyle(t),o=(r[$i+"Delay"]||""...
function Ui (line 7) | function Ui(t,e){while(t.length<e.length)t=t.concat(t);return Math.max.a...
function Bi (line 7) | function Bi(t){return 1e3*Number(t.slice(0,-1).replace(",","."))}
function qi (line 7) | function qi(t,e){var n=t.elm;o(n._leaveCb)&&(n._leaveCb.cancelled=!0,n._...
function Hi (line 7) | function Hi(t,e){var n=t.elm;o(n._enterCb)&&(n._enterCb.cancelled=!0,n._...
function Vi (line 7) | function Vi(t){return"number"===typeof t&&!isNaN(t)}
function zi (line 7) | function zi(t){if(r(t))return!1;var e=t.fns;return o(e)?zi(Array.isArray...
function Gi (line 7) | function Gi(t,e){!0!==e.data.show&&qi(e)}
function Qi (line 7) | function Qi(t,e,n){Zi(t,e,n),(tt||nt)&&setTimeout((function(){Zi(t,e,n)}...
function Zi (line 7) | function Zi(t,e,n){var r=e.value,o=t.multiple;if(!o||Array.isArray(r)){f...
function ta (line 7) | function ta(t,e){return e.every((function(e){return!N(e,t)}))}
function ea (line 7) | function ea(t){return"_value"in t?t._value:t.value}
function na (line 7) | function na(t){t.target.composing=!0}
function ra (line 7) | function ra(t){t.target.composing&&(t.target.composing=!1,oa(t.target,"i...
function oa (line 7) | function oa(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,...
function ia (line 7) | function ia(t){return!t.componentInstance||t.data&&t.data.transition?t:i...
function ua (line 7) | function ua(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abst...
function fa (line 7) | function fa(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];...
function la (line 7) | function la(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{...
function pa (line 7) | function pa(t){while(t=t.parent)if(t.data.transition)return!0}
function da (line 7) | function da(t,e){return e.key===t.key&&e.tag===t.tag}
function ba (line 7) | function ba(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._ent...
function _a (line 7) | function _a(t){t.data.newPos=t.elm.getBoundingClientRect()}
function wa (line 7) | function wa(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-...
function n (line 13) | function n(t){var e=Number(t.version.split(".")[0]);if(e>=2)t.mixin({bef...
function i (line 13) | function i(t){o&&(t._devtoolHook=o,o.emit("vuex:init",t),o.on("vuex:trav...
function a (line 13) | function a(t,e){Object.keys(t).forEach((function(n){return e(t[n],n)}))}
function s (line 13) | function s(t){return null!==t&&"object"===typeof t}
function c (line 13) | function c(t){return t&&"function"===typeof t.then}
function u (line 13) | function u(t,e){return function(){return t(e)}}
function d (line 13) | function d(t,e,n){if(e.update(n),n.modules)for(var r in n.modules){if(!e...
function m (line 13) | function m(t,e){return e.indexOf(t)<0&&e.push(t),function(){var n=e.inde...
function g (line 13) | function g(t,e){t._actions=Object.create(null),t._mutations=Object.creat...
function b (line 13) | function b(t,e,n){var r=t._vm;t.getters={},t._makeLocalGettersCache=Obje...
function _ (line 13) | function _(t,e,n,r,o){var i=!n.length,a=t._modules.getNamespace(n);if(r....
function w (line 13) | function w(t,e,n){var r=""===e,o={dispatch:r?t.dispatch:function(n,r,o){...
function x (line 13) | function x(t,e){if(!t._makeLocalGettersCache[e]){var n={},r=e.length;Obj...
function C (line 13) | function C(t,e,n,r){var o=t._mutations[e]||(t._mutations[e]=[]);o.push((...
function O (line 13) | function O(t,e,n,r){var o=t._actions[e]||(t._actions[e]=[]);o.push((func...
function A (line 13) | function A(t,e,n,r){t._wrappedGetters[e]||(t._wrappedGetters[e]=function...
function k (line 13) | function k(t){t._vm.$watch((function(){return this._data.$$state}),(func...
function j (line 13) | function j(t,e){return e.reduce((function(t,e){return t[e]}),t)}
function S (line 13) | function S(t,e,n){return s(t)&&t.type&&(n=e,e=t,t=t.type),{type:t,payloa...
function $ (line 13) | function $(t){h&&t===h||(h=t,n(h))}
function M (line 13) | function M(t){return N(t)?Array.isArray(t)?t.map((function(t){return{key...
function N (line 13) | function N(t){return Array.isArray(t)||s(t)}
function L (line 13) | function L(t){return function(e,n){return"string"!==typeof e?(n=e,e=""):...
function D (line 13) | function D(t,e,n){var r=t._modulesNamespaceMap[n];return r}
function o (line 13) | function o(t){return encodeURIComponent(t).replace(/%40/gi,"@").replace(...
function o (line 13) | function o(t){var r=t;return e&&(n.setAttribute("href",r),r=n.href),n.se...
function s (line 13) | function s(t){t.cancelToken&&t.cancelToken.throwIfRequested()}
function r (line 13) | function r(t){this.message=t}
function r (line 18) | function r(t,e){0}
function o (line 18) | function o(t){return Object.prototype.toString.call(t).indexOf("Error")>-1}
function i (line 18) | function i(t,e){return e instanceof t||e&&(e.name===t.name||e._name===t....
function a (line 18) | function a(t,e){for(var n in e)t[n]=e[n];return t}
function c (line 18) | function c(t,e,n,r){var o=e.props=u(n,r);if(o){o=e.props=a({},o);var i=e...
function u (line 18) | function u(t,e){switch(typeof e){case"undefined":return;case"object":ret...
function v (line 18) | function v(t,e,n){void 0===e&&(e={});var r,o=n||y;try{r=o(t||"")}catch(a...
function y (line 18) | function y(t){var e={};return t=t.trim().replace(/^(\?|#|&)/,""),t?(t.sp...
function m (line 18) | function m(t){var e=t?Object.keys(t).map((function(e){var n=t[e];if(void...
function b (line 18) | function b(t,e,n,r){var o=r&&r.options.stringifyQuery,i=e.query||{};try{...
function _ (line 18) | function _(t){if(Array.isArray(t))return t.map(_);if(t&&"object"===typeo...
function x (line 18) | function x(t){var e=[];while(t)e.unshift(t),t=t.parent;return e}
function C (line 18) | function C(t,e){var n=t.path,r=t.query;void 0===r&&(r={});var o=t.hash;v...
function O (line 18) | function O(t,e){return e===w?t===e:!!e&&(t.path&&e.path?t.path.replace(g...
function A (line 18) | function A(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t...
function k (line 18) | function k(t,e){return 0===t.path.replace(g,"/").indexOf(e.path.replace(...
function j (line 18) | function j(t,e){for(var n in e)if(!(n in t))return!1;return!0}
function S (line 18) | function S(t,e,n){var r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"=...
function $ (line 18) | function $(t){var e="",n="",r=t.indexOf("#");r>=0&&(e=t.slice(r),t=t.sli...
function E (line 18) | function E(t){return t.replace(/\/\//g,"/")}
function D (line 18) | function D(t,e){var n,r=[],o=0,i=0,a="",s=e&&e.delimiter||"/";while(null...
function F (line 18) | function F(t,e){return q(D(t,e))}
function U (line 18) | function U(t){return encodeURI(t).replace(/[\/?#]/g,(function(t){return"...
function B (line 18) | function B(t){return encodeURI(t).replace(/[?#]/g,(function(t){return"%"...
function q (line 18) | function q(t){for(var e=new Array(t.length),n=0;n<t.length;n++)"object"=...
function H (line 18) | function H(t){return t.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}
function V (line 18) | function V(t){return t.replace(/([=!:$\/()])/g,"\\$1")}
function z (line 18) | function z(t,e){return t.keys=e,t}
function G (line 18) | function G(t){return t.sensitive?"":"i"}
function W (line 18) | function W(t,e){var n=t.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.l...
function K (line 18) | function K(t,e,n){for(var r=[],o=0;o<t.length;o++)r.push(Y(t[o],e,n).sou...
function X (line 18) | function X(t,e,n){return J(D(t,n),e,n)}
function J (line 18) | function J(t,e,n){T(e)||(n=e||n,e=[]),n=n||{};for(var r=n.strict,o=!1!==...
function Y (line 18) | function Y(t,e,n){return T(e)||(n=e||n,e=[]),n=n||{},t instanceof RegExp...
function Z (line 18) | function Z(t,e,n){e=e||{};try{var r=Q[t]||(Q[t]=P.compile(t));return"str...
function tt (line 18) | function tt(t,e,n,r){var o="string"===typeof t?{path:t}:t;if(o._normaliz...
function at (line 18) | function at(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)&&!t.defa...
function st (line 18) | function st(t){if(t)for(var e,n=0;n<t.length;n++){if(e=t[n],"a"===e.tag)...
function ct (line 18) | function ct(t){if(!ct.installed||et!==t){ct.installed=!0,et=t;var e=func...
function ft (line 18) | function ft(t,e,n,r){var o=e||[],i=n||Object.create(null),a=r||Object.cr...
function lt (line 18) | function lt(t,e,n,r,o,i){var a=r.path,s=r.name;var c=r.pathToRegexpOptio...
function pt (line 18) | function pt(t,e){var n=P(t,[],e);return n}
function dt (line 18) | function dt(t,e,n){return n||(t=t.replace(/\/$/,"")),"/"===t[0]||null==e...
function ht (line 18) | function ht(t,e){var n=ft(t),r=n.pathList,o=n.pathMap,i=n.nameMap;functi...
function vt (line 18) | function vt(t,e,n){var r=e.match(t);if(!r)return!1;if(!n)return!0;for(va...
function yt (line 18) | function yt(t,e){return S(t,e.parent?e.parent.path:"/",!0)}
function gt (line 18) | function gt(){return mt.now().toFixed(3)}
function _t (line 18) | function _t(){return bt}
function wt (line 18) | function wt(t){return bt=t}
function Ct (line 18) | function Ct(){var t=window.location.protocol+"//"+window.location.host,e...
function Ot (line 18) | function Ot(t,e,n,r){if(t.app){var o=t.options.scrollBehavior;o&&t.app.$...
function At (line 18) | function At(){var t=_t();t&&(xt[t]={x:window.pageXOffset,y:window.pageYO...
function kt (line 18) | function kt(){var t=_t();if(t)return xt[t]}
function jt (line 18) | function jt(t,e){var n=document.documentElement,r=n.getBoundingClientRec...
function St (line 18) | function St(t){return Tt(t.x)||Tt(t.y)}
function $t (line 18) | function $t(t){return{x:Tt(t.x)?t.x:window.pageXOffset,y:Tt(t.y)?t.y:win...
function Et (line 18) | function Et(t){return{x:Tt(t.x)?t.x:0,y:Tt(t.y)?t.y:0}}
function Tt (line 18) | function Tt(t){return"number"===typeof t}
function Rt (line 18) | function Rt(t,e){var n="object"===typeof t;if(n&&"string"===typeof t.sel...
function Mt (line 18) | function Mt(t,e){At();var n=window.history;try{if(e){var r=a({},n.state)...
function Nt (line 18) | function Nt(t){Mt(t,!0)}
function Lt (line 18) | function Lt(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(functi...
function Dt (line 18) | function Dt(t){return function(e,n,r){var i=!1,a=0,s=null;Ft(t,(function...
function Ft (line 18) | function Ft(t,e){return Ut(t.map((function(t){return Object.keys(t.compo...
function Ut (line 18) | function Ut(t){return Array.prototype.concat.apply([],t)}
function qt (line 18) | function qt(t){return t.__esModule||Bt&&"Module"===t[Symbol.toStringTag]}
function Ht (line 18) | function Ht(t){var e=!1;return function(){var n=[],r=arguments.length;wh...
function e (line 18) | function e(e){t.call(this),this.name=this._name="NavigationDuplicated",t...
function Gt (line 18) | function Gt(t){if(!t)if(ut){var e=document.querySelector("base");t=e&&e....
function Wt (line 18) | function Wt(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n<r;n++)if(...
function Kt (line 18) | function Kt(t,e,n,r){var o=Ft(t,(function(t,r,o,i){var a=Xt(t,e);if(a)re...
function Xt (line 18) | function Xt(t,e){return"function"!==typeof t&&(t=et.extend(t)),t.options...
function Jt (line 18) | function Jt(t){return Kt(t,"beforeRouteLeave",Qt,!0)}
function Yt (line 18) | function Yt(t){return Kt(t,"beforeRouteUpdate",Qt)}
function Qt (line 18) | function Qt(t,e){if(e)return function(){return t.apply(e,arguments)}}
function Zt (line 18) | function Zt(t,e,n){return Kt(t,"beforeRouteEnter",(function(t,r,o,i){ret...
function te (line 18) | function te(t,e,n,r,o){return function(i,a,s){return t(i,a,(function(t){...
function ee (line 18) | function ee(t,e,n,r){e[n]&&!e[n]._isBeingDestroyed?t(e[n]):r()&&setTimeo...
function e (line 18) | function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavi...
function re (line 18) | function re(t){var e=decodeURI(window.location.pathname);return t&&0===e...
function e (line 18) | function e(e,n,r){t.call(this,e,n),r&&ie(this.base)||ae()}
function ie (line 18) | function ie(t){var e=re(t);if(!/^\/#/.test(e))return window.location.rep...
function ae (line 18) | function ae(){var t=se();return"/"===t.charAt(0)||(fe("/"+t),!1)}
function se (line 18) | function se(){var t=window.location.href,e=t.indexOf("#");if(e<0)return"...
function ce (line 18) | function ce(t){var e=window.location.href,n=e.indexOf("#"),r=n>=0?e.slic...
function ue (line 18) | function ue(t){It?Mt(ce(t)):window.location.hash=t}
function fe (line 18) | function fe(t){It?Nt(ce(t)):window.location.replace(ce(t))}
function e (line 18) | function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}
function he (line 18) | function he(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t....
function ve (line 18) | function ve(t,e,n){var r="hash"===n?"#"+e:e;return t?E(t+"/"+r):r}
function o (line 18) | function o(t){if("function"!==typeof t)throw new TypeError("executor mus...
function i (line 18) | function i(t){return"[object Array]"===o.call(t)}
function a (line 18) | function a(t){return"undefined"===typeof t}
function s (line 18) | function s(t){return null!==t&&!a(t)&&null!==t.constructor&&!a(t.constru...
function c (line 18) | function c(t){return"[object ArrayBuffer]"===o.call(t)}
function u (line 18) | function u(t){return"undefined"!==typeof FormData&&t instanceof FormData}
function f (line 18) | function f(t){var e;return e="undefined"!==typeof ArrayBuffer&&ArrayBuff...
function l (line 18) | function l(t){return"string"===typeof t}
function p (line 18) | function p(t){return"number"===typeof t}
function d (line 18) | function d(t){return null!==t&&"object"===typeof t}
function h (line 18) | function h(t){return"[object Date]"===o.call(t)}
function v (line 18) | function v(t){return"[object File]"===o.call(t)}
function y (line 18) | function y(t){return"[object Blob]"===o.call(t)}
function m (line 18) | function m(t){return"[object Function]"===o.call(t)}
function g (line 18) | function g(t){return d(t)&&m(t.pipe)}
function b (line 18) | function b(t){return"undefined"!==typeof URLSearchParams&&t instanceof U...
function _ (line 18) | function _(t){return t.replace(/^\s*/,"").replace(/\s*$/,"")}
function w (line 18) | function w(){return("undefined"===typeof navigator||"ReactNative"!==navi...
function x (line 18) | function x(t,e){if(null!==t&&"undefined"!==typeof t)if("object"!==typeof...
function C (line 18) | function C(){var t={};function e(e,n){"object"===typeof t[n]&&"object"==...
function O (line 18) | function O(){var t={};function e(e,n){"object"===typeof t[n]&&"object"==...
function A (line 18) | function A(t,e,n){return x(e,(function(e,o){t[o]=n&&"function"===typeof ...
function c (line 18) | function c(t){var e=new i(t),n=o(i.prototype.request,e);return r.extend(...
function n (line 18) | function n(t,e){for(var n=0,r=t.length-1;r>=0;r--){var o=t[r];"."===o?t....
function r (line 18) | function r(t){"string"!==typeof t&&(t+="");var e,n=0,r=-1,o=!0;for(e=t.l...
function o (line 18) | function o(t,e){if(t.filter)return t.filter(e);for(var n=[],r=0;r<t.leng...
function r (line 18) | function r(t){for(var e=0;e<t.length;e++)if(""!==t[e])break;for(var n=t....
function t (line 18) | function t(){}
function o (line 18) | function o(){this.handlers=[]}
FILE: lesson80/bluebell/controller/code.go
type ResCode (line 3) | type ResCode
method Msg (line 29) | func (c ResCode) Msg() string {
constant CodeSuccess (line 6) | CodeSuccess ResCode = 1000 + iota
constant CodeInvalidParam (line 7) | CodeInvalidParam
constant CodeUserExist (line 8) | CodeUserExist
constant CodeUserNotExist (line 9) | CodeUserNotExist
constant CodeInvalidPassword (line 10) | CodeInvalidPassword
constant CodeServerBusy (line 11) | CodeServerBusy
constant CodeNeedLogin (line 13) | CodeNeedLogin
constant CodeInvalidToken (line 14) | CodeInvalidToken
FILE: lesson80/bluebell/controller/community.go
function CommunityHandler (line 13) | func CommunityHandler(c *gin.Context) {
function CommunityDetailHandler (line 25) | func CommunityDetailHandler(c *gin.Context) {
FILE: lesson80/bluebell/controller/doc_response_models.go
type _ResponsePostList (line 9) | type _ResponsePostList struct
FILE: lesson80/bluebell/controller/post.go
function CreatePostHandler (line 14) | func CreatePostHandler(c *gin.Context) {
function GetPostDetailHandler (line 43) | func GetPostDetailHandler(c *gin.Context) {
function GetPostListHandler (line 65) | func GetPostListHandler(c *gin.Context) {
function GetPostListHandler2 (line 90) | func GetPostListHandler2(c *gin.Context) {
FILE: lesson80/bluebell/controller/post_test.go
function TestCreatePostHandler (line 14) | func TestCreatePostHandler(t *testing.T) {
FILE: lesson80/bluebell/controller/request.go
constant CtxUserIDKey (line 10) | CtxUserIDKey = "userID"
function getCurrentUserID (line 15) | func getCurrentUserID(c *gin.Context) (userID int64, err error) {
function getPageInfo (line 29) | func getPageInfo(c *gin.Context) (int64, int64) {
FILE: lesson80/bluebell/controller/response.go
type ResponseData (line 18) | type ResponseData struct
function ResponseError (line 24) | func ResponseError(c *gin.Context, code ResCode) {
function ResponseErrorWithMsg (line 32) | func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {
function ResponseSuccess (line 40) | func ResponseSuccess(c *gin.Context, data interface{}) {
FILE: lesson80/bluebell/controller/user.go
function SignUpHandler (line 17) | func SignUpHandler(c *gin.Context) {
function LoginHandler (line 46) | func LoginHandler(c *gin.Context) {
FILE: lesson80/bluebell/controller/validator.go
function InitTrans (line 22) | func InitTrans(locale string) (err error) {
function removeTopStruct (line 69) | func removeTopStruct(fields map[string]string) map[string]string {
function SignUpParamStructLevelValidation (line 78) | func SignUpParamStructLevelValidation(sl validator.StructLevel) {
FILE: lesson80/bluebell/controller/vote.go
function PostVoteController (line 22) | func PostVoteController(c *gin.Context) {
FILE: lesson80/bluebell/dao/mysql/community.go
function GetCommunityList (line 10) | func GetCommunityList() (communityList []*models.Community, err error) {
function GetCommunityDetailByID (line 22) | func GetCommunityDetailByID(id int64) (community *models.CommunityDetail...
FILE: lesson80/bluebell/dao/mysql/mysql.go
function Init (line 14) | func Init(cfg *setting.MySQLConfig) (err error) {
function Close (line 27) | func Close() {
FILE: lesson80/bluebell/dao/mysql/post.go
function CreatePost (line 11) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 21) | func GetPostById(pid int64) (post *models.Post, err error) {
function GetPostList (line 33) | func GetPostList(page, size int64) (posts []*models.Post, err error) {
function GetPostListByIDs (line 47) | func GetPostListByIDs(ids []string) (postList []*models.Post, err error) {
FILE: lesson80/bluebell/dao/mysql/post_test.go
function init (line 9) | func init() {
function TestCreatePost (line 25) | func TestCreatePost(t *testing.T) {
FILE: lesson80/bluebell/dao/mysql/user.go
constant secret (line 13) | secret = "liwenzhou.com"
function CheckUserExist (line 16) | func CheckUserExist(username string) (err error) {
function InsertUser (line 29) | func InsertUser(user *models.User) (err error) {
function encryptPassword (line 39) | func encryptPassword(oPassword string) string {
function Login (line 46) | func Login(user *models.User) (err error) {
function GetUserById (line 66) | func GetUserById(uid int64) (user *models.User, err error) {
FILE: lesson80/bluebell/dao/redis/keys.go
constant Prefix (line 8) | Prefix = "bluebell:"
constant KeyPostTimeZSet (line 9) | KeyPostTimeZSet = "post:time"
constant KeyPostScoreZSet (line 10) | KeyPostScoreZSet = "post:score"
constant KeyPostVotedZSetPF (line 11) | KeyPostVotedZSetPF = "post:voted:"
constant KeyCommunitySetPF (line 13) | KeyCommunitySetPF = "community:"
function getRedisKey (line 17) | func getRedisKey(key string) string {
FILE: lesson80/bluebell/dao/redis/post.go
function getIDsFormKey (line 12) | func getIDsFormKey(key string, page, size int64) ([]string, error) {
function GetPostIDsInOrder (line 19) | func GetPostIDsInOrder(p *models.ParamPostList) ([]string, error) {
function GetPostVoteData (line 31) | func GetPostVoteData(ids []string) (data []int64, err error) {
function GetCommunityPostIDsInOrder (line 58) | func GetCommunityPostIDsInOrder(p *models.ParamPostList) ([]string, erro...
FILE: lesson80/bluebell/dao/redis/redis.go
function Init (line 20) | func Init(cfg *setting.RedisConfig) (err error) {
function Close (line 36) | func Close() {
FILE: lesson80/bluebell/dao/redis/vote.go
constant oneWeekInSeconds (line 39) | oneWeekInSeconds = 7 * 24 * 3600
constant scorePerVote (line 40) | scorePerVote = 432
function CreatePost (line 48) | func CreatePost(postID, communityID int64) error {
function VoteForPost (line 68) | func VoteForPost(userID, postID string, value float64) error {
FILE: lesson80/bluebell/docs/docs.go
type swaggerInfo (line 194) | type swaggerInfo struct
type s (line 213) | type s struct
method ReadDoc (line 215) | func (s *s) ReadDoc() string {
function init (line 237) | func init() {
FILE: lesson80/bluebell/logger/logger.go
function Init (line 22) | func Init(cfg *setting.LogConfig, mode string) (err error) {
function getEncoder (line 49) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 59) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 70) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 92) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: lesson80/bluebell/logic/community.go
function GetCommunityList (line 8) | func GetCommunityList() ([]*models.Community, error) {
function GetCommunityDetail (line 13) | func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
FILE: lesson80/bluebell/logic/post.go
function CreatePost (line 12) | func CreatePost(p *models.Post) (err error) {
function GetPostById (line 26) | func GetPostById(pid int64) (data *models.ApiPostDetail, err error) {
function GetPostList (line 61) | func GetPostList(page, size int64) (data []*models.ApiPostDetail, err er...
function GetPostList2 (line 95) | func GetPostList2(p *models.ParamPostList) (data []*models.ApiPostDetail...
function GetCommunityPostList (line 149) | func GetCommunityPostList(p *models.ParamPostList) (data []*models.ApiPo...
function GetPostListNew (line 203) | func GetPostListNew(p *models.ParamPostList) (data []*models.ApiPostDeta...
FILE: lesson80/bluebell/logic/user.go
function SignUp (line 12) | func SignUp(p *models.ParamSignUp) (err error) {
function Login (line 29) | func Login(p *models.ParamLogin) (user *models.User, err error) {
FILE: lesson80/bluebell/logic/vote.go
function VoteForPost (line 35) | func VoteForPost(userID int64, p *models.ParamVoteData) error {
FILE: lesson80/bluebell/main.go
function main (line 24) | func main() {
FILE: lesson80/bluebell/middlewares/auth.go
function JWTAuthMiddleware (line 12) | func JWTAuthMiddleware() func(c *gin.Context) {
FILE: lesson80/bluebell/middlewares/ratelimit.go
function RateLimitMiddleware (line 11) | func RateLimitMiddleware(fillInterval time.Duration, cap int64) func(c *...
FILE: lesson80/bluebell/models/community.go
type Community (line 5) | type Community struct
type CommunityDetail (line 10) | type CommunityDetail struct
FILE: lesson80/bluebell/models/create_table.sql
type `user` (line 2) | CREATE TABLE `user` (
type `community` (line 18) | CREATE TABLE `community` (
type `post` (line 37) | CREATE TABLE `post` (
FILE: lesson80/bluebell/models/params.go
constant OrderTime (line 6) | OrderTime = "time"
constant OrderScore (line 7) | OrderScore = "score"
type ParamSignUp (line 11) | type ParamSignUp struct
type ParamLogin (line 18) | type ParamLogin struct
type ParamVoteData (line 24) | type ParamVoteData struct
type ParamPostList (line 31) | type ParamPostList struct
FILE: lesson80/bluebell/models/post.go
type Post (line 7) | type Post struct
type ApiPostDetail (line 18) | type ApiPostDetail struct
FILE: lesson80/bluebell/models/struct_test.go
type s1 (line 11) | type s1 struct
type s2 (line 17) | type s2 struct
function TestStruct (line 23) | func TestStruct(t *testing.T) {
FILE: lesson80/bluebell/models/user.go
type User (line 3) | type User struct
FILE: lesson80/bluebell/pkg/jwt/jwt.go
type MyClaims (line 18) | type MyClaims struct
function GenToken (line 25) | func GenToken(userID int64, username string) (string, error) {
function ParseToken (line 43) | func ParseToken(tokenString string) (*MyClaims, error) {
FILE: lesson80/bluebell/pkg/snowflake/snowflake.go
function Init (line 11) | func Init(startTime string, machineID int64) (err error) {
function GenID (line 21) | func GenID() int64 {
FILE: lesson80/bluebell/router/route.go
function SetupRouter (line 18) | func SetupRouter(mode string) *gin.Engine {
FILE: lesson80/bluebell/setting/setting.go
type AppConfig (line 12) | type AppConfig struct
type MySQLConfig (line 25) | type MySQLConfig struct
type RedisConfig (line 35) | type RedisConfig struct
type LogConfig (line 44) | type LogConfig struct
function Init (line 52) | func Init(filePath string) (err error) {
FILE: lesson80/bluebell/sql/bluebell_community.sql
type community (line 1) | create table community
FILE: lesson80/bluebell/sql/bluebell_post.sql
type post (line 1) | create table post
type idx_community_id (line 21) | create index idx_community_id
FILE: lesson80/bluebell/sql/bluebell_user.sql
type user (line 1) | create table user
FILE: lesson80/bluebell/static/js/app.9f3efa6d.js
function s (line 1) | function s(s){for(var n,o,c=s[0],r=s[1],l=s[2],m=0,p=[];m<c.length;m++)o...
function e (line 1) | function e(){for(var t,s=0;s<a.length;s++){for(var e=a[s],n=!0,c=1;c<e.l...
function o (line 1) | function o(s){if(n[s])return n[s].exports;var e=n[s]={i:s,l:!1,exports:{...
FILE: lesson80/bluebell/static/js/chunk-vendors.57f9e9d6.js
function c (line 1) | function c(t){this.defaults=t,this.interceptors={request:new i,response:...
function a (line 1) | function a(t,e){!r.isUndefined(t)&&r.isUndefined(t["Content-Type"])&&(t[...
function s (line 1) | function s(){var t;return("undefined"!==typeof XMLHttpRequest||"undefine...
function r (line 1) | function r(t,e,n,r,o,i,a,s){var c,u="function"===typeof t?t.options:t;if...
function r (line 7) | function r(t){return void 0===t||null===t}
function o (line 7) | function o(t){return void 0!==t&&null!==t}
function i (line 7) | function i(t){return!0===t}
function a (line 7) | function a(t){return!1===t}
function s (line 7) | function s(t){return"string"===typeof t||"number"===typeof t||"symbol"==...
function c (line 7) | function c(t){return null!==t&&"object"===typeof t}
function f (line 7) | function f(t){return"[object Object]"===u.call(t)}
function l (line 7) | function l(t){return"[object RegExp]"===u.call(t)}
function p (line 7) | function p(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e...
function d (line 7) | function d(t){return o(t)&&"function"===typeof t.then&&"function"===type...
function h (line 7) | function h(t){return null==t?"":Array.isArray(t)||f(t)&&t.toString===u?J...
function v (line 7) | function v(t){var e=parseFloat(t);return isNaN(e)?t:e}
function y (line 7) | function y(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o<r.len...
function g (line 7) | function g(t,e){if(t.length){var n=t.indexOf(e);if(n>-1)return t.splice(...
function _ (line 7) | function _(t,e){return b.call(t,e)}
function w (line 7) | function w(t){var e=Object.create(null);return function(n){var r=e[n];re...
function j (line 7) | function j(t,e){function n(n){var r=arguments.length;return r?r>1?t.appl...
function S (line 7) | function S(t,e){return t.bind(e)}
function E (line 7) | function E(t,e){e=e||0;var n=t.length-e,r=new Array(n);while(n--)r[n]=t[...
function T (line 7) | function T(t,e){for(var n in e)t[n]=e[n];return t}
function P (line 7) | function P(t){for(var e={},n=0;n<t.length;n++)t[n]&&T(e,t[n]);return e}
function R (line 7) | function R(t,e,n){}
function N (line 7) | function N(t,e){if(t===e)return!0;var n=c(t),r=c(e);if(!n||!r)return!n&&...
function L (line 7) | function L(t,e){for(var n=0;n<t.length;n++)if(N(t[n],e))return n;return-1}
function D (line 7) | function D(t){var e=!1;return function(){e||(e=!0,t.apply(this,arguments...
function V (line 7) | function V(t){var e=(t+"").charCodeAt(0);return 36===e||95===e}
function z (line 7) | function z(t,e,n,r){Object.defineProperty(t,e,{value:n,enumerable:!!r,wr...
function W (line 7) | function W(t){if(!G.test(t)){var e=t.split(".");return function(t){for(v...
function ft (line 7) | function ft(t){return"function"===typeof t&&/native code/.test(t.toStrin...
function t (line 7) | function t(){this.set=Object.create(null)}
function mt (line 7) | function mt(t){yt.push(t),vt.target=t}
function gt (line 7) | function gt(){yt.pop(),vt.target=yt[yt.length-1]}
function xt (line 7) | function xt(t){return new bt(void 0,void 0,void 0,String(t))}
function Ct (line 7) | function Ct(t){var e=new bt(t.tag,t.data,t.children&&t.children.slice(),...
function $t (line 7) | function $t(t){St=t}
function Tt (line 7) | function Tt(t,e){t.__proto__=e}
function Pt (line 7) | function Pt(t,e,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];z(t,i,e[i])}}
function Rt (line 7) | function Rt(t,e){var n;if(c(t)&&!(t instanceof bt))return _(t,"__ob__")&...
function It (line 7) | function It(t,e,n,r,o){var i=new vt,a=Object.getOwnPropertyDescriptor(t,...
function Mt (line 7) | function Mt(t,e,n){if(Array.isArray(t)&&p(e))return t.length=Math.max(t....
function Nt (line 7) | function Nt(t,e){if(Array.isArray(t)&&p(e))t.splice(e,1);else{var n=t.__...
function Lt (line 7) | function Lt(t){for(var e=void 0,n=0,r=t.length;n<r;n++)e=t[n],e&&e.__ob_...
function Ft (line 7) | function Ft(t,e){if(!e)return t;for(var n,r,o,i=pt?Reflect.ownKeys(e):Ob...
function Ut (line 7) | function Ut(t,e,n){return n?function(){var r="function"===typeof e?e.cal...
function Bt (line 7) | function Bt(t,e){var n=e?t?t.concat(e):Array.isArray(e)?e:[e]:t;return n...
function qt (line 7) | function qt(t){for(var e=[],n=0;n<t.length;n++)-1===e.indexOf(t[n])&&e.p...
function Ht (line 7) | function Ht(t,e,n,r){var o=Object.create(t||null);return e?T(o,e):o}
function zt (line 7) | function zt(t,e){var n=t.props;if(n){var r,o,i,a={};if(Array.isArray(n))...
function Gt (line 7) | function Gt(t,e){var n=t.inject;if(n){var r=t.inject={};if(Array.isArray...
function Wt (line 7) | function Wt(t){var e=t.directives;if(e)for(var n in e){var r=e[n];"funct...
function Kt (line 7) | function Kt(t,e,n){if("function"===typeof e&&(e=e.options),zt(e,n),Gt(e,...
function Xt (line 7) | function Xt(t,e,n,r){if("string"===typeof n){var o=t[e];if(_(o,n))return...
function Jt (line 7) | function Jt(t,e,n,r){var o=e[t],i=!_(n,t),a=n[t],s=te(Boolean,o.type);if...
function Yt (line 7) | function Yt(t,e,n){if(_(e,"default")){var r=e.default;return t&&t.$optio...
function Qt (line 7) | function Qt(t){var e=t&&t.toString().match(/^\s*function (\w+)/);return ...
function Zt (line 7) | function Zt(t,e){return Qt(t)===Qt(e)}
function te (line 7) | function te(t,e){if(!Array.isArray(e))return Zt(e,t)?0:-1;for(var n=0,r=...
function ee (line 7) | function ee(t,e,n){mt();try{if(e){var r=e;while(r=r.$parent){var o=r.$op...
function ne (line 7) | function ne(t,e,n,r,o){var i;try{i=n?t.apply(e,n):t.call(e),i&&!i._isVue...
function re (line 7) | function re(t,e,n){if(q.errorHandler)try{return q.errorHandler.call(null...
function oe (line 7) | function oe(t,e,n){if(!J&&!Y||"undefined"===typeof console)throw t;conso...
function ue (line 7) | function ue(){ce=!1;var t=se.slice(0);se.length=0;for(var e=0;e<t.length...
function he (line 7) | function he(t,e){var n;if(se.push((function(){if(t)try{t.call(e)}catch(C...
function ye (line 7) | function ye(t){me(t,ve),ve.clear()}
function me (line 7) | function me(t,e){var n,r,o=Array.isArray(t);if(!(!o&&!c(t)||Object.isFro...
function be (line 7) | function be(t,e){function n(){var t=arguments,r=n.fns;if(!Array.isArray(...
function _e (line 7) | function _e(t,e,n,o,a,s){var c,u,f,l;for(c in t)u=t[c],f=e[c],l=ge(c),r(...
function we (line 7) | function we(t,e,n){var a;t instanceof bt&&(t=t.data.hook||(t.data.hook={...
function xe (line 7) | function xe(t,e,n){var i=e.options.props;if(!r(i)){var a={},s=t.attrs,c=...
function Ce (line 7) | function Ce(t,e,n,r,i){if(o(e)){if(_(e,n))return t[n]=e[n],i||delete e[n...
function Oe (line 7) | function Oe(t){for(var e=0;e<t.length;e++)if(Array.isArray(t[e]))return ...
function Ae (line 7) | function Ae(t){return s(t)?[xt(t)]:Array.isArray(t)?je(t):void 0}
function ke (line 7) | function ke(t){return o(t)&&o(t.text)&&a(t.isComment)}
function je (line 7) | function je(t,e){var n,a,c,u,f=[];for(n=0;n<t.length;n++)a=t[n],r(a)||"b...
function Se (line 7) | function Se(t){var e=t.$options.provide;e&&(t._provided="function"===typ...
function $e (line 7) | function $e(t){var e=Ee(t.$options.inject,t);e&&($t(!1),Object.keys(e).f...
function Ee (line 7) | function Ee(t,e){if(t){for(var n=Object.create(null),r=pt?Reflect.ownKey...
function Te (line 7) | function Te(t,e){if(!t||!t.length)return{};for(var n={},r=0,o=t.length;r...
function Pe (line 7) | function Pe(t){return t.isComment&&!t.asyncFactory||" "===t.text}
function Re (line 7) | function Re(t,e,r){var o,i=Object.keys(e).length>0,a=t?!!t.$stable:!i,s=...
function Ie (line 7) | function Ie(t,e,n){var r=function(){var t=arguments.length?n.apply(null,...
function Me (line 7) | function Me(t,e){return function(){return t[e]}}
function Ne (line 7) | function Ne(t,e){var n,r,i,a,s;if(Array.isArray(t)||"string"===typeof t)...
function Le (line 7) | function Le(t,e,n,r){var o,i=this.$scopedSlots[t];i?(n=n||{},r&&(n=T(T({...
function De (line 7) | function De(t){return Xt(this.$options,"filters",t,!0)||M}
function Fe (line 7) | function Fe(t,e){return Array.isArray(t)?-1===t.indexOf(e):t!==e}
function Ue (line 7) | function Ue(t,e,n,r,o){var i=q.keyCodes[e]||n;return o&&r&&!q.keyCodes[e...
function Be (line 7) | function Be(t,e,n,r,o){if(n)if(c(n)){var i;Array.isArray(n)&&(n=P(n));va...
function qe (line 7) | function qe(t,e){var n=this._staticTrees||(this._staticTrees=[]),r=n[t];...
function He (line 7) | function He(t,e,n){return Ve(t,"__once__"+e+(n?"_"+n:""),!0),t}
function Ve (line 7) | function Ve(t,e,n){if(Array.isArray(t))for(var r=0;r<t.length;r++)t[r]&&...
function ze (line 7) | function ze(t,e,n){t.isStatic=!0,t.key=e,t.isOnce=n}
function Ge (line 7) | function Ge(t,e){if(e)if(f(e)){var n=t.on=t.on?T({},t.on):{};for(var r i...
function We (line 7) | function We(t,e,n,r){e=e||{$stable:!n};for(var o=0;o<t.length;o++){var i...
function Ke (line 7) | function Ke(t,e){for(var n=0;n<e.length;n+=2){var r=e[n];"string"===type...
function Xe (line 7) | function Xe(t,e){return"string"===typeof t?e+t:t}
function Je (line 7) | function Je(t){t._o=He,t._n=v,t._s=h,t._l=Ne,t._t=Le,t._q=N,t._i=L,t._m=...
function Ye (line 7) | function Ye(t,e,r,o,a){var s,c=this,u=a.options;_(o,"_uid")?(s=Object.cr...
function Qe (line 7) | function Qe(t,e,r,i,a){var s=t.options,c={},u=s.props;if(o(u))for(var f ...
function Ze (line 7) | function Ze(t,e,n,r,o){var i=Ct(t);return i.fnContext=n,i.fnOptions=r,e....
function tn (line 7) | function tn(t,e){for(var n in e)t[C(n)]=e[n]}
function rn (line 7) | function rn(t,e,n,a,s){if(!r(t)){var u=n.$options._base;if(c(t)&&(t=u.ex...
function on (line 7) | function on(t,e){var n={_isComponent:!0,_parentVnode:t,parent:e},r=t.dat...
function an (line 7) | function an(t){for(var e=t.hook||(t.hook={}),n=0;n<nn.length;n++){var r=...
function sn (line 7) | function sn(t,e){var n=function(n,r){t(n,r),e(n,r)};return n._merged=!0,n}
function cn (line 7) | function cn(t,e){var n=t.model&&t.model.prop||"value",r=t.model&&t.model...
function ln (line 7) | function ln(t,e,n,r,o,a){return(Array.isArray(n)||s(n))&&(o=r,r=n,n=void...
function pn (line 7) | function pn(t,e,n,r,i){if(o(n)&&o(n.__ob__))return wt();if(o(n)&&o(n.is)...
function dn (line 7) | function dn(t,e,n){if(t.ns=e,"foreignObject"===t.tag&&(e=void 0,n=!0),o(...
function hn (line 7) | function hn(t){c(t.style)&&ye(t.style),c(t.class)&&ye(t.class)}
function vn (line 7) | function vn(t){t._vnode=null,t._staticTrees=null;var e=t.$options,r=t.$v...
function gn (line 7) | function gn(t){Je(t.prototype),t.prototype.$nextTick=function(t){return ...
function bn (line 7) | function bn(t,e){return(t.__esModule||pt&&"Module"===t[Symbol.toStringTa...
function _n (line 7) | function _n(t,e,n,r,o){var i=wt();return i.asyncFactory=t,i.asyncMeta={d...
function wn (line 7) | function wn(t,e){if(i(t.error)&&o(t.errorComp))return t.errorComp;if(o(t...
function xn (line 7) | function xn(t){return t.isComment&&t.asyncFactory}
function Cn (line 7) | function Cn(t){if(Array.isArray(t))for(var e=0;e<t.length;e++){var n=t[e...
function On (line 7) | function On(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t....
function An (line 7) | function An(t,e){yn.$on(t,e)}
function kn (line 7) | function kn(t,e){yn.$off(t,e)}
function jn (line 7) | function jn(t,e){var n=yn;return function r(){var o=e.apply(null,argumen...
function Sn (line 7) | function Sn(t,e,n){yn=t,_e(e,n||{},An,kn,jn,t),yn=void 0}
function $n (line 7) | function $n(t){var e=/^hook:/;t.prototype.$on=function(t,n){var r=this;i...
function Tn (line 7) | function Tn(t){var e=En;return En=t,function(){En=e}}
function Pn (line 7) | function Pn(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){while(n.$o...
function Rn (line 7) | function Rn(t){t.prototype._update=function(t,e){var n=this,r=n.$el,o=n....
function In (line 7) | function In(t,e,n){var r;return t.$el=e,t.$options.render||(t.$options.r...
function Mn (line 7) | function Mn(t,e,r,o,i){var a=o.data.scopedSlots,s=t.$scopedSlots,c=!!(a&...
function Nn (line 7) | function Nn(t){while(t&&(t=t.$parent))if(t._inactive)return!0;return!1}
function Ln (line 7) | function Ln(t,e){if(e){if(t._directInactive=!1,Nn(t))return}else if(t._d...
function Dn (line 7) | function Dn(t,e){if((!e||(t._directInactive=!0,!Nn(t)))&&!t._inactive){t...
function Fn (line 7) | function Fn(t,e){mt();var n=t.$options[e],r=e+" hook";if(n)for(var o=0,i...
function Gn (line 7) | function Gn(){zn=Un.length=Bn.length=0,qn={},Hn=Vn=!1}
function Jn (line 7) | function Jn(){var t,e;for(Wn=Kn(),Vn=!0,Un.sort((function(t,e){return t....
function Yn (line 7) | function Yn(t){var e=t.length;while(e--){var n=t[e],r=n.vm;r._watcher===...
function Qn (line 7) | function Qn(t){t._inactive=!1,Bn.push(t)}
function Zn (line 7) | function Zn(t){for(var e=0;e<t.length;e++)t[e]._inactive=!0,Ln(t[e],!0)}
function tr (line 7) | function tr(t){var e=t.id;if(null==qn[e]){if(qn[e]=!0,Vn){var n=Un.lengt...
function or (line 7) | function or(t,e,n){rr.get=function(){return this[e][n]},rr.set=function(...
function ir (line 7) | function ir(t){t._watchers=[];var e=t.$options;e.props&&ar(t,e.props),e....
function ar (line 7) | function ar(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$optio...
function sr (line 7) | function sr(t){var e=t.$options.data;e=t._data="function"===typeof e?cr(...
function cr (line 7) | function cr(t,e){mt();try{return t.call(e,e)}catch(Ca){return ee(Ca,e,"d...
function fr (line 7) | function fr(t,e){var n=t._computedWatchers=Object.create(null),r=ct();fo...
function lr (line 7) | function lr(t,e,n){var r=!ct();"function"===typeof n?(rr.get=r?pr(e):dr(...
function pr (line 7) | function pr(t){return function(){var e=this._computedWatchers&&this._com...
function dr (line 7) | function dr(t){return function(){return t.call(this,this)}}
function hr (line 7) | function hr(t,e){t.$options.props;for(var n in e)t[n]="function"!==typeo...
function vr (line 7) | function vr(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var ...
function yr (line 7) | function yr(t,e,n,r){return f(n)&&(r=n,n=n.handler),"string"===typeof n&...
function mr (line 7) | function mr(t){var e={get:function(){return this._data}},n={get:function...
function br (line 7) | function br(t){t.prototype._init=function(t){var e=this;e._uid=gr++,e._i...
function _r (line 7) | function _r(t,e){var n=t.$options=Object.create(t.constructor.options),r...
function wr (line 7) | function wr(t){var e=t.options;if(t.super){var n=wr(t.super),r=t.superOp...
function xr (line 7) | function xr(t){var e,n=t.options,r=t.sealedOptions;for(var o in n)n[o]!=...
function Cr (line 7) | function Cr(t){this._init(t)}
function Or (line 7) | function Or(t){t.use=function(t){var e=this._installedPlugins||(this._in...
function Ar (line 7) | function Ar(t){t.mixin=function(t){return this.options=Kt(this.options,t...
function kr (line 7) | function kr(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r...
function jr (line 7) | function jr(t){var e=t.options.props;for(var n in e)or(t.prototype,"_pro...
function Sr (line 7) | function Sr(t){var e=t.options.computed;for(var n in e)lr(t.prototype,n,...
function $r (line 7) | function $r(t){U.forEach((function(e){t[e]=function(t,n){return n?("comp...
function Er (line 7) | function Er(t){return t&&(t.Ctor.options.name||t.tag)}
function Tr (line 7) | function Tr(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"===type...
function Pr (line 7) | function Pr(t,e){var n=t.cache,r=t.keys,o=t._vnode;for(var i in n){var a...
function Rr (line 7) | function Rr(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstanc...
function Lr (line 7) | function Lr(t){var e={get:function(){return q}};Object.defineProperty(t,...
function Xr (line 7) | function Xr(t){var e=t.data,n=t,r=t;while(o(r.componentInstance))r=r.com...
function Jr (line 7) | function Jr(t,e){return{staticClass:Qr(t.staticClass,e.staticClass),clas...
function Yr (line 7) | function Yr(t,e){return o(t)||o(e)?Qr(t,Zr(e)):""}
function Qr (line 7) | function Qr(t,e){return t?e?t+" "+e:t:e||""}
function Zr (line 7) | function Zr(t){return Array.isArray(t)?to(t):c(t)?eo(t):"string"===typeo...
function to (line 7) | function to(t){for(var e,n="",r=0,i=t.length;r<i;r++)o(e=Zr(t[r]))&&""!=...
function eo (line 7) | function eo(t){var e="";for(var n in t)t[n]&&(e&&(e+=" "),e+=n);return e}
function ao (line 7) | function ao(t){return oo(t)?"svg":"math"===t?"math":void 0}
function co (line 7) | function co(t){if(!J)return!0;if(io(t))return!1;if(t=t.toLowerCase(),nul...
function fo (line 7) | function fo(t){if("string"===typeof t){var e=document.querySelector(t);r...
function lo (line 7) | function lo(t,e){var n=document.createElement(t);return"select"!==t||e.d...
function po (line 7) | function po(t,e){return document.createElementNS(no[t],e)}
function ho (line 7) | function ho(t){return document.createTextNode(t)}
function vo (line 7) | function vo(t){return document.createComment(t)}
function yo (line 7) | function yo(t,e,n){t.insertBefore(e,n)}
function mo (line 7) | function mo(t,e){t.removeChild(e)}
function go (line 7) | function go(t,e){t.appendChild(e)}
function bo (line 7) | function bo(t){return t.parentNode}
function _o (line 7) | function _o(t){return t.nextSibling}
function wo (line 7) | function wo(t){return t.tagName}
function xo (line 7) | function xo(t,e){t.textContent=e}
function Co (line 7) | function Co(t,e){t.setAttribute(e,"")}
function ko (line 7) | function ko(t,e){var n=t.data.ref;if(o(n)){var r=t.context,i=t.component...
function $o (line 7) | function $o(t,e){return t.key===e.key&&(t.tag===e.tag&&t.isComment===e.i...
function Eo (line 7) | function Eo(t,e){if("input"!==t.tag)return!0;var n,r=o(n=t.data)&&o(n=n....
function To (line 7) | function To(t,e,n){var r,i,a={};for(r=e;r<=n;++r)i=t[r].key,o(i)&&(a[i]=...
function Po (line 7) | function Po(t){var e,n,a={},c=t.modules,u=t.nodeOps;for(e=0;e<So.length;...
function Io (line 7) | function Io(t,e){(t.data.directives||e.data.directives)&&Mo(t,e)}
function Mo (line 7) | function Mo(t,e){var n,r,o,i=t===jo,a=e===jo,s=Lo(t.data.directives,t.co...
function Lo (line 7) | function Lo(t,e){var n,r,o=Object.create(null);if(!t)return o;for(n=0;n<...
function Do (line 7) | function Do(t){return t.rawName||t.name+"."+Object.keys(t.modifiers||{})...
function Fo (line 7) | function Fo(t,e,n,r,o){var i=t.def&&t.def[e];if(i)try{i(n.elm,t,n,r,o)}c...
function Bo (line 7) | function Bo(t,e){var n=e.componentOptions;if((!o(n)||!1!==n.Ctor.options...
function qo (line 7) | function qo(t,e,n){t.tagName.indexOf("-")>-1?Ho(t,e,n):Vr(e)?Kr(n)?t.rem...
function Ho (line 7) | function Ho(t,e,n){if(Kr(n))t.removeAttribute(e);else{if(tt&&!et&&"TEXTA...
function zo (line 7) | function zo(t,e){var n=e.elm,i=e.data,a=t.data;if(!(r(i.staticClass)&&r(...
function Jo (line 7) | function Jo(t){if(o(t[Ko])){var e=tt?"change":"input";t[e]=[].concat(t[K...
function Yo (line 7) | function Yo(t,e,n){var r=Go;return function o(){var i=e.apply(null,argum...
function Zo (line 7) | function Zo(t,e,n,r){if(Qo){var o=Wn,i=e;e=i._wrapper=function(t){if(t.t...
function ti (line 7) | function ti(t,e,n,r){(r||Go).removeEventListener(t,e._wrapper||e,n)}
function ei (line 7) | function ei(t,e){if(!r(t.data.on)||!r(e.data.on)){var n=e.data.on||{},o=...
function oi (line 7) | function oi(t,e){if(!r(t.data.domProps)||!r(e.data.domProps)){var n,i,a=...
function ii (line 7) | function ii(t,e){return!t.composing&&("OPTION"===t.tagName||ai(t,e)||si(...
function ai (line 7) | function ai(t,e){var n=!0;try{n=document.activeElement!==t}catch(Ca){}re...
function si (line 7) | function si(t,e){var n=t.value,r=t._vModifiers;if(o(r)){if(r.number)retu...
function fi (line 7) | function fi(t){var e=li(t.style);return t.staticStyle?T(t.staticStyle,e):e}
function li (line 7) | function li(t){return Array.isArray(t)?P(t):"string"===typeof t?ui(t):t}
function pi (line 7) | function pi(t,e){var n,r={};if(e){var o=t;while(o.componentInstance)o=o....
function bi (line 7) | function bi(t,e){var n=e.data,i=t.data;if(!(r(n.staticStyle)&&r(n.style)...
function xi (line 7) | function xi(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.s...
function Ci (line 7) | function Ci(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.s...
function Oi (line 7) | function Oi(t){if(t){if("object"===typeof t){var e={};return!1!==t.css&&...
function Ii (line 7) | function Ii(t){Ri((function(){Ri(t)}))}
function Mi (line 7) | function Mi(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n...
function Ni (line 7) | function Ni(t,e){t._transitionClasses&&g(t._transitionClasses,e),Ci(t,e)}
function Li (line 7) | function Li(t,e,n){var r=Fi(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!...
function Fi (line 7) | function Fi(t,e){var n,r=window.getComputedStyle(t),o=(r[$i+"Delay"]||""...
function Ui (line 7) | function Ui(t,e){while(t.length<e.length)t=t.concat(t);return Math.max.a...
function Bi (line 7) | function Bi(t){return 1e3*Number(t.slice(0,-1).replace(",","."))}
function qi (line 7) | function qi(t,e){var n=t.elm;o(n._leaveCb)&&(n._leaveCb.cancelled=!0,n._...
function Hi (line 7) | function Hi(t,e){var n=t.elm;o(n._enterCb)&&(n._enterCb.cancelled=!0,n._...
function Vi (line 7) | function Vi(t){return"number"===typeof t&&!isNaN(t)}
function zi (line 7) | function zi(t){if(r(t))return!1;var e=t.fns;return o(e)?zi(Array.isArray...
function Gi (line 7) | function Gi(t,e){!0!==e.data.show&&qi(e)}
function Qi (line 7) | function Qi(t,e,n){Zi(t,e,n),(tt||nt)&&setTimeout((function(){Zi(t,e,n)}...
function Zi (line 7) | function Zi(t,e,n){var r=e.value,o=t.multiple;if(!o||Array.isArray(r)){f...
function ta (line 7) | function ta(t,e){return e.every((function(e){return!N(e,t)}))}
function ea (line 7) | function ea(t){return"_value"in t?t._value:t.value}
function na (line 7) | function na(t){t.target.composing=!0}
function ra (line 7) | function ra(t){t.target.composing&&(t.target.composing=!1,oa(t.target,"i...
function oa (line 7) | function oa(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,...
function ia (line 7) | function ia(t){return!t.componentInstance||t.data&&t.data.transition?t:i...
function ua (line 7) | function ua(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abst...
function fa (line 7) | function fa(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];...
function la (line 7) | function la(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{...
function pa (line 7) | function pa(t){while(t=t.parent)if(t.data.transition)return!0}
function da (line 7) | function da(t,e){return e.key===t.key&&e.tag===t.tag}
function ba (line 7) | function ba(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._ent...
function _a (line 7) | function _a(t){t.data.newPos=t.elm.getBoundingClientRect()}
function wa (line 7) | function wa(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-...
function n (line 13) | function n(t){var e=Number(t.version.split(".")[0]);if(e>=2)t.mixin({bef...
function i (line 13) | function i(t){o&&(t._devtoolHook=o,o.emit("vuex:init",t),o.on("vuex:trav...
function a (line 13) | function a(t,e){Object.keys(t).forEach((function(n){return e(t[n],n)}))}
function s (line 13) | function s(t){return null!==t&&"object"===typeof t}
function c (line 13) | function c(t){return t&&"function"===typeof t.then}
function u (line 13) | function u(t,e){return function(){return t(e)}}
function d (line 13) | function d(t,e,n){if(e.update(n),n.modules)for(var r in n.modules){if(!e...
function m (line 13) | function m(t,e){return e.indexOf(t)<0&&e.push(t),function(){var n=e.inde...
function g (line 13) | function g(t,e){t._actions=Object.create(null),t._mutations=Object.creat...
function b (line 13) | function b(t,e,n){var r=t._vm;t.getters={},t._makeLocalGettersCache=Obje...
function _ (line 13) | function _(t,e,n,r,o){var i=!n.length,a=t._modules.getNamespace(n);if(r....
function w (line 13) | function w(t,e,n){var r=""===e,o={dispatch:r?t.dispatch:function(n,r,o){...
function x (line 13) | function x(t,e){if(!t._makeLocalGettersCache[e]){var n={},r=e.length;Obj...
function C (line 13) | function C(t,e,n,r){var o=t._mutations[e]||(t._mutations[e]=[]);o.push((...
function O (line 13) | function O(t,e,n,r){var o=t._actions[e]||(t._actions[e]=[]);o.push((func...
function A (line 13) | function A(t,e,n,r){t._wrappedGetters[e]||(t._wrappedGetters[e]=function...
function k (line 13) | function k(t){t._vm.$watch((function(){return this._data.$$state}),(func...
function j (line 13) | function j(t,e){return e.reduce((function(t,e){return t[e]}),t)}
function S (line 13) | function S(t,e,n){return s(t)&&t.type&&(n=e,e=t,t=t.type),{type:t,payloa...
function $ (line 13) | function $(t){h&&t===h||(h=t,n(h))}
function M (line 13) | function M(t){return N(t)?Array.isArray(t)?t.map((function(t){return{key...
function N (line 13) | function N(t){return Array.isArray(t)||s(t)}
function L (line 13) | function L(t){return function(e,n){return"string"!==typeof e?(n=e,e=""):...
function D (line 13) | function D(t,e,n){var r=t._modulesNamespaceMap[n];return r}
function o (line 13) | function o(t){return encodeURIComponent(t).replace(/%40/gi,"@").replace(...
function o (line 13) | function o(t){var r=t;return e&&(n.setAttribute("href",r),r=n.href),n.se...
function s (line 13) | function s(t){t.cancelToken&&t.cancelToken.throwIfRequested()}
function r (line 13) | function r(t){this.message=t}
function r (line 18) | function r(t,e){0}
function o (line 18) | function o(t){return Object.prototype.toString.call(t).indexOf("Error")>-1}
function i (line 18) | function i(t,e){return e instanceof t||e&&(e.name===t.name||e._name===t....
function a (line 18) | function a(t,e){for(var n in e)t[n]=e[n];return t}
function c (line 18) | function c(t,e,n,r){var o=e.props=u(n,r);if(o){o=e.props=a({},o);var i=e...
function u (line 18) | function u(t,e){switch(typeof e){case"undefined":return;case"object":ret...
function v (line 18) | function v(t,e,n){void 0===e&&(e={});var r,o=n||y;try{r=o(t||"")}catch(a...
function y (line 18) | function y(t){var e={};return t=t.trim().replace(/^(\?|#|&)/,""),t?(t.sp...
function m (line 18) | function m(t){var e=t?Object.keys(t).map((function(e){var n=t[e];if(void...
function b (line 18) | function b(t,e,n,r){var o=r&&r.options.stringifyQuery,i=e.query||{};try{...
function _ (line 18) | function _(t){if(Array.isArray(t))return t.map(_);if(t&&"object"===typeo...
function x (line 18) | function x(t){var e=[];while(t)e.unshift(t),t=t.parent;return e}
function C (line 18) | function C(t,e){var n=t.path,r=t.query;void 0===r&&(r={});var o=t.hash;v...
function O (line 18) | function O(t,e){return e===w?t===e:!!e&&(t.path&&e.path?t.path.replace(g...
function A (line 18) | function A(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t...
function k (line 18) | function k(t,e){return 0===t.path.replace(g,"/").indexOf(e.path.replace(...
function j (line 18) | function j(t,e){for(var n in e)if(!(n in t))return!1;return!0}
function S (line 18) | function S(t,e,n){var r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"=...
function $ (line 18) | function $(t){var e="",n="",r=t.indexOf("#");r>=0&&(e=t.slice(r),t=t.sli...
function E (line 18) | function E(t){return t.replace(/\/\//g,"/")}
function D (line 18) | function D(t,e){var n,r=[],o=0,i=0,a="",s=e&&e.delimiter||"/";while(null...
function F (line 18) | function F(t,e){return q(D(t,e))}
function U (line 18) | function U(t){return encodeURI(t).replace(/[\/?#]/g,(function(t){return"...
function B (line 18) | function B(t){return encodeURI(t).replace(/[?#]/g,(function(t){return"%"...
function q (line 18) | function q(t){for(var e=new Array(t.length),n=0;n<t.length;n++)"object"=...
function H (line 18) | function H(t){return t.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}
function V (line 18) | function V(t){return t.replace(/([=!:$\/()])/g,"\\$1")}
function z (line 18) | function z(t,e){return t.keys=e,t}
function G (line 18) | function G(t){return t.sensitive?"":"i"}
function W (line 18) | function W(t,e){var n=t.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.l...
function K (line 18) | function K(t,e,n){for(var r=[],o=0;o<t.length;o++)r.push(Y(t[o],e,n).sou...
function X (line 18) | function X(t,e,n){return J(D(t,n),e,n)}
function J (line 18) | function J(t,e,n){T(e)||(n=e||n,e=[]),n=n||{};for(var r=n.strict,o=!1!==...
function Y (line 18) | function Y(t,e,n){return T(e)||(n=e||n,e=[]),n=n||{},t instanceof RegExp...
function Z (line 18) | function Z(t,e,n){e=e||{};try{var r=Q[t]||(Q[t]=P.compile(t));return"str...
function tt (line 18) | function tt(t,e,n,r){var o="string"===typeof t?{path:t}:t;if(o._normaliz...
function at (line 18) | function at(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)&&!t.defa...
function st (line 18) | function st(t){if(t)for(var e,n=0;n<t.length;n++){if(e=t[n],"a"===e.tag)...
function ct (line 18) | function ct(t){if(!ct.installed||et!==t){ct.installed=!0,et=t;var e=func...
function ft (line 18) | function ft(t,e,n,r){var o=e||[],i=n||Object.create(null),a=r||Object.cr...
function lt (line 18) | function lt(t,e,n,r,o,i){var a=r.path,s=r.name;var c=r.pathToRegexpOptio...
function pt (line 18) | function pt(t,e){var n=P(t,[],e);return n}
function dt (line 18) | function dt(t,e,n){return n||(t=t.replace(/\/$/,"")),"/"===t[0]||null==e...
function ht (line 18) | function ht(t,e){var n=ft(t),r=n.pathList,o=n.pathMap,i=n.nameMap;functi...
function vt (line 18) | function vt(t,e,n){var r=e.match(t);if(!r)return!1;if(!n)return!0;for(va...
function yt (line 18) | function yt(t,e){return S(t,e.parent?e.parent.path:"/",!0)}
function gt (line 18) | function gt(){return mt.now().toFixed(3)}
function _t (line 18) | function _t(){return bt}
function wt (line 18) | function wt(t){return bt=t}
function Ct (line 18) | function Ct(){var t=window.location.protocol+"//"+window.location.host,e...
function Ot (line 18) | function Ot(t,e,n,r){if(t.app){var o=t.options.scrollBehavior;o&&t.app.$...
function At (line 18) | function At(){var t=_t();t&&(xt[t]={x:window.pageXOffset,y:window.pageYO...
function kt (line 18) | function kt(){var t=_t();if(t)return xt[t]}
function jt (line 18) | function jt(t,e){var n=document.documentElement,r=n.getBoundingClientRec...
function St (line 18) | function St(t){return Tt(t.x)||Tt(t.y)}
function $t (line 18) | function $t(t){return{x:Tt(t.x)?t.x:window.pageXOffset,y:Tt(t.y)?t.y:win...
function Et (line 18) | function Et(t){return{x:Tt(t.x)?t.x:0,y:Tt(t.y)?t.y:0}}
function Tt (line 18) | function Tt(t){return"number"===typeof t}
function Rt (line 18) | function Rt(t,e){var n="object"===typeof t;if(n&&"string"===typeof t.sel...
function Mt (line 18) | function Mt(t,e){At();var n=window.history;try{if(e){var r=a({},n.state)...
function Nt (line 18) | function Nt(t){Mt(t,!0)}
function Lt (line 18) | function Lt(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(functi...
function Dt (line 18) | function Dt(t){return function(e,n,r){var i=!1,a=0,s=null;Ft(t,(function...
function Ft (line 18) | function Ft(t,e){return Ut(t.map((function(t){return Object.keys(t.compo...
function Ut (line 18) | function Ut(t){return Array.prototype.concat.apply([],t)}
function qt (line 18) | function qt(t){return t.__esModule||Bt&&"Module"===t[Symbol.toStringTag]}
function Ht (line 18) | function Ht(t){var e=!1;return function(){var n=[],r=arguments.length;wh...
function e (line 18) | function e(e){t.call(this),this.name=this._name="NavigationDuplicated",t...
function Gt (line 18) | function Gt(t){if(!t)if(ut){var e=document.querySelector("base");t=e&&e....
function Wt (line 18) | function Wt(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n<r;n++)if(...
function Kt (line 18) | function Kt(t,e,n,r){var o=Ft(t,(function(t,r,o,i){var a=Xt(t,e);if(a)re...
function Xt (line 18) | function Xt(t,e){return"function"!==typeof t&&(t=et.extend(t)),t.options...
function Jt (line 18) | function Jt(t){return Kt(t,"beforeRouteLeave",Qt,!0)}
function Yt (line 18) | function Yt(t){return Kt(t,"beforeRouteUpdate",Qt)}
function Qt (line 18) | function Qt(t,e){if(e)return function(){return t.apply(e,arguments)}}
function Zt (line 18) | function Zt(t,e,n){return Kt(t,"beforeRouteEnter",(function(t,r,o,i){ret...
function te (line 18) | function te(t,e,n,r,o){return function(i,a,s){return t(i,a,(function(t){...
function ee (line 18) | function ee(t,e,n,r){e[n]&&!e[n]._isBeingDestroyed?t(e[n]):r()&&setTimeo...
function e (line 18) | function e(e,n){var r=this;t.call(this,e,n);var o=e.options.scrollBehavi...
function re (line 18) | function re(t){var e=decodeURI(window.location.pathname);return t&&0===e...
function e (line 18) | function e(e,n,r){t.call(this,e,n),r&&ie(this.base)||ae()}
function ie (line 18) | function ie(t){var e=re(t);if(!/^\/#/.test(e))return window.location.rep...
function ae (line 18) | function ae(){var t=se();return"/"===t.charAt(0)||(fe("/"+t),!1)}
function se (line 18) | function se(){var t=window.location.href,e=t.indexOf("#");if(e<0)return"...
function ce (line 18) | function ce(t){var e=window.location.href,n=e.indexOf("#"),r=n>=0?e.slic...
function ue (line 18) | function ue(t){It?Mt(ce(t)):window.location.hash=t}
function fe (line 18) | function fe(t){It?Nt(ce(t)):window.location.replace(ce(t))}
function e (line 18) | function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}
function he (line 18) | function he(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t....
function ve (line 18) | function ve(t,e,n){var r="hash"===n?"#"+e:e;return t?E(t+"/"+r):r}
function o (line 18) | function o(t){if("function"!==typeof t)throw new TypeError("executor mus...
function i (line 18) | function i(t){return"[object Array]"===o.call(t)}
function a (line 18) | function a(t){return"undefined"===typeof t}
function s (line 18) | function s(t){return null!==t&&!a(t)&&null!==t.constructor&&!a(t.constru...
function c (line 18) | function c(t){return"[object ArrayBuffer]"===o.call(t)}
function u (line 18) | function u(t){return"undefined"!==typeof FormData&&t instanceof FormData}
function f (line 18) | function f(t){var e;return e="undefined"!==typeof ArrayBuffer&&ArrayBuff...
function l (line 18) | function l(t){return"string"===typeof t}
function p (line 18) | function p(t){return"number"===typeof t}
function d (line 18) | function d(t){return null!==t&&"object"===typeof t}
function h (line 18) | function h(t){return"[object Date]"===o.call(t)}
function v (line 18) | function v(t){return"[object File]"===o.call(t)}
function y (line 18) | function y(t){return"[object Blob]"===o.call(t)}
function m (line 18) | function m(t){return"[object Function]"===o.call(t)}
function g (line 18) | function g(t){return d(t)&&m(t.pipe)}
function b (line 18) | function b(t){return"undefined"!==typeof URLSearchParams&&t instanceof U...
function _ (line 18) | function _(t){return t.replace(/^\s*/,"").replace(/\s*$/,"")}
function w (line 18) | function w(){return("undefined"===typeof navigator||"ReactNative"!==navi...
function x (line 18) | function x(t,e){if(null!==t&&"undefined"!==typeof t)if("object"!==typeof...
function C (line 18) | function C(){var t={};function e(e,n){"object"===typeof t[n]&&"object"==...
function O (line 18) | function O(){var t={};function e(e,n){"object"===typeof t[n]&&"object"==...
function A (line 18) | function A(t,e,n){return x(e,(function(e,o){t[o]=n&&"function"===typeof ...
function c (line 18) | function c(t){var e=new i(t),n=o(i.prototype.request,e);return r.extend(...
function n (line 18) | function n(t,e){for(var n=0,r=t.length-1;r>=0;r--){var o=t[r];"."===o?t....
function r (line 18) | function r(t){"string"!==typeof t&&(t+="");var e,n=0,r=-1,o=!0;for(e=t.l...
function o (line 18) | function o(t,e){if(t.filter)return t.filter(e);for(var n=[],r=0;r<t.leng...
function r (line 18) | function r(t){for(var e=0;e<t.length;e++)if(""!==t[e])break;for(var n=t....
function t (line 18) | function t(){}
function o (line 18) | function o(){this.handlers=[]}
FILE: mysql_demo/main.go
function initMySQL (line 12) | func initMySQL() (err error) {
type user (line 34) | type user struct
function queryRowDemo (line 41) | func queryRowDemo() {
function queryMultiRowDemo (line 56) | func queryMultiRowDemo() {
function insertRowDemo (line 79) | func insertRowDemo() {
function updateRowDemo (line 96) | func updateRowDemo() {
function deleteRowDemo (line 113) | func deleteRowDemo() {
function prepareQueryDemo (line 130) | func prepareQueryDemo() {
function prepareInsertDemo (line 157) | func prepareInsertDemo() {
function sqlInjectDemo (line 179) | func sqlInjectDemo(name string) {
function transactionDemo (line 192) | func transactionDemo() {
function main (line 242) | func main() {
FILE: ratelimit_demo/main.go
function pingHandler (line 13) | func pingHandler(c *gin.Context) {
function heiHandler (line 17) | func heiHandler(c *gin.Context) {
function rateLimit1 (line 22) | func rateLimit1() func(ctx *gin.Context) {
function rateLimit2 (line 38) | func rateLimit2(fillInterval time.Duration, cap int64) func(ctx *gin.Con...
function main (line 52) | func main() {
FILE: redis_demo/new.go
function initClient (line 18) | func initClient() (err error) {
function V8Example (line 33) | func V8Example() {
function transDemo (line 62) | func transDemo() {
function incrementWithOutTX (line 126) | func incrementWithOutTX(key string) error {
function main (line 136) | func main() {
FILE: shutdown_demo/main.go
function main (line 17) | func main() {
FILE: sqlx_demo/main.go
function initDB (line 15) | func initDB() (err error) {
type user (line 29) | type user struct
method Value (line 35) | func (u user) Value() (driver.Value, error) {
function BatchInsertUsers2 (line 40) | func BatchInsertUsers2(users []interface{}) error {
function BatchInsertUsers3 (line 52) | func BatchInsertUsers3(users []*user) error {
function queryRowDemo (line 58) | func queryRowDemo() {
function queryMultiRowDemo (line 70) | func queryMultiRowDemo() {
function insertRowDemo (line 82) | func insertRowDemo() {
function updateRowDemo (line 98) | func updateRowDemo() {
function deleteRowDemo (line 114) | func deleteRowDemo() {
function insertUserDemo (line 129) | func insertUserDemo()(err error){
function namedQuery (line 140) | func namedQuery(){
function transactionDemo2 (line 180) | func transactionDemo2()(err error) {
function QueryByIDs (line 229) | func QueryByIDs(ids []int)(users []user, err error){
function QueryAndOrderByIDs (line 243) | func QueryAndOrderByIDs(ids []int)(users []user, err error){
function main (line 261) | func main() {
FILE: swagger_demo/docs/docs.go
type swaggerInfo (line 38) | type swaggerInfo struct
type s (line 57) | type s struct
method ReadDoc (line 59) | func (s *s) ReadDoc() string {
function init (line 81) | func init() {
FILE: swagger_demo/main.go
function main (line 25) | func main() {
FILE: viper_demo/main.go
type Config (line 11) | type Config struct
type MySQLConfig (line 17) | type MySQLConfig struct
function main (line 23) | func main() {
FILE: web_app/dao/mysql/mysql.go
function Init (line 15) | func Init() (err error) {
function Close (line 34) | func Close() {
FILE: web_app/dao/redis/redis.go
function Init (line 14) | func Init() (err error) {
function Close (line 29) | func Close() {
FILE: web_app/logger/logger.go
function Init (line 21) | func Init() (err error) {
function getEncoder (line 42) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 52) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 63) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 85) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: web_app/main.go
function main (line 25) | func main() {
FILE: web_app/routes/routes.go
function Setup (line 10) | func Setup() *gin.Engine {
FILE: web_app/settings/settings.go
function Init (line 10) | func Init() (err error) {
FILE: web_app2/dao/mysql/mysql.go
function Init (line 15) | func Init(cfg *settings.MySQLConfig) (err error) {
function Close (line 34) | func Close() {
FILE: web_app2/dao/redis/redis.go
function Init (line 14) | func Init(cfg *settings.RedisConfig) (err error) {
function Close (line 29) | func Close() {
FILE: web_app2/logger/logger.go
function Init (line 20) | func Init(cfg *settings.LogConfig) (err error) {
function getEncoder (line 41) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 51) | func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapco...
function GinLogger (line 62) | func GinLogger() gin.HandlerFunc {
function GinRecovery (line 84) | func GinRecovery(stack bool) gin.HandlerFunc {
FILE: web_app2/main.go
function main (line 23) | func main() {
FILE: web_app2/routes/routes.go
function Setup (line 11) | func Setup(mode string) *gin.Engine {
FILE: web_app2/settings/settings.go
type AppConfig (line 13) | type AppConfig struct
type LogConfig (line 23) | type LogConfig struct
type MySQLConfig (line 31) | type MySQLConfig struct
type RedisConfig (line 41) | type RedisConfig struct
function Init (line 49) | func Init() (err error) {
FILE: zap_demo/main.go
function main (line 32) | func main() {
function InitLogger (line 43) | func InitLogger() {
function getEncoder (line 52) | func getEncoder() zapcore.Encoder {
function getLogWriter (line 76) | func getLogWriter() zapcore.WriteSyncer {
function simpleHttpGet (line 87) | func simpleHttpGet(url string) {
function GinLogger (line 103) | func GinLogger(logger *zap.Logger) gin.HandlerFunc {
function GinRecovery (line 125) | func GinRecovery(logger *zap.Logger, stack bool) gin.HandlerFunc {
Condensed preview — 445 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,667K chars).
[
{
"path": ".gitignore",
"chars": 283,
"preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Ou"
},
{
"path": "README.md",
"chars": 250,
"preview": "# Go Web开发进阶实战课程\n\n\n## 课程源代码地址\n\n[Github仓库地址](https://github.com/Q1mi/goweb_pro)\n\n## 视频课程地址\n\n- [网易云课堂课程连接](https://study.1"
},
{
"path": "bluebell/.air.conf",
"chars": 884,
"preview": "# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件\n\n# 工作目录\n# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下\nroot = \".\"\ntmp"
},
{
"path": "bluebell/Makefile",
"chars": 479,
"preview": ".PHONY: all build run gotool clean help\n\nBINARY=\"xx\"\n\nall: gotool build\n\nbuild:\n\tCGO_ENABLED=0 GOOS=linux GOARCH=amd64 g"
},
{
"path": "bluebell/conf/config.yaml",
"chars": 416,
"preview": "name: \"bluebell\"\nmode: \"dev\"\nport: 8081\nversion: \"v0.0.1\"\nstart_time: \"2020-07-01\"\nmachine_id: 1\n\nlog:\n level: \"debug\"\n"
},
{
"path": "bluebell/controller/code.go",
"chars": 620,
"preview": "package controller\n\ntype ResCode int64\n\nconst (\n\tCodeSuccess ResCode = 1000 + iota\n\tCodeInvalidParam\n\tCodeUserExist\n\tCod"
},
{
"path": "bluebell/controller/request.go",
"chars": 405,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nconst CtxUserIDKey = \"userID\"\n\nvar ErrorUserNotLo"
},
{
"path": "bluebell/controller/response.go",
"chars": 749,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n/*\n{\n\t\"code\": 10000, // 程序中的错误码\n\t\"msg\": xx, "
},
{
"path": "bluebell/controller/user.go",
"chars": 1764,
"preview": "package controller\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"errors\"\n\n\t\"github.com/go-playg"
},
{
"path": "bluebell/controller/validator.go",
"chars": 2206,
"preview": "package controller\n\nimport (\n\t\"bluebell/models\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin/binding\"\n\t\"gith"
},
{
"path": "bluebell/dao/mysql/mysql.go",
"chars": 572,
"preview": "package mysql\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"github.com/jmoiron/sqlx\"\n)\n\nva"
},
{
"path": "bluebell/dao/mysql/user.go",
"chars": 1516,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"crypto/md5\"\n\t\"database/sql\"\n\t\"encoding/hex\"\n\t\"errors\"\n)\n\n// 把每一步数据库操作封装成函数\n"
},
{
"path": "bluebell/dao/redis/redis.go",
"chars": 583,
"preview": "package redis\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t\"github.com/go-redis/redis\"\n)\n\nvar (\n\tclient *redis.Client\n\tNil "
},
{
"path": "bluebell/go.mod",
"chars": 711,
"preview": "module bluebell\n\ngo 1.14\n\nrequire (\n\tgithub.com/bwmarrin/snowflake v0.3.0\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatib"
},
{
"path": "bluebell/go.sum",
"chars": 40156,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "bluebell/logger/logger.go",
"chars": 3633,
"preview": "package logger\n\nimport (\n\t\"bluebell/setting\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"os\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t"
},
{
"path": "bluebell/logic/user.go",
"chars": 749,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n\t\"bluebell/pkg/jwt\"\n\t\"bluebell/pkg/snowflake\"\n)\n\n// 存放业"
},
{
"path": "bluebell/main.go",
"chars": 1352,
"preview": "package main\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/dao/redis\"\n\t\"bluebell/logger\"\n\t\"bluebell/"
},
{
"path": "bluebell/middlewares/auth.go",
"chars": 1113,
"preview": "package middlewares\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/pkg/jwt\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n// J"
},
{
"path": "bluebell/models/create_table.sql",
"chars": 677,
"preview": "\nCREATE TABLE `user` (\n `id` bigint(20) NOT NULL AUTO_INCREMENT,\n `user_id` bigint(20) NOT NULL,\n `username` va"
},
{
"path": "bluebell/models/params.go",
"chars": 426,
"preview": "package models\n\n// 定义请求的参数结构体\n\n// ParamSignUp 注册请求参数\ntype ParamSignUp struct {\n\tUsername string `json:\"username\" bindi"
},
{
"path": "bluebell/models/user.go",
"chars": 135,
"preview": "package models\n\ntype User struct {\n\tUserID int64 `db:\"user_id\"`\n\tUsername string `db:\"username\"`\n\tPassword string `db"
},
{
"path": "bluebell/pkg/jwt/jwt.go",
"chars": 1245,
"preview": "package jwt\n\nimport (\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/dgrijalva/jwt-go\"\n)\n\nconst TokenExpireDuration = time.Hour * 2\n\nva"
},
{
"path": "bluebell/pkg/snowflake/snowflake.go",
"chars": 384,
"preview": "package snowflake\n\nimport (\n\t\"time\"\n\n\tsf \"github.com/bwmarrin/snowflake\"\n)\n\nvar node *sf.Node\n\nfunc Init(startTime strin"
},
{
"path": "bluebell/router/route.go",
"chars": 696,
"preview": "package router\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/logger\"\n\t\"bluebell/middlewares\"\n\t\"net/http\"\n\n\t\"github.com/gin"
},
{
"path": "bluebell/setting/setting.go",
"chars": 2501,
"preview": "package setting\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/fsnotify/fsnotify\"\n\t\"github.com/spf13/viper\"\n)\n\nvar Conf = new(AppConfig)"
},
{
"path": "docker_demo/Dockerfile",
"chars": 389,
"preview": "FROM golang:alpine AS builder\n\n# 为我们的镜像设置必要的环境变量\nENV GO111MODULE=on \\\n CGO_ENABLED=0 \\\n GOOS=linux \\\n GOARCH=am"
},
{
"path": "docker_demo/Dockerfile.back",
"chars": 270,
"preview": "FROM golang:alpine\n\n# 为我们的镜像设置必要的环境变量\nENV GO111MODULE=on \\\n CGO_ENABLED=0 \\\n GOOS=linux \\\n GOARCH=amd64\n\n# 移动到工"
},
{
"path": "docker_demo/go.mod",
"chars": 20,
"preview": "module \"docker_demo\""
},
{
"path": "docker_demo/main.go",
"chars": 370,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\nfunc main() {\n\thttp.HandleFunc(\"/\", hello)\n\tserver := &http.Server{\n\t\tAddr:"
},
{
"path": "flag_demo/args_demo.go",
"chars": 249,
"preview": "package main\n\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\n//os.Args demo\nfunc main() {\n\t// os.Args是一个[]string\n\t// os.Args[0] 是当前执行的程序\n\tfmt"
},
{
"path": "flag_demo/flag_demo.go",
"chars": 522,
"preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc main() {\n\t//定义命令行参数方式1\n\tvar name string\n\tvar age int\n\tvar married "
},
{
"path": "flag_demo/go.mod",
"chars": 26,
"preview": "module flag_demo\n\ngo 1.14\n"
},
{
"path": "gin_demo/go.mod",
"chars": 66,
"preview": "module gin_demo\n\ngo 1.14\n\nrequire github.com/gin-gonic/gin v1.6.3\n"
},
{
"path": "gin_demo/go.sum",
"chars": 4313,
"preview": "github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1"
},
{
"path": "gin_demo/main.go",
"chars": 739,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"github.com/gin-gonic/gin\"\n\t\"net/http\"\n)\n\nfunc func1(c *gin.Context){\n\tfmt.Println(\"func1"
},
{
"path": "json_demo/go.mod",
"chars": 67,
"preview": "module json_demo\n\ngo 1.14\n\nrequire github.com/gin-gonic/gin v1.6.3\n"
},
{
"path": "json_demo/go.sum",
"chars": 4313,
"preview": "github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1"
},
{
"path": "json_demo/index.html",
"chars": 462,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>json demo</title>\n</head>\n<body>\n <h1>j"
},
{
"path": "json_demo/json_demo.go",
"chars": 688,
"preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n)\n\ntype MyData struct {\n\tID int64 `json:\"id,string\"`\n\tName str"
},
{
"path": "json_demo/main.go",
"chars": 547,
"preview": "package main\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n// ???\n// 在后端使用的时候还是用int64\n// 进行json序列化与反序列化的时候就使用字符串"
},
{
"path": "lesson23/bluebell/.air.conf",
"chars": 884,
"preview": "# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件\n\n# 工作目录\n# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下\nroot = \".\"\ntmp"
},
{
"path": "lesson23/bluebell/Makefile",
"chars": 479,
"preview": ".PHONY: all build run gotool clean help\n\nBINARY=\"xx\"\n\nall: gotool build\n\nbuild:\n\tCGO_ENABLED=0 GOOS=linux GOARCH=amd64 g"
},
{
"path": "lesson23/bluebell/conf/config.yaml",
"chars": 442,
"preview": "name: \"bluebell\"\nmode: \"dev\"\nport: 8084\nversion: \"v0.0.1\"\nstart_time: \"2020-07-01\"\nmachine_id: 1\n\nauth:\n jwt_expire: 87"
},
{
"path": "lesson23/bluebell/controller/code.go",
"chars": 620,
"preview": "package controller\n\ntype ResCode int64\n\nconst (\n\tCodeSuccess ResCode = 1000 + iota\n\tCodeInvalidParam\n\tCodeUserExist\n\tCod"
},
{
"path": "lesson23/bluebell/controller/community.go",
"chars": 916,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"go.uber.org/zap\"\n)\n\n// ---- 跟社区"
},
{
"path": "lesson23/bluebell/controller/post.go",
"chars": 165,
"preview": "package controller\n\nimport \"github.com/gin-gonic/gin\"\n\nfunc CreatePostHandler(c *gin.Context) {\n\t// 1. 获取参数及参数的校验\n\n\t//c."
},
{
"path": "lesson23/bluebell/controller/request.go",
"chars": 405,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nconst CtxUserIDKey = \"userID\"\n\nvar ErrorUserNotLo"
},
{
"path": "lesson23/bluebell/controller/response.go",
"chars": 749,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n/*\n{\n\t\"code\": 10000, // 程序中的错误码\n\t\"msg\": xx, "
},
{
"path": "lesson23/bluebell/controller/user.go",
"chars": 1764,
"preview": "package controller\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"errors\"\n\n\t\"github.com/go-playg"
},
{
"path": "lesson23/bluebell/controller/validator.go",
"chars": 2206,
"preview": "package controller\n\nimport (\n\t\"bluebell/models\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin/binding\"\n\t\"gith"
},
{
"path": "lesson23/bluebell/dao/mysql/community.go",
"chars": 815,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"database/sql\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc GetCommunityList() (communityList"
},
{
"path": "lesson23/bluebell/dao/mysql/error_code.go",
"chars": 219,
"preview": "package mysql\n\nimport \"errors\"\n\nvar (\n\tErrorUserExist = errors.New(\"用户已存在\")\n\tErrorUserNotExist = errors.New(\"用户"
},
{
"path": "lesson23/bluebell/dao/mysql/mysql.go",
"chars": 572,
"preview": "package mysql\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"github.com/jmoiron/sqlx\"\n)\n\nva"
},
{
"path": "lesson23/bluebell/dao/mysql/user.go",
"chars": 1362,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"crypto/md5\"\n\t\"database/sql\"\n\t\"encoding/hex\"\n)\n\n// 把每一步数据库操作封装成函数\n// 待logic层"
},
{
"path": "lesson23/bluebell/dao/redis/redis.go",
"chars": 583,
"preview": "package redis\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t\"github.com/go-redis/redis\"\n)\n\nvar (\n\tclient *redis.Client\n\tNil "
},
{
"path": "lesson23/bluebell/go.mod",
"chars": 711,
"preview": "module bluebell\n\ngo 1.14\n\nrequire (\n\tgithub.com/bwmarrin/snowflake v0.3.0\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatib"
},
{
"path": "lesson23/bluebell/go.sum",
"chars": 40156,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "lesson23/bluebell/logger/logger.go",
"chars": 3633,
"preview": "package logger\n\nimport (\n\t\"bluebell/setting\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"os\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t"
},
{
"path": "lesson23/bluebell/logic/community.go",
"chars": 300,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n)\n\nfunc GetCommunityList() ([]*models.Community, error)"
},
{
"path": "lesson23/bluebell/logic/user.go",
"chars": 749,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n\t\"bluebell/pkg/jwt\"\n\t\"bluebell/pkg/snowflake\"\n)\n\n// 存放业"
},
{
"path": "lesson23/bluebell/main.go",
"chars": 1352,
"preview": "package main\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/dao/redis\"\n\t\"bluebell/logger\"\n\t\"bluebell/"
},
{
"path": "lesson23/bluebell/middlewares/auth.go",
"chars": 1113,
"preview": "package middlewares\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/pkg/jwt\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n// J"
},
{
"path": "lesson23/bluebell/models/community.go",
"chars": 428,
"preview": "package models\n\nimport \"time\"\n\ntype Community struct {\n\tID int64 `json:\"id\" db:\"community_id\"`\n\tName string `json:\"na"
},
{
"path": "lesson23/bluebell/models/create_table.sql",
"chars": 2638,
"preview": "--\nCREATE TABLE `user` (\n `id` bigint(20) NOT NULL AUTO_INCREMENT,\n `user_id` bigint(20) NOT NULL,\n `username` "
},
{
"path": "lesson23/bluebell/models/params.go",
"chars": 426,
"preview": "package models\n\n// 定义请求的参数结构体\n\n// ParamSignUp 注册请求参数\ntype ParamSignUp struct {\n\tUsername string `json:\"username\" bindi"
},
{
"path": "lesson23/bluebell/models/post.go",
"chars": 445,
"preview": "package models\n\nimport \"time\"\n\n// 内存对齐概念\n\ntype Post struct {\n\tID int64 `json:\"id\" db:\"post_id\"`\n\tAuthorID "
},
{
"path": "lesson23/bluebell/models/struct_test.go",
"chars": 329,
"preview": "package models\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"unsafe\"\n)\n\n// Go 内存对齐\n\ntype s1 struct {\n\ta int8\n\tb string\n\tc int8\n}\n\ntype s"
},
{
"path": "lesson23/bluebell/models/user.go",
"chars": 135,
"preview": "package models\n\ntype User struct {\n\tUserID int64 `db:\"user_id\"`\n\tUsername string `db:\"username\"`\n\tPassword string `db"
},
{
"path": "lesson23/bluebell/pkg/jwt/jwt.go",
"chars": 1238,
"preview": "package jwt\n\nimport (\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/spf13/viper\"\n\n\t\"github.com/dgrijalva/jwt-go\"\n)\n\nvar mySecret = []b"
},
{
"path": "lesson23/bluebell/pkg/snowflake/snowflake.go",
"chars": 384,
"preview": "package snowflake\n\nimport (\n\t\"time\"\n\n\tsf \"github.com/bwmarrin/snowflake\"\n)\n\nvar node *sf.Node\n\nfunc Init(startTime strin"
},
{
"path": "lesson23/bluebell/router/route.go",
"chars": 789,
"preview": "package router\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/logger\"\n\t\"bluebell/middlewares\"\n\t\"net/http\"\n\n\t\"github.com/gin"
},
{
"path": "lesson23/bluebell/setting/setting.go",
"chars": 2501,
"preview": "package setting\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/fsnotify/fsnotify\"\n\t\"github.com/spf13/viper\"\n)\n\nvar Conf = new(AppConfig)"
},
{
"path": "lesson28/bluebell/.air.conf",
"chars": 884,
"preview": "# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件\n\n# 工作目录\n# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下\nroot = \".\"\ntmp"
},
{
"path": "lesson28/bluebell/Makefile",
"chars": 479,
"preview": ".PHONY: all build run gotool clean help\n\nBINARY=\"xx\"\n\nall: gotool build\n\nbuild:\n\tCGO_ENABLED=0 GOOS=linux GOARCH=amd64 g"
},
{
"path": "lesson28/bluebell/conf/config.yaml",
"chars": 442,
"preview": "name: \"bluebell\"\nmode: \"dev\"\nport: 8084\nversion: \"v0.0.1\"\nstart_time: \"2020-07-01\"\nmachine_id: 1\n\nauth:\n jwt_expire: 87"
},
{
"path": "lesson28/bluebell/controller/code.go",
"chars": 620,
"preview": "package controller\n\ntype ResCode int64\n\nconst (\n\tCodeSuccess ResCode = 1000 + iota\n\tCodeInvalidParam\n\tCodeUserExist\n\tCod"
},
{
"path": "lesson28/bluebell/controller/community.go",
"chars": 916,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"go.uber.org/zap\"\n)\n\n// ---- 跟社区"
},
{
"path": "lesson28/bluebell/controller/post.go",
"chars": 1731,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"strconv\"\n\n\t\"go.uber.org/zap\"\n\n\t\"github.com/gin-gonic"
},
{
"path": "lesson28/bluebell/controller/request.go",
"chars": 756,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nconst CtxUserIDKey = \"userID\"\n\nvar Err"
},
{
"path": "lesson28/bluebell/controller/response.go",
"chars": 749,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n/*\n{\n\t\"code\": 10000, // 程序中的错误码\n\t\"msg\": xx, "
},
{
"path": "lesson28/bluebell/controller/user.go",
"chars": 1764,
"preview": "package controller\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"errors\"\n\n\t\"github.com/go-playg"
},
{
"path": "lesson28/bluebell/controller/validator.go",
"chars": 2206,
"preview": "package controller\n\nimport (\n\t\"bluebell/models\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin/binding\"\n\t\"gith"
},
{
"path": "lesson28/bluebell/dao/mysql/community.go",
"chars": 815,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"database/sql\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc GetCommunityList() (communityList"
},
{
"path": "lesson28/bluebell/dao/mysql/error_code.go",
"chars": 219,
"preview": "package mysql\n\nimport \"errors\"\n\nvar (\n\tErrorUserExist = errors.New(\"用户已存在\")\n\tErrorUserNotExist = errors.New(\"用户"
},
{
"path": "lesson28/bluebell/dao/mysql/mysql.go",
"chars": 572,
"preview": "package mysql\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"github.com/jmoiron/sqlx\"\n)\n\nva"
},
{
"path": "lesson28/bluebell/dao/mysql/post.go",
"chars": 840,
"preview": "package mysql\n\nimport \"bluebell/models\"\n\nfunc CreatePost(p *models.Post) (err error) {\n\tsqlStr := `insert into post(\n\tpo"
},
{
"path": "lesson28/bluebell/dao/mysql/user.go",
"chars": 1584,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"crypto/md5\"\n\t\"database/sql\"\n\t\"encoding/hex\"\n)\n\n// 把每一步数据库操作封装成函数\n// 待logic层"
},
{
"path": "lesson28/bluebell/dao/redis/redis.go",
"chars": 583,
"preview": "package redis\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t\"github.com/go-redis/redis\"\n)\n\nvar (\n\tclient *redis.Client\n\tNil "
},
{
"path": "lesson28/bluebell/go.mod",
"chars": 711,
"preview": "module bluebell\n\ngo 1.14\n\nrequire (\n\tgithub.com/bwmarrin/snowflake v0.3.0\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatib"
},
{
"path": "lesson28/bluebell/go.sum",
"chars": 40156,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "lesson28/bluebell/logger/logger.go",
"chars": 3633,
"preview": "package logger\n\nimport (\n\t\"bluebell/setting\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"os\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t"
},
{
"path": "lesson28/bluebell/logic/community.go",
"chars": 300,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n)\n\nfunc GetCommunityList() ([]*models.Community, error)"
},
{
"path": "lesson28/bluebell/logic/post.go",
"chars": 2058,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n\t\"bluebell/pkg/snowflake\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc C"
},
{
"path": "lesson28/bluebell/logic/user.go",
"chars": 749,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n\t\"bluebell/pkg/jwt\"\n\t\"bluebell/pkg/snowflake\"\n)\n\n// 存放业"
},
{
"path": "lesson28/bluebell/main.go",
"chars": 1352,
"preview": "package main\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/dao/redis\"\n\t\"bluebell/logger\"\n\t\"bluebell/"
},
{
"path": "lesson28/bluebell/middlewares/auth.go",
"chars": 1113,
"preview": "package middlewares\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/pkg/jwt\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n// J"
},
{
"path": "lesson28/bluebell/models/community.go",
"chars": 428,
"preview": "package models\n\nimport \"time\"\n\ntype Community struct {\n\tID int64 `json:\"id\" db:\"community_id\"`\n\tName string `json:\"na"
},
{
"path": "lesson28/bluebell/models/create_table.sql",
"chars": 2638,
"preview": "--\nCREATE TABLE `user` (\n `id` bigint(20) NOT NULL AUTO_INCREMENT,\n `user_id` bigint(20) NOT NULL,\n `username` "
},
{
"path": "lesson28/bluebell/models/params.go",
"chars": 426,
"preview": "package models\n\n// 定义请求的参数结构体\n\n// ParamSignUp 注册请求参数\ntype ParamSignUp struct {\n\tUsername string `json:\"username\" bindi"
},
{
"path": "lesson28/bluebell/models/post.go",
"chars": 714,
"preview": "package models\n\nimport \"time\"\n\n// 内存对齐概念\n\ntype Post struct {\n\tID int64 `json:\"id\" db:\"post_id\"`\n\tAuthorID "
},
{
"path": "lesson28/bluebell/models/struct_test.go",
"chars": 360,
"preview": "package models\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"unsafe\"\n)\n\n// Go 内存对齐\n\ntype s1 struct {\n\ta int8 // 1\n\tb string // 3\n\tc in"
},
{
"path": "lesson28/bluebell/models/user.go",
"chars": 135,
"preview": "package models\n\ntype User struct {\n\tUserID int64 `db:\"user_id\"`\n\tUsername string `db:\"username\"`\n\tPassword string `db"
},
{
"path": "lesson28/bluebell/pkg/jwt/jwt.go",
"chars": 1238,
"preview": "package jwt\n\nimport (\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/spf13/viper\"\n\n\t\"github.com/dgrijalva/jwt-go\"\n)\n\nvar mySecret = []b"
},
{
"path": "lesson28/bluebell/pkg/snowflake/snowflake.go",
"chars": 384,
"preview": "package snowflake\n\nimport (\n\t\"time\"\n\n\tsf \"github.com/bwmarrin/snowflake\"\n)\n\nvar node *sf.Node\n\nfunc Init(startTime strin"
},
{
"path": "lesson28/bluebell/router/route.go",
"chars": 895,
"preview": "package router\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/logger\"\n\t\"bluebell/middlewares\"\n\t\"net/http\"\n\n\t\"github.com/gin"
},
{
"path": "lesson28/bluebell/setting/setting.go",
"chars": 2501,
"preview": "package setting\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/fsnotify/fsnotify\"\n\t\"github.com/spf13/viper\"\n)\n\nvar Conf = new(AppConfig)"
},
{
"path": "lesson35/bluebell/.air.conf",
"chars": 884,
"preview": "# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件\n\n# 工作目录\n# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下\nroot = \".\"\ntmp"
},
{
"path": "lesson35/bluebell/Makefile",
"chars": 479,
"preview": ".PHONY: all build run gotool clean help\n\nBINARY=\"xx\"\n\nall: gotool build\n\nbuild:\n\tCGO_ENABLED=0 GOOS=linux GOARCH=amd64 g"
},
{
"path": "lesson35/bluebell/conf/config.yaml",
"chars": 442,
"preview": "name: \"bluebell\"\nmode: \"dev\"\nport: 8084\nversion: \"v0.0.1\"\nstart_time: \"2020-07-01\"\nmachine_id: 1\n\nauth:\n jwt_expire: 87"
},
{
"path": "lesson35/bluebell/controller/code.go",
"chars": 620,
"preview": "package controller\n\ntype ResCode int64\n\nconst (\n\tCodeSuccess ResCode = 1000 + iota\n\tCodeInvalidParam\n\tCodeUserExist\n\tCod"
},
{
"path": "lesson35/bluebell/controller/community.go",
"chars": 916,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"go.uber.org/zap\"\n)\n\n// ---- 跟社区"
},
{
"path": "lesson35/bluebell/controller/post.go",
"chars": 1730,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"go.uber.org/"
},
{
"path": "lesson35/bluebell/controller/request.go",
"chars": 756,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nconst CtxUserIDKey = \"userID\"\n\nvar Err"
},
{
"path": "lesson35/bluebell/controller/response.go",
"chars": 759,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n/*\n{\n\t\"code\": 10000, // 程序中的错误码\n\t\"msg\": xx, "
},
{
"path": "lesson35/bluebell/controller/user.go",
"chars": 1914,
"preview": "package controller\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/g"
},
{
"path": "lesson35/bluebell/controller/validator.go",
"chars": 2206,
"preview": "package controller\n\nimport (\n\t\"bluebell/models\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin/binding\"\n\t\"gith"
},
{
"path": "lesson35/bluebell/controller/vote.go",
"chars": 1045,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\n\t\"go.uber.org/zap\"\n\n\t\"github.com/go-playground/valida"
},
{
"path": "lesson35/bluebell/dao/mysql/community.go",
"chars": 815,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"database/sql\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc GetCommunityList() (communityList"
},
{
"path": "lesson35/bluebell/dao/mysql/error_code.go",
"chars": 219,
"preview": "package mysql\n\nimport \"errors\"\n\nvar (\n\tErrorUserExist = errors.New(\"用户已存在\")\n\tErrorUserNotExist = errors.New(\"用户"
},
{
"path": "lesson35/bluebell/dao/mysql/mysql.go",
"chars": 572,
"preview": "package mysql\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"github.com/jmoiron/sqlx\"\n)\n\nva"
},
{
"path": "lesson35/bluebell/dao/mysql/post.go",
"chars": 840,
"preview": "package mysql\n\nimport \"bluebell/models\"\n\nfunc CreatePost(p *models.Post) (err error) {\n\tsqlStr := `insert into post(\n\tpo"
},
{
"path": "lesson35/bluebell/dao/mysql/user.go",
"chars": 1584,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"crypto/md5\"\n\t\"database/sql\"\n\t\"encoding/hex\"\n)\n\n// 把每一步数据库操作封装成函数\n// 待logic层"
},
{
"path": "lesson35/bluebell/dao/redis/keys.go",
"chars": 369,
"preview": "package redis\n\n// redis key\n\n// redis key注意使用命名空间的方式,方便查询和拆分\n\nconst (\n\tPrefix = \"bluebell:\" // 项目key前缀\n\tKe"
},
{
"path": "lesson35/bluebell/dao/redis/redis.go",
"chars": 583,
"preview": "package redis\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t\"github.com/go-redis/redis\"\n)\n\nvar (\n\tclient *redis.Client\n\tNil "
},
{
"path": "lesson35/bluebell/dao/redis/vote.go",
"chars": 2143,
"preview": "package redis\n\nimport (\n\t\"errors\"\n\t\"math\"\n\t\"time\"\n\n\t\"github.com/go-redis/redis\"\n)\n\n// 推荐阅读\n// 基于用户投票的相关算法:http://www.rua"
},
{
"path": "lesson35/bluebell/go.mod",
"chars": 711,
"preview": "module bluebell\n\ngo 1.14\n\nrequire (\n\tgithub.com/bwmarrin/snowflake v0.3.0\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatib"
},
{
"path": "lesson35/bluebell/go.sum",
"chars": 40156,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "lesson35/bluebell/logger/logger.go",
"chars": 3633,
"preview": "package logger\n\nimport (\n\t\"bluebell/setting\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"os\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t"
},
{
"path": "lesson35/bluebell/logic/community.go",
"chars": 300,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n)\n\nfunc GetCommunityList() ([]*models.Community, error)"
},
{
"path": "lesson35/bluebell/logic/post.go",
"chars": 2150,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/dao/redis\"\n\t\"bluebell/models\"\n\t\"bluebell/pkg/snowflake\"\n\n\t\"go.u"
},
{
"path": "lesson35/bluebell/logic/user.go",
"chars": 818,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n\t\"bluebell/pkg/jwt\"\n\t\"bluebell/pkg/snowflake\"\n)\n\n// 存放业"
},
{
"path": "lesson35/bluebell/logic/vote.go",
"chars": 947,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/redis\"\n\t\"bluebell/models\"\n\t\"strconv\"\n\n\t\"go.uber.org/zap\"\n)\n\n// 推荐阅读\n// 基于用户投票的相关算"
},
{
"path": "lesson35/bluebell/main.go",
"chars": 1352,
"preview": "package main\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/dao/redis\"\n\t\"bluebell/logger\"\n\t\"bluebell/"
},
{
"path": "lesson35/bluebell/middlewares/auth.go",
"chars": 1113,
"preview": "package middlewares\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/pkg/jwt\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n// J"
},
{
"path": "lesson35/bluebell/models/community.go",
"chars": 428,
"preview": "package models\n\nimport \"time\"\n\ntype Community struct {\n\tID int64 `json:\"id\" db:\"community_id\"`\n\tName string `json:\"na"
},
{
"path": "lesson35/bluebell/models/create_table.sql",
"chars": 2638,
"preview": "--\nCREATE TABLE `user` (\n `id` bigint(20) NOT NULL AUTO_INCREMENT,\n `user_id` bigint(20) NOT NULL,\n `username` "
},
{
"path": "lesson35/bluebell/models/params.go",
"chars": 672,
"preview": "package models\n\n// 定义请求的参数结构体\n\n// ParamSignUp 注册请求参数\ntype ParamSignUp struct {\n\tUsername string `json:\"username\" bindi"
},
{
"path": "lesson35/bluebell/models/post.go",
"chars": 721,
"preview": "package models\n\nimport \"time\"\n\n// 内存对齐概念\n\ntype Post struct {\n\tID int64 `json:\"id,string\" db:\"post_id\"`\n\tAut"
},
{
"path": "lesson35/bluebell/models/struct_test.go",
"chars": 360,
"preview": "package models\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"unsafe\"\n)\n\n// Go 内存对齐\n\ntype s1 struct {\n\ta int8 // 1\n\tb string // 3\n\tc in"
},
{
"path": "lesson35/bluebell/models/user.go",
"chars": 152,
"preview": "package models\n\ntype User struct {\n\tUserID int64 `db:\"user_id\"`\n\tUsername string `db:\"username\"`\n\tPassword string `db"
},
{
"path": "lesson35/bluebell/pkg/jwt/jwt.go",
"chars": 1238,
"preview": "package jwt\n\nimport (\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/spf13/viper\"\n\n\t\"github.com/dgrijalva/jwt-go\"\n)\n\nvar mySecret = []b"
},
{
"path": "lesson35/bluebell/pkg/snowflake/snowflake.go",
"chars": 384,
"preview": "package snowflake\n\nimport (\n\t\"time\"\n\n\tsf \"github.com/bwmarrin/snowflake\"\n)\n\nvar node *sf.Node\n\nfunc Init(startTime strin"
},
{
"path": "lesson35/bluebell/router/route.go",
"chars": 955,
"preview": "package router\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/logger\"\n\t\"bluebell/middlewares\"\n\t\"net/http\"\n\n\t\"github.com/gin"
},
{
"path": "lesson35/bluebell/setting/setting.go",
"chars": 2501,
"preview": "package setting\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/fsnotify/fsnotify\"\n\t\"github.com/spf13/viper\"\n)\n\nvar Conf = new(AppConfig)"
},
{
"path": "lesson68/bluebell/.air.conf",
"chars": 884,
"preview": "# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件\n\n# 工作目录\n# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下\nroot = \".\"\ntmp"
},
{
"path": "lesson68/bluebell/Makefile",
"chars": 479,
"preview": ".PHONY: all build run gotool clean help\n\nBINARY=\"xx\"\n\nall: gotool build\n\nbuild:\n\tCGO_ENABLED=0 GOOS=linux GOARCH=amd64 g"
},
{
"path": "lesson68/bluebell/conf/config.yaml",
"chars": 442,
"preview": "name: \"bluebell\"\nmode: \"dev\"\nport: 8084\nversion: \"v0.0.1\"\nstart_time: \"2020-07-01\"\nmachine_id: 1\n\nauth:\n jwt_expire: 87"
},
{
"path": "lesson68/bluebell/controller/code.go",
"chars": 620,
"preview": "package controller\n\ntype ResCode int64\n\nconst (\n\tCodeSuccess ResCode = 1000 + iota\n\tCodeInvalidParam\n\tCodeUserExist\n\tCod"
},
{
"path": "lesson68/bluebell/controller/community.go",
"chars": 916,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"go.uber.org/zap\"\n)\n\n// ---- 跟社区"
},
{
"path": "lesson68/bluebell/controller/post.go",
"chars": 3349,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"go.uber.org/"
},
{
"path": "lesson68/bluebell/controller/request.go",
"chars": 756,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nconst CtxUserIDKey = \"userID\"\n\nvar Err"
},
{
"path": "lesson68/bluebell/controller/response.go",
"chars": 759,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n/*\n{\n\t\"code\": 10000, // 程序中的错误码\n\t\"msg\": xx, "
},
{
"path": "lesson68/bluebell/controller/user.go",
"chars": 1914,
"preview": "package controller\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/g"
},
{
"path": "lesson68/bluebell/controller/validator.go",
"chars": 2206,
"preview": "package controller\n\nimport (\n\t\"bluebell/models\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin/binding\"\n\t\"gith"
},
{
"path": "lesson68/bluebell/controller/vote.go",
"chars": 1045,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\n\t\"go.uber.org/zap\"\n\n\t\"github.com/go-playground/valida"
},
{
"path": "lesson68/bluebell/dao/mysql/community.go",
"chars": 815,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"database/sql\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc GetCommunityList() (communityList"
},
{
"path": "lesson68/bluebell/dao/mysql/error_code.go",
"chars": 219,
"preview": "package mysql\n\nimport \"errors\"\n\nvar (\n\tErrorUserExist = errors.New(\"用户已存在\")\n\tErrorUserNotExist = errors.New(\"用户"
},
{
"path": "lesson68/bluebell/dao/mysql/mysql.go",
"chars": 572,
"preview": "package mysql\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"github.com/jmoiron/sqlx\"\n)\n\nva"
},
{
"path": "lesson68/bluebell/dao/mysql/post.go",
"chars": 1486,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"strings\"\n\n\t\"github.com/jmoiron/sqlx\"\n)\n\n// CreatePost 创建帖子\nfunc CreatePost("
},
{
"path": "lesson68/bluebell/dao/mysql/user.go",
"chars": 1584,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"crypto/md5\"\n\t\"database/sql\"\n\t\"encoding/hex\"\n)\n\n// 把每一步数据库操作封装成函数\n// 待logic层"
},
{
"path": "lesson68/bluebell/dao/redis/keys.go",
"chars": 424,
"preview": "package redis\n\n// redis key\n\n// redis key注意使用命名空间的方式,方便查询和拆分\n\nconst (\n\tPrefix = \"bluebell:\" // 项目key前缀\n\tKe"
},
{
"path": "lesson68/bluebell/dao/redis/post.go",
"chars": 2185,
"preview": "package redis\n\nimport (\n\t\"bluebell/models\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/go-redis/redis\"\n)\n\nfunc getIDsFormKey(key st"
},
{
"path": "lesson68/bluebell/dao/redis/redis.go",
"chars": 583,
"preview": "package redis\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t\"github.com/go-redis/redis\"\n)\n\nvar (\n\tclient *redis.Client\n\tNil "
},
{
"path": "lesson68/bluebell/dao/redis/vote.go",
"chars": 2417,
"preview": "package redis\n\nimport (\n\t\"errors\"\n\t\"math\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/go-redis/redis\"\n)\n\n// 推荐阅读\n// 基于用户投票的相关算法:htt"
},
{
"path": "lesson68/bluebell/go.mod",
"chars": 711,
"preview": "module bluebell\n\ngo 1.14\n\nrequire (\n\tgithub.com/bwmarrin/snowflake v0.3.0\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatib"
},
{
"path": "lesson68/bluebell/go.sum",
"chars": 40156,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "lesson68/bluebell/logger/logger.go",
"chars": 3633,
"preview": "package logger\n\nimport (\n\t\"bluebell/setting\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"os\"\n\t\"runtime/debug\"\n\t\"strings\"\n\t"
},
{
"path": "lesson68/bluebell/logic/community.go",
"chars": 300,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n)\n\nfunc GetCommunityList() ([]*models.Community, error)"
},
{
"path": "lesson68/bluebell/logic/post.go",
"chars": 5268,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/dao/redis\"\n\t\"bluebell/models\"\n\t\"bluebell/pkg/snowflake\"\n\n\t\"go.u"
},
{
"path": "lesson68/bluebell/logic/user.go",
"chars": 818,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/models\"\n\t\"bluebell/pkg/jwt\"\n\t\"bluebell/pkg/snowflake\"\n)\n\n// 存放业"
},
{
"path": "lesson68/bluebell/logic/vote.go",
"chars": 947,
"preview": "package logic\n\nimport (\n\t\"bluebell/dao/redis\"\n\t\"bluebell/models\"\n\t\"strconv\"\n\n\t\"go.uber.org/zap\"\n)\n\n// 推荐阅读\n// 基于用户投票的相关算"
},
{
"path": "lesson68/bluebell/main.go",
"chars": 1352,
"preview": "package main\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/dao/redis\"\n\t\"bluebell/logger\"\n\t\"bluebell/"
},
{
"path": "lesson68/bluebell/middlewares/auth.go",
"chars": 1113,
"preview": "package middlewares\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/pkg/jwt\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n// J"
},
{
"path": "lesson68/bluebell/models/community.go",
"chars": 428,
"preview": "package models\n\nimport \"time\"\n\ntype Community struct {\n\tID int64 `json:\"id\" db:\"community_id\"`\n\tName string `json:\"na"
},
{
"path": "lesson68/bluebell/models/create_table.sql",
"chars": 2638,
"preview": "--\nCREATE TABLE `user` (\n `id` bigint(20) NOT NULL AUTO_INCREMENT,\n `user_id` bigint(20) NOT NULL,\n `username` "
},
{
"path": "lesson68/bluebell/models/params.go",
"chars": 1005,
"preview": "package models\n\n// 定义请求的参数结构体\n\nconst (\n\tOrderTime = \"time\"\n\tOrderScore = \"score\"\n)\n\n// ParamSignUp 注册请求参数\ntype ParamSig"
},
{
"path": "lesson68/bluebell/models/post.go",
"chars": 776,
"preview": "package models\n\nimport \"time\"\n\n// 内存对齐概念\n\ntype Post struct {\n\tID int64 `json:\"id,string\" db:\"post_id\"`\n\tAut"
},
{
"path": "lesson68/bluebell/models/struct_test.go",
"chars": 360,
"preview": "package models\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"unsafe\"\n)\n\n// Go 内存对齐\n\ntype s1 struct {\n\ta int8 // 1\n\tb string // 3\n\tc in"
},
{
"path": "lesson68/bluebell/models/user.go",
"chars": 152,
"preview": "package models\n\ntype User struct {\n\tUserID int64 `db:\"user_id\"`\n\tUsername string `db:\"username\"`\n\tPassword string `db"
},
{
"path": "lesson68/bluebell/pkg/jwt/jwt.go",
"chars": 1238,
"preview": "package jwt\n\nimport (\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/spf13/viper\"\n\n\t\"github.com/dgrijalva/jwt-go\"\n)\n\nvar mySecret = []b"
},
{
"path": "lesson68/bluebell/pkg/snowflake/snowflake.go",
"chars": 384,
"preview": "package snowflake\n\nimport (\n\t\"time\"\n\n\tsf \"github.com/bwmarrin/snowflake\"\n)\n\nvar node *sf.Node\n\nfunc Init(startTime strin"
},
{
"path": "lesson68/bluebell/router/route.go",
"chars": 1025,
"preview": "package router\n\nimport (\n\t\"bluebell/controller\"\n\t\"bluebell/logger\"\n\t\"bluebell/middlewares\"\n\t\"net/http\"\n\n\t\"github.com/gin"
},
{
"path": "lesson68/bluebell/setting/setting.go",
"chars": 2501,
"preview": "package setting\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/fsnotify/fsnotify\"\n\t\"github.com/spf13/viper\"\n)\n\nvar Conf = new(AppConfig)"
},
{
"path": "lesson69/bluebell/.air.conf",
"chars": 897,
"preview": "# [Air](https://github.com/cosmtrek/air) TOML 格式的配置文件\n\n# 工作目录\n# 使用 . 或绝对路径,请注意 `tmp_dir` 目录必须在 `root` 目录下\nroot = \".\"\ntmp"
},
{
"path": "lesson69/bluebell/Makefile",
"chars": 479,
"preview": ".PHONY: all build run gotool clean help\n\nBINARY=\"xx\"\n\nall: gotool build\n\nbuild:\n\tCGO_ENABLED=0 GOOS=linux GOARCH=amd64 g"
},
{
"path": "lesson69/bluebell/conf/config.yaml",
"chars": 442,
"preview": "name: \"bluebell\"\nmode: \"dev\"\nport: 8084\nversion: \"v0.0.1\"\nstart_time: \"2020-07-01\"\nmachine_id: 1\n\nauth:\n jwt_expire: 87"
},
{
"path": "lesson69/bluebell/controller/code.go",
"chars": 620,
"preview": "package controller\n\ntype ResCode int64\n\nconst (\n\tCodeSuccess ResCode = 1000 + iota\n\tCodeInvalidParam\n\tCodeUserExist\n\tCod"
},
{
"path": "lesson69/bluebell/controller/community.go",
"chars": 916,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"go.uber.org/zap\"\n)\n\n// ---- 跟社区"
},
{
"path": "lesson69/bluebell/controller/doc_response_models.go",
"chars": 316,
"preview": "package controller\n\nimport \"bluebell/models\"\n\n// 专门用来放接口文档用到的model\n// 因为我们的接口文档返回的数据格式是一致的,但是具体的data类型不一致\n\ntype _Respons"
},
{
"path": "lesson69/bluebell/controller/post.go",
"chars": 3603,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n\t\"go.uber.org/"
},
{
"path": "lesson69/bluebell/controller/request.go",
"chars": 756,
"preview": "package controller\n\nimport (\n\t\"errors\"\n\t\"strconv\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\nconst CtxUserIDKey = \"userID\"\n\nvar Err"
},
{
"path": "lesson69/bluebell/controller/response.go",
"chars": 759,
"preview": "package controller\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/gin-gonic/gin\"\n)\n\n/*\n{\n\t\"code\": 10000, // 程序中的错误码\n\t\"msg\": xx, "
},
{
"path": "lesson69/bluebell/controller/user.go",
"chars": 1914,
"preview": "package controller\n\nimport (\n\t\"bluebell/dao/mysql\"\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/g"
},
{
"path": "lesson69/bluebell/controller/validator.go",
"chars": 2206,
"preview": "package controller\n\nimport (\n\t\"bluebell/models\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/gin-gonic/gin/binding\"\n\t\"gith"
},
{
"path": "lesson69/bluebell/controller/vote.go",
"chars": 1045,
"preview": "package controller\n\nimport (\n\t\"bluebell/logic\"\n\t\"bluebell/models\"\n\n\t\"go.uber.org/zap\"\n\n\t\"github.com/go-playground/valida"
},
{
"path": "lesson69/bluebell/dao/mysql/community.go",
"chars": 815,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"database/sql\"\n\n\t\"go.uber.org/zap\"\n)\n\nfunc GetCommunityList() (communityList"
},
{
"path": "lesson69/bluebell/dao/mysql/error_code.go",
"chars": 219,
"preview": "package mysql\n\nimport \"errors\"\n\nvar (\n\tErrorUserExist = errors.New(\"用户已存在\")\n\tErrorUserNotExist = errors.New(\"用户"
},
{
"path": "lesson69/bluebell/dao/mysql/mysql.go",
"chars": 572,
"preview": "package mysql\n\nimport (\n\t\"bluebell/setting\"\n\t\"fmt\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"github.com/jmoiron/sqlx\"\n)\n\nva"
},
{
"path": "lesson69/bluebell/dao/mysql/post.go",
"chars": 1486,
"preview": "package mysql\n\nimport (\n\t\"bluebell/models\"\n\t\"strings\"\n\n\t\"github.com/jmoiron/sqlx\"\n)\n\n// CreatePost 创建帖子\nfunc CreatePost("
}
]
// ... and 245 more files (download for full content)
About this extraction
This page contains the full source code of the Q1mi/goweb_pro GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 445 files (147.4 MB), approximately 638.1k tokens, and a symbol index with 1754 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.