-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第一次提交 #21
base: main
Are you sure you want to change the base?
第一次提交 #21
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
FROM golang:alpine AS builder | ||
|
||
# 为我们的镜像设置必要的环境变量 | ||
ENV GO111MODULE=on \ | ||
GOPROXY=https://goproxy.cn,direct \ | ||
CGO_ENABLED=0 \ | ||
GOOS=linux \ | ||
GOARCH=amd64 | ||
|
||
# 移动到工作目录:/build | ||
WORKDIR /build | ||
|
||
# 将代码复制到容器中 | ||
COPY . . | ||
|
||
# 将我们的代码编译成二进制可执行文件 app | ||
RUN go build -o app . | ||
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider adding build flags for optimization. The current build command is functional but could be optimized further. Consider adding flags to reduce binary size and improve performance: RUN go build -ldflags="-s -w" -o app . The Additionally, you might want to add a step to run tests before building: RUN go test ./...
RUN go build -ldflags="-s -w" -o app . This ensures that all tests pass before creating the final binary. |
||
|
||
################### | ||
# 接下来创建一个小镜像 | ||
################### | ||
FROM scratch | ||
|
||
# 从builder镜像中把/dist/app 拷贝到当前目录 | ||
COPY --from=builder /build/app / | ||
|
||
# 需要运行的命令 | ||
ENTRYPOINT ["/app"] |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,43 @@ | ||||||||||||||
module sample-app | ||||||||||||||
|
||||||||||||||
go 1.23.1 | ||||||||||||||
Comment on lines
+1
to
+3
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect Go version specified The Go version specified (1.23.1) is not a valid Go version. As of October 2024, the latest stable version is in the 1.22.x series. Please update the Go version to a valid, stable version. For example: -go 1.23.1
+go 1.22.0 Make sure to test your code with the corrected Go version to ensure compatibility. 📝 Committable suggestion
Suggested change
|
||||||||||||||
|
||||||||||||||
require ( | ||||||||||||||
filippo.io/edwards25519 v1.1.0 // indirect | ||||||||||||||
github.com/bytedance/sonic v1.12.3 // indirect | ||||||||||||||
github.com/bytedance/sonic/loader v0.2.0 // indirect | ||||||||||||||
github.com/cloudwego/base64x v0.1.4 // indirect | ||||||||||||||
github.com/cloudwego/iasm v0.2.0 // indirect | ||||||||||||||
github.com/gabriel-vasile/mimetype v1.4.5 // indirect | ||||||||||||||
github.com/gin-contrib/sessions v1.0.1 // indirect | ||||||||||||||
github.com/gin-contrib/sse v0.1.0 // indirect | ||||||||||||||
github.com/gin-gonic/gin v1.10.0 // indirect | ||||||||||||||
github.com/go-playground/locales v0.14.1 // indirect | ||||||||||||||
github.com/go-playground/universal-translator v0.18.1 // indirect | ||||||||||||||
github.com/go-playground/validator/v10 v10.22.1 // indirect | ||||||||||||||
github.com/go-sql-driver/mysql v1.8.1 // indirect | ||||||||||||||
github.com/goccy/go-json v0.10.3 // indirect | ||||||||||||||
github.com/gorilla/context v1.1.2 // indirect | ||||||||||||||
github.com/gorilla/securecookie v1.1.2 // indirect | ||||||||||||||
github.com/gorilla/sessions v1.2.2 // indirect | ||||||||||||||
github.com/jinzhu/inflection v1.0.0 // indirect | ||||||||||||||
github.com/jinzhu/now v1.1.5 // indirect | ||||||||||||||
github.com/json-iterator/go v1.1.12 // indirect | ||||||||||||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect | ||||||||||||||
github.com/leodido/go-urn v1.4.0 // indirect | ||||||||||||||
github.com/mattn/go-isatty v0.0.20 // indirect | ||||||||||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | ||||||||||||||
github.com/modern-go/reflect2 v1.0.2 // indirect | ||||||||||||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect | ||||||||||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect | ||||||||||||||
github.com/ugorji/go/codec v1.2.12 // indirect | ||||||||||||||
golang.org/x/arch v0.10.0 // indirect | ||||||||||||||
golang.org/x/crypto v0.27.0 // indirect | ||||||||||||||
golang.org/x/net v0.29.0 // indirect | ||||||||||||||
golang.org/x/sys v0.25.0 // indirect | ||||||||||||||
golang.org/x/text v0.18.0 // indirect | ||||||||||||||
google.golang.org/protobuf v1.34.2 // indirect | ||||||||||||||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||||||||||||||
gorm.io/driver/mysql v1.5.7 // indirect | ||||||||||||||
gorm.io/gorm v1.25.12 // indirect | ||||||||||||||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= | ||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= | ||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= | ||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= | ||
github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= | ||
github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= | ||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= | ||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= | ||
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= | ||
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= | ||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= | ||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= | ||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= | ||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= | ||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= | ||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= | ||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= | ||
github.com/gin-contrib/sessions v1.0.1 h1:3hsJyNs7v7N8OtelFmYXFrulAf6zSR7nW/putcPEHxI= | ||
github.com/gin-contrib/sessions v1.0.1/go.mod h1:ouxSFM24/OgIud5MJYQJLpy6AwxQ5EYO9yLhbtObGkM= | ||
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.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= | ||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= | ||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= | ||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= | ||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= | ||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= | ||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= | ||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= | ||
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= | ||
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= | ||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= | ||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= | ||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= | ||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= | ||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | ||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= | ||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= | ||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= | ||
github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM= | ||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= | ||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= | ||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= | ||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= | ||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= | ||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= | ||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= | ||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= | ||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= | ||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= | ||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | ||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= | ||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= | ||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= | ||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= | ||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= | ||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= | ||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= | ||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= | ||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | ||
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 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= | ||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | ||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= | ||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= | ||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= | ||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= | ||
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/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= | ||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= | ||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= | ||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= | ||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= | ||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= | ||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= | ||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= | ||
golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8= | ||
golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= | ||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= | ||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= | ||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= | ||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= | ||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= | ||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= | ||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= | ||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= | ||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= | ||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= | ||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= | ||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= | ||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= | ||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= | ||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= | ||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= | ||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= | ||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= | ||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= | ||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= | ||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= | ||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= | ||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,189 @@ | ||||||||
package main | ||||||||
|
||||||||
import ( | ||||||||
"log" | ||||||||
"strconv" | ||||||||
"time" | ||||||||
|
||||||||
"github.com/gin-contrib/sessions" | ||||||||
"github.com/gin-contrib/sessions/cookie" | ||||||||
"github.com/gin-gonic/gin" | ||||||||
"gorm.io/driver/mysql" | ||||||||
"gorm.io/gorm" | ||||||||
) | ||||||||
|
||||||||
// 用户结构体 | ||||||||
type User struct { | ||||||||
gorm.Model | ||||||||
Username string `gorm:"unique;not null"` | ||||||||
Password string `gorm:"not null"` | ||||||||
IsManager bool | ||||||||
} | ||||||||
|
||||||||
type KeyWord struct { | ||||||||
Keyword string | ||||||||
} | ||||||||
|
||||||||
// 问题结构体 | ||||||||
type Question struct { | ||||||||
gorm.Model | ||||||||
Title string | ||||||||
Content string | ||||||||
UserID uint | ||||||||
Answers []Answer `gorm:"foreignKey:QuestionID"` | ||||||||
IsDeleted bool | ||||||||
Deleted_Time time.Time | ||||||||
} | ||||||||
|
||||||||
type AgreeOrNot struct { | ||||||||
AgreeNum uint | ||||||||
DisagreeNum uint | ||||||||
} | ||||||||
|
||||||||
// 答案中的评论结构体 | ||||||||
type Comment struct { | ||||||||
gorm.Model | ||||||||
AgreeOrNot | ||||||||
Content string | ||||||||
UserID uint | ||||||||
AnswerID uint | ||||||||
} | ||||||||
Comment on lines
+44
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Reconsider embedding The |
||||||||
|
||||||||
// 回复评论结构体 | ||||||||
type ReplyComment struct { | ||||||||
gorm.Model | ||||||||
CommentUserID uint | ||||||||
CommentID uint | ||||||||
ReplyCommentID uint | ||||||||
ReplyUserID uint | ||||||||
} | ||||||||
|
||||||||
// 答案结构体 | ||||||||
type Answer struct { | ||||||||
gorm.Model | ||||||||
AgreeOrNot | ||||||||
Content string | ||||||||
UserID uint | ||||||||
QuestionID uint | ||||||||
IsDeleted bool | ||||||||
// 评论 | ||||||||
Comments []Comment `gorm:"foreignKey:AnswerID"` | ||||||||
} | ||||||||
|
||||||||
var db *gorm.DB | ||||||||
|
||||||||
const max_question_num = 30 | ||||||||
|
||||||||
var resultCh chan Question = make(chan Question, max_question_num) | ||||||||
Comment on lines
+73
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider refactoring global variables Global variables like
Example refactoring: type App struct {
DB *gorm.DB
ResultCh chan Question
}
func NewApp(db *gorm.DB) *App {
return &App{
DB: db,
ResultCh: make(chan Question, max_question_num),
}
} This approach would make the code more modular and easier to test. |
||||||||
|
||||||||
func main() { | ||||||||
var err error | ||||||||
// 使用mysql.Open创建Dialector实例 | ||||||||
dialector := mysql.Open("root:123Qbz123@tcp(localhost:3306)/go_web_1?charset=utf8mb4&parseTime=True&loc=Local") | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security Risk: Hardcoded Database Credentials The database credentials are hardcoded in the code, which poses a significant security risk. Exposing sensitive information like usernames and passwords in the codebase can lead to unauthorized access if the code is ever compromised. It is recommended to use environment variables or a secure configuration management system to store and access sensitive data. Apply this diff to remove the hardcoded credentials: - dialector := mysql.Open("root:123Qbz123@tcp(localhost:3306)/go_web_1?charset=utf8mb4&parseTime=True&loc=Local")
+ dsn := os.Getenv("DATABASE_DSN")
+ dialector := mysql.Open(dsn) Make sure to set the 📝 Committable suggestion
Suggested change
|
||||||||
// 将Dialector实例传递给gorm.Open | ||||||||
db, err = gorm.Open(dialector, &gorm.Config{}) | ||||||||
if err != nil { | ||||||||
log.Fatal("数据库连接失败:", err) | ||||||||
} | ||||||||
db.AutoMigrate(&User{}, &Question{}, &Answer{}, &Comment{}, &ReplyComment{}) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Caution: Auto-migration in production Using Example: if os.Getenv("ENVIRONMENT") != "production" {
db.AutoMigrate(&User{}, &Question{}, &Answer{}, &Comment{}, &ReplyComment{})
} else {
log.Println("Skipping auto-migration in production. Please run migrations manually.")
} |
||||||||
|
||||||||
r := gin.Default() | ||||||||
|
||||||||
// 设置会话 | ||||||||
store := cookie.NewStore([]byte("secret")) | ||||||||
r.Use(sessions.Sessions("mysession", store)) | ||||||||
|
||||||||
v_post := r.Group("/") | ||||||||
{ | ||||||||
//注册 | ||||||||
v_post.POST("register", Register) | ||||||||
//登录 | ||||||||
v_post.POST("login", Login) | ||||||||
// 提出问题 | ||||||||
v_post.POST("questions", CreateQuestion) | ||||||||
// 回答问题 | ||||||||
v_post.POST("questions/:question_id/answers", CreateAnswer) | ||||||||
// 评论答案,需要查询参数,传入答案id和所属问题id | ||||||||
v_post.POST("questions/answers/comments", CreateCommentToAnswer) | ||||||||
//回复其他评论,需要传入查询参数,传入其他评论id和所属答案id | ||||||||
v_post.POST("questions/answers/comments/comments", CreateReplyToComment) | ||||||||
|
||||||||
} | ||||||||
|
||||||||
v_get := r.Group("/") | ||||||||
{ | ||||||||
// 查看某个用户提出的问题 | ||||||||
v_get.GET(":user_id/questions", GetQuestions) | ||||||||
// 查看某问题的答案 | ||||||||
v_get.GET("questions/:question_id/answers", GetAnswers) | ||||||||
// 查看被逻辑删除删除的问题 | ||||||||
v_get.GET("deleted_questions", GetDeletedQuestions) | ||||||||
//按关键词搜索问题 | ||||||||
v_get.GET("questions/search", SearchQuestionsByKeyword) | ||||||||
//查看对自己评论的回复 | ||||||||
v_get.GET("questions/answers/comments/comments", GetReplysToSelf) | ||||||||
|
||||||||
} | ||||||||
|
||||||||
v_put := r.Group("/") | ||||||||
{ | ||||||||
//申请管理员权限 | ||||||||
v_put.PUT("users", ApplyManager) | ||||||||
// 更新问题内容 | ||||||||
v_put.PUT("questions/:id", UpdateQuestionContent) | ||||||||
// 恢复被逻辑删除的问题 | ||||||||
v_put.PUT("deleted_questions/:id", RestoreQuestion) | ||||||||
// 赞同答案 | ||||||||
v_put.PUT("questions/answers/agree", AgreeAnswer) | ||||||||
// 反对答案 | ||||||||
v_put.PUT("questions/answers/disagree", DisagreeAnswer) | ||||||||
Comment on lines
+137
to
+139
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider Using POST Instead of PUT for Action Endpoints The routes for agreeing and disagreeing with an answer are using the PUT method: v_put.PUT("questions/answers/agree", AgreeAnswer)
v_put.PUT("questions/answers/disagree", DisagreeAnswer) In RESTful API design, actions that do not idempotently update a resource state are often better suited to the POST method. Consider using POST for these endpoints to align with RESTful principles. Apply this diff to update the HTTP methods: - v_put.PUT("questions/answers/agree", AgreeAnswer)
+ v_post.POST("questions/answers/agree", AgreeAnswer)
- v_put.PUT("questions/answers/disagree", DisagreeAnswer)
+ v_post.POST("questions/answers/disagree", DisagreeAnswer) |
||||||||
//恢复被删除的答案,需要传入查询参数,传入答案id和所属问题id | ||||||||
v_put.PUT("questions/answers/restore", RestoreAnswer) | ||||||||
//恢复对答案的评论,需要传入查询参数,传入评论id和所属答案id | ||||||||
v_put.PUT("questions/answers/comments/restore", RestoreCommentToAnswer) | ||||||||
} | ||||||||
|
||||||||
v_delete := r.Group("/") | ||||||||
{ | ||||||||
// 逻辑删除问题 | ||||||||
v_delete.DELETE("questions/:id", DeleteQuestion) | ||||||||
// 永久删除问题 | ||||||||
v_delete.DELETE("deleted_questions/:id", DeleteQuestionForever) | ||||||||
// 永久删除答案 | ||||||||
v_delete.DELETE("questions/answers", DeleteAnswerForever) | ||||||||
//逻辑删除答案,需要传入查询参数,传入答案id和所属问题id | ||||||||
v_delete.DELETE("questions/deleted_answers", DeleteAnswer) | ||||||||
Comment on lines
+153
to
+155
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use Path Parameters Instead of Query Parameters for Resource Identification The DELETE routes for answers require query parameters to identify the answer and its associated question: v_delete.DELETE("questions/answers", DeleteAnswerForever)
v_delete.DELETE("questions/deleted_answers", DeleteAnswer) It's recommended to use path parameters to uniquely identify resources in RESTful APIs. This enhances clarity and aligns with RESTful design principles. Consider modifying the routes as follows: - v_delete.DELETE("questions/answers", DeleteAnswerForever)
+ v_delete.DELETE("questions/:question_id/answers/:answer_id", DeleteAnswerForever)
- v_delete.DELETE("questions/deleted_answers", DeleteAnswer)
+ v_delete.DELETE("questions/:question_id/deleted_answers/:answer_id", DeleteAnswer) Update the corresponding handler functions to accept the path parameters. |
||||||||
//软删除评论,需要传入查询参数,传入评论id和所属答案id | ||||||||
v_delete.DELETE("questions/answers/comments", DeleteCommentToAnswer) | ||||||||
//永久删除评论,需要传入查询参数,传入评论id和所属答案id | ||||||||
v_delete.DELETE("questions/answers/deleted_comments", DeleteCommentForever) | ||||||||
} | ||||||||
|
||||||||
//统计每个被删除的删除天数,超过15天则永久删除 | ||||||||
go func() { | ||||||||
flag := true | ||||||||
for flag { | ||||||||
time.Sleep(time.Second * 30) // 添加延迟 | ||||||||
deleted_questions.mux.Lock() | ||||||||
for _, q := range deleted_questions.deleted { | ||||||||
if q.IsDeleted && time.Since(q.Deleted_Time) > time.Second*10 { | ||||||||
Comment on lines
+163
to
+169
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistency Between Comment and Code Regarding Deletion Timing The comment suggests that deleted questions should be permanently removed after 15 days: //统计每个被删除的删除天数,超过15天则永久删除 However, the code deletes questions after they have been deleted for more than 10 seconds: if q.IsDeleted && time.Since(q.Deleted_Time) > time.Second*10 { This inconsistency could result in questions being deleted much sooner than intended. Please adjust the code to match the intended deletion threshold. Apply this diff to correct the deletion timing: - if q.IsDeleted && time.Since(q.Deleted_Time) > time.Second*10 {
+ if q.IsDeleted && time.Since(q.Deleted_Time) > time.Hour*24*15 { This change sets the threshold to 15 days. |
||||||||
resultCh <- q | ||||||||
db.Unscoped().Delete(&q) | ||||||||
} | ||||||||
} | ||||||||
deleted_questions.mux.Unlock() | ||||||||
} | ||||||||
Comment on lines
+167
to
+175
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Undefined Variable: 'deleted_questions' The variable |
||||||||
}() | ||||||||
|
||||||||
// 收集结果 | ||||||||
go func() { | ||||||||
for { | ||||||||
select { | ||||||||
case q := <-resultCh: | ||||||||
delete(deleted_questions.deleted, strconv.FormatUint(uint64(q.ID), 10)) | ||||||||
Comment on lines
+182
to
+183
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Undefined Variable: 'deleted_questions' Again, the variable delete(deleted_questions.deleted, strconv.FormatUint(uint64(q.ID), 10)) This will cause a runtime error. Ensure that |
||||||||
} | ||||||||
} | ||||||||
}() | ||||||||
Comment on lines
+179
to
+186
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Potential issue: Unbuffered channel usage The goroutine collecting results from Example: stopCh := make(chan struct{})
go func() {
for {
select {
case q := <-resultCh:
delete(deleted_questions.deleted, strconv.FormatUint(uint64(q.ID), 10))
case <-stopCh:
return
}
}
}()
// In the main function, before r.Run(":8080"):
defer close(stopCh) This allows the goroutine to be properly stopped when the main function exits. |
||||||||
|
||||||||
r.Run(":8080") | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider using environment variable for port configuration Hardcoding the port number (8080) reduces the flexibility of the application in different environments. Consider using an environment variable to set the port: import "os"
// ...
port := os.Getenv("PORT")
if port == "" {
port = "8080" // Default port if not set
}
r.Run(":" + port) This change allows easy configuration of the port through environment variables, making the application more flexible for different deployment scenarios. |
||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider optimizing the file copying process.
While setting the working directory is good, copying all files from the build context might include unnecessary files in the image.
Consider being more selective about what files are copied:
This approach:
This can improve build times by leveraging Docker's layer caching mechanism.