diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 6851d1e..0ba6394 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -24,7 +24,7 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} - cache: true + cache: false - name: Go cache info run: | diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index dafd28e..07c0580 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -351,3 +351,46 @@ type LogFilter struct { | Model | `internal/model/` | | Wire | `internal/wire/` | | Cache | `internal/cache/` | + +--- + +## 11. Wire 生成的代码规范 + +### 11.1 禁止直接修改生成的文件 + +以下文件由 Wire 工具自动生成,**禁止直接修改**: + +- `cmd/server/wire_gen.go` +- `cmd/server/wire.go` 中的 Provider 函数签名由 Wire 维护 + +如果需要修改这些文件: +1. **修改源文件**(如 `wire.go` 中的结构) +2. **运行 `wire` 命令**重新生成 + +### 11.2 正确的修改流程 + +```bash +# 1. 修改 wire.go 或 wire/*.go +# 2. 运行 wire 重新生成 +go run -mod=mod github.com/google/wire/cmd/wire ./cmd/server +``` + +### 11.3 Provider 依赖添加 + +新增依赖时,必须同步修改: + +1. `wire/service.go` 中的 Provider 函数 +2. `wire/handler.go` 中的 Handler Provider 函数 +3. `cmd/server/wire.go` 中的 `ProvideRouter` 函数 +4. `wire/repository.go`(如需新增 Repository) +5. 重新运行 `wire ./cmd/server` 生成 `wire_gen.go` + +### 11.4 生成文件识别 + +``` +// Code generated by Wire. DO NOT EDIT. +//go:generate go run -mod=mod github.com/google/wire/cmd/wire +//go:build !wireinject +``` + +带以上标记的文件均为自动生成文件。 diff --git a/go.mod b/go.mod index adf5a16..b0625a3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module carrot_bbs -go 1.25.7 +go 1.26 require ( github.com/alicebob/miniredis/v2 v2.37.0 @@ -18,7 +18,7 @@ require ( github.com/spf13/viper v1.21.0 go.uber.org/zap v1.27.1 golang.org/x/crypto v0.49.0 - golang.org/x/image v0.37.0 + golang.org/x/image v0.38.0 google.golang.org/grpc v1.79.3 google.golang.org/protobuf v1.36.11 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df @@ -32,14 +32,14 @@ require ( github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect github.com/bytedance/gopkg v0.1.4 // indirect github.com/bytedance/sonic v1.15.0 // indirect - github.com/bytedance/sonic/loader v0.5.0 // indirect + github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/casbin/govaluate v1.10.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect - github.com/gin-contrib/sse v1.1.0 // indirect + github.com/gin-contrib/sse v1.1.1 // indirect github.com/glebarez/go-sqlite v1.22.0 // indirect github.com/glebarez/sqlite v1.11.0 // indirect github.com/go-ini/ini v1.67.0 // indirect @@ -54,12 +54,12 @@ require ( github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.8.0 // indirect + github.com/jackc/pgx/v5 v5.9.1 // indirect github.com/jackc/puddle/v2 v2.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/compress v1.18.4 // indirect + github.com/klauspost/compress v1.18.5 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/klauspost/crc32 v1.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect @@ -71,7 +71,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pelletier/go-toml/v2 v2.3.0 // indirect github.com/philhofer/fwd v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/quic-go/qpack v0.6.0 // indirect @@ -101,7 +101,7 @@ require ( golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.35.0 // indirect golang.org/x/tools v0.43.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gorm.io/driver/mysql v1.6.0 // indirect gorm.io/driver/sqlserver v1.6.3 // indirect @@ -109,5 +109,5 @@ require ( modernc.org/libc v1.70.0 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect - modernc.org/sqlite v1.47.0 // indirect + modernc.org/sqlite v1.48.0 // indirect ) diff --git a/go.sum b/go.sum index 60a4add..0bf4349 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= -github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= -github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI= +github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/casbin/casbin/v3 v3.10.0 h1:039ORla55vCeIZWd0LfzWFt1yiEA5X4W41xBW2bQuHs= github.com/casbin/casbin/v3 v3.10.0/go.mod h1:5rJbQr2e6AuuDDNxnPc5lQlC9nIgg6nS1zYwKXhpHC8= github.com/casbin/gorm-adapter/v3 v3.41.0 h1:Xhpi0tfRP9aKPDWDf6dgBxHZ9UM6IophxxPIEGWqCNM= @@ -68,8 +68,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= -github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= -github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko= +github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s= github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= @@ -115,8 +115,6 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= -github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= -github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -134,8 +132,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.8.0 h1:TYPDoleBBme0xGSAX3/+NujXXtpZn9HBONkQC7IEZSo= -github.com/jackc/pgx/v5 v5.8.0/go.mod h1:QVeDInX2m9VyzvNeiCJVjCkNFqzsNb43204HshNSZKw= +github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc= +github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= @@ -150,8 +148,8 @@ 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/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= -github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= @@ -192,8 +190,8 @@ github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3P github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM= +github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= @@ -301,8 +299,8 @@ golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5D golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.37.0 h1:ZiRjArKI8GwxZOoEtUfhrBtaCN+4b/7709dlT6SSnQA= -golang.org/x/image v0.37.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY= +golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE= +golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -401,8 +399,8 @@ golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5 h1:aJmi6DVGGIStN9Mobk/tZOOQUBbj0BPjZjjnOdoZKts= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260316180232-0b37fe3546d5/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7 h1:ndE4FoJqsIceKP2oYSnUZqhTdYufCYYkqwtFzfrhI7w= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= @@ -456,8 +454,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.47.0 h1:R1XyaNpoW4Et9yly+I2EeX7pBza/w+pmYee/0HJDyKk= -modernc.org/sqlite v1.47.0/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig= +modernc.org/sqlite v1.48.0 h1:ElZyLop3Q2mHYk5IFPPXADejZrlHu7APbpB0sF78bq4= +modernc.org/sqlite v1.48.0/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/internal/cache/cache.go b/internal/cache/cache.go index fe09972..802356c 100644 --- a/internal/cache/cache.go +++ b/internal/cache/cache.go @@ -17,9 +17,9 @@ var ErrKeyNotFound = errors.New("key not found") // Cache 缓存接口 type Cache interface { // Set 设置缓存值,支持TTL - Set(key string, value interface{}, ttl time.Duration) + Set(key string, value any, ttl time.Duration) // Get 获取缓存值 - Get(key string) (interface{}, bool) + Get(key string) (any, bool) // Delete 删除缓存 Delete(key string) // DeleteByPrefix 根据前缀删除缓存 @@ -35,13 +35,13 @@ type Cache interface { // ==================== Hash 操作 ==================== // HSet 设置 Hash 字段 - HSet(ctx context.Context, key string, field string, value interface{}) error + HSet(ctx context.Context, key string, field string, value any) error // HMSet 批量设置 Hash 字段 - HMSet(ctx context.Context, key string, values map[string]interface{}) error + HMSet(ctx context.Context, key string, values map[string]any) error // HGet 获取 Hash 字段值 HGet(ctx context.Context, key string, field string) (string, error) // HMGet 批量获取 Hash 字段值 - HMGet(ctx context.Context, key string, fields ...string) ([]interface{}, error) + HMGet(ctx context.Context, key string, fields ...string) ([]any, error) // HGetAll 获取 Hash 所有字段 HGetAll(ctx context.Context, key string) (map[string]string, error) // HDel 删除 Hash 字段 @@ -59,7 +59,7 @@ type Cache interface { // ZReplaceSortedSet 原子替换整个 ZSET(先删后批量写入) ZReplaceSortedSet(ctx context.Context, key string, members []redis.Z) error // ZRem 删除 Sorted Set 成员 - ZRem(ctx context.Context, key string, members ...interface{}) error + ZRem(ctx context.Context, key string, members ...any) error // ZCard 获取 Sorted Set 成员数量 ZCard(ctx context.Context, key string) (int64, error) @@ -145,7 +145,7 @@ func normalizePrefix(prefix string) string { return cmp.Or(settings.KeyPrefix, "") + ":" + prefix } -func SetWithJitter(c Cache, key string, value interface{}, ttl time.Duration, jitterRatio float64) { +func SetWithJitter(c Cache, key string, value any, ttl time.Duration, jitterRatio float64) { if !settings.Enabled { return } diff --git a/internal/cache/redis_cache.go b/internal/cache/redis_cache.go index b30d837..365763a 100644 --- a/internal/cache/redis_cache.go +++ b/internal/cache/redis_cache.go @@ -26,7 +26,7 @@ func NewRedisCache(client *redisPkg.Client) *RedisCache { } // Set 设置缓存值 -func (c *RedisCache) Set(key string, value interface{}, ttl time.Duration) { +func (c *RedisCache) Set(key string, value any, ttl time.Duration) { key = normalizeKey(key) // 将值序列化为JSON data, err := json.Marshal(value) @@ -49,7 +49,7 @@ func (c *RedisCache) Set(key string, value interface{}, ttl time.Duration) { } // Get 获取缓存值 -func (c *RedisCache) Get(key string) (interface{}, bool) { +func (c *RedisCache) Get(key string) (any, bool) { key = normalizeKey(key) data, err := c.client.Get(c.ctx, key) if err != nil { @@ -164,13 +164,13 @@ func (c *RedisCache) IncrementBy(key string, value int64) int64 { // ==================== RedisCache Hash 操作 ==================== // HSet 设置 Hash 字段 -func (c *RedisCache) HSet(ctx context.Context, key string, field string, value interface{}) error { +func (c *RedisCache) HSet(ctx context.Context, key string, field string, value any) error { key = normalizeKey(key) return c.client.HSet(ctx, key, field, value) } // HMSet 批量设置 Hash 字段 -func (c *RedisCache) HMSet(ctx context.Context, key string, values map[string]interface{}) error { +func (c *RedisCache) HMSet(ctx context.Context, key string, values map[string]any) error { key = normalizeKey(key) return c.client.HMSet(ctx, key, values) } @@ -182,7 +182,7 @@ func (c *RedisCache) HGet(ctx context.Context, key string, field string) (string } // HMGet 批量获取 Hash 字段值 -func (c *RedisCache) HMGet(ctx context.Context, key string, fields ...string) ([]interface{}, error) { +func (c *RedisCache) HMGet(ctx context.Context, key string, fields ...string) ([]any, error) { key = normalizeKey(key) return c.client.HMGet(ctx, key, fields...) } @@ -239,7 +239,7 @@ func (c *RedisCache) ZReplaceSortedSet(ctx context.Context, key string, members } // ZRem 删除 Sorted Set 成员 -func (c *RedisCache) ZRem(ctx context.Context, key string, members ...interface{}) error { +func (c *RedisCache) ZRem(ctx context.Context, key string, members ...any) error { key = normalizeKey(key) return c.client.ZRem(ctx, key, members...) } diff --git a/internal/config/config.go b/internal/config/config.go index 23f0504..1e73710 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -153,7 +153,7 @@ func Load(configPath string) (*Config, error) { viper.SetDefault("hot_rank.recent_fetch_limit", 500) viper.SetDefault("hot_rank.candidate_cap", 800) // WebRTC 默认值(Google 公共 STUN 服务器) - viper.SetDefault("webrtc.ice_servers", []map[string]interface{}{ + viper.SetDefault("webrtc.ice_servers", []map[string]any{ {"urls": []string{"stun:stun.l.google.com:19302"}}, }) // Report 默认值 diff --git a/internal/dto/dto.go b/internal/dto/dto.go index 4ebf053..012188c 100644 --- a/internal/dto/dto.go +++ b/internal/dto/dto.go @@ -516,15 +516,15 @@ type PushRecordListResponse struct { // SystemMessageResponse 系统消息响应 type SystemMessageResponse struct { - ID string `json:"id"` - SenderID string `json:"sender_id"` - ReceiverID string `json:"receiver_id"` - Content string `json:"content"` - Category string `json:"category"` - SystemType string `json:"system_type"` - ExtraData map[string]interface{} `json:"extra_data,omitempty"` - IsRead bool `json:"is_read"` - CreatedAt time.Time `json:"created_at"` + ID string `json:"id"` + SenderID string `json:"sender_id"` + ReceiverID string `json:"receiver_id"` + Content string `json:"content"` + Category string `json:"category"` + SystemType string `json:"system_type"` + ExtraData map[string]any `json:"extra_data,omitempty"` + IsRead bool `json:"is_read"` + CreatedAt time.Time `json:"created_at"` } // SystemMessageListResponse 系统消息列表响应 @@ -905,10 +905,10 @@ type VoteResultDTO struct { // WSResponse WebSocket响应结构体 type WSResponse struct { - Success bool `json:"success"` // 是否成功 - Action string `json:"action"` // 响应原action - Data interface{} `json:"data,omitempty"` // 响应数据 - Error string `json:"error,omitempty"` // 错误信息 + Success bool `json:"success"` // 是否成功 + Action string `json:"action"` // 响应原action + Data any `json:"data,omitempty"` // 响应数据 + Error string `json:"error,omitempty"` // 错误信息 } // ==================== Admin Post DTOs ==================== @@ -1212,13 +1212,13 @@ type CursorPageRequest struct { } // CursorPageResponse 游标分页响应(泛型版本) -// 注意:由于 Go 的限制,这里使用 interface{} 作为 Items 类型 +// 注意:由于 Go 的限制,这里使用 any 作为 Items 类型 // 实际使用时可以创建特定类型的响应结构体 type CursorPageResponse struct { - Items interface{} `json:"list"` - NextCursor string `json:"next_cursor,omitempty"` // 下一页游标 - PrevCursor string `json:"prev_cursor,omitempty"` // 上一页游标(可选) - HasMore bool `json:"has_more"` // 是否有更多数据 + Items any `json:"list"` + NextCursor string `json:"next_cursor,omitempty"` // 下一页游标 + PrevCursor string `json:"prev_cursor,omitempty"` // 上一页游标(可选) + HasMore bool `json:"has_more"` // 是否有更多数据 } // CursorPageMeta 分页元信息 diff --git a/internal/dto/notification_converter.go b/internal/dto/notification_converter.go index 102cf9f..49721be 100644 --- a/internal/dto/notification_converter.go +++ b/internal/dto/notification_converter.go @@ -54,7 +54,7 @@ func SystemMessageToResponse(msg *model.Message) *SystemMessageResponse { CreatedAt: msg.CreatedAt, } if msg.ExtraData != nil { - resp.ExtraData = map[string]interface{}{ + resp.ExtraData = map[string]any{ "actor_id": msg.ExtraData.ActorID, "actor_name": msg.ExtraData.ActorName, "avatar_url": msg.ExtraData.AvatarURL, @@ -92,7 +92,7 @@ func SystemNotificationToResponse(n *model.SystemNotification) *SystemMessageRes CreatedAt: n.CreatedAt, } if n.ExtraData != nil { - resp.ExtraData = map[string]interface{}{ + resp.ExtraData = map[string]any{ "actor_id": n.ExtraData.ActorID, "actor_id_str": n.ExtraData.ActorIDStr, "actor_name": n.ExtraData.ActorName, diff --git a/internal/dto/segment.go b/internal/dto/segment.go index 497e732..202ad76 100644 --- a/internal/dto/segment.go +++ b/internal/dto/segment.go @@ -9,7 +9,7 @@ import ( ) // ParseSegmentData 解析Segment数据到目标结构体 -func ParseSegmentData(segment model.MessageSegment, target interface{}) error { +func ParseSegmentData(segment model.MessageSegment, target any) error { dataBytes, err := json.Marshal(segment.Data) if err != nil { return err @@ -21,7 +21,7 @@ func ParseSegmentData(segment model.MessageSegment, target interface{}) error { func NewTextSegment(content string) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeText), - Data: map[string]interface{}{"text": content}, + Data: map[string]any{"text": content}, } } @@ -29,7 +29,7 @@ func NewTextSegment(content string) model.MessageSegment { func NewImageSegment(url string, width, height int, thumbnailURL string) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeImage), - Data: map[string]interface{}{ + Data: map[string]any{ "url": url, "width": width, "height": height, @@ -42,7 +42,7 @@ func NewImageSegment(url string, width, height int, thumbnailURL string) model.M func NewImageSegmentWithSize(url string, width, height int, thumbnailURL string, fileSize int64) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeImage), - Data: map[string]interface{}{ + Data: map[string]any{ "url": url, "width": width, "height": height, @@ -56,7 +56,7 @@ func NewImageSegmentWithSize(url string, width, height int, thumbnailURL string, func NewVoiceSegment(url string, duration int, fileSize int64) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeVoice), - Data: map[string]interface{}{ + Data: map[string]any{ "url": url, "duration": duration, "file_size": fileSize, @@ -68,7 +68,7 @@ func NewVoiceSegment(url string, duration int, fileSize int64) model.MessageSegm func NewVideoSegment(url string, width, height, duration int, thumbnailURL string, fileSize int64) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeVideo), - Data: map[string]interface{}{ + Data: map[string]any{ "url": url, "width": width, "height": height, @@ -83,7 +83,7 @@ func NewVideoSegment(url string, width, height, duration int, thumbnailURL strin func NewFileSegment(url, name string, size int64, mimeType string) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeFile), - Data: map[string]interface{}{ + Data: map[string]any{ "url": url, "name": name, "size": size, @@ -96,7 +96,7 @@ func NewFileSegment(url, name string, size int64, mimeType string) model.Message func NewAtSegment(userID string) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeAt), - Data: map[string]interface{}{ + Data: map[string]any{ "user_id": userID, }, } @@ -106,7 +106,7 @@ func NewAtSegment(userID string) model.MessageSegment { func NewAtAllSegment() model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeAt), - Data: map[string]interface{}{ + Data: map[string]any{ "user_id": "all", }, } @@ -116,7 +116,7 @@ func NewAtAllSegment() model.MessageSegment { func NewReplySegment(messageID string) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeReply), - Data: map[string]interface{}{"id": messageID}, + Data: map[string]any{"id": messageID}, } } @@ -124,7 +124,7 @@ func NewReplySegment(messageID string) model.MessageSegment { func NewFaceSegment(id int, name, url string) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeFace), - Data: map[string]interface{}{ + Data: map[string]any{ "id": id, "name": name, "url": url, @@ -136,7 +136,7 @@ func NewFaceSegment(id int, name, url string) model.MessageSegment { func NewLinkSegment(url, title, description, image string) model.MessageSegment { return model.MessageSegment{ Type: string(SegmentTypeLink), - Data: map[string]interface{}{ + Data: map[string]any{ "url": url, "title": title, "description": description, diff --git a/internal/grpc/runner/hub.go b/internal/grpc/runner/hub.go index 0ea6196..4b98d7a 100644 --- a/internal/grpc/runner/hub.go +++ b/internal/grpc/runner/hub.go @@ -236,13 +236,13 @@ func (h *RunnerHub) GetAvailableRunner(taskType runner.TaskType) (*RunnerConnect } // GetAllRunners 获取所有已连接的 Runner 信息 -func (h *RunnerHub) GetAllRunners() []map[string]interface{} { +func (h *RunnerHub) GetAllRunners() []map[string]any { h.mu.RLock() defer h.mu.RUnlock() - result := make([]map[string]interface{}, 0, len(h.runners)) + result := make([]map[string]any, 0, len(h.runners)) for id, conn := range h.runners { - result = append(result, map[string]interface{}{ + result = append(result, map[string]any{ "id": id, "version": conn.Version, "capabilities": conn.Capabilities, diff --git a/internal/grpc/runner/task_manager.go b/internal/grpc/runner/task_manager.go index 92a8a09..809921d 100644 --- a/internal/grpc/runner/task_manager.go +++ b/internal/grpc/runner/task_manager.go @@ -43,7 +43,7 @@ func NewTaskManager(hub *RunnerHub, timeout time.Duration, logger *zap.Logger) * } // SubmitTask 提交任务并等待结果 -func (tm *TaskManager) SubmitTask(ctx context.Context, taskType runner.TaskType, payload interface{}, callback TaskCallback) (*runner.Task, error) { +func (tm *TaskManager) SubmitTask(ctx context.Context, taskType runner.TaskType, payload any, callback TaskCallback) (*runner.Task, error) { payloadBytes, err := json.Marshal(payload) if err != nil { return nil, fmt.Errorf("failed to marshal payload: %w", err) @@ -89,7 +89,7 @@ func (tm *TaskManager) SubmitTask(ctx context.Context, taskType runner.TaskType, } // SubmitTaskSync 同步提交任务并等待结果 -func (tm *TaskManager) SubmitTaskSync(ctx context.Context, taskType runner.TaskType, payload interface{}) (*runner.TaskResult, error) { +func (tm *TaskManager) SubmitTaskSync(ctx context.Context, taskType runner.TaskType, payload any) (*runner.TaskResult, error) { resultChan := make(chan *runner.TaskResult, 1) task, err := tm.SubmitTask(ctx, taskType, payload, func(result *runner.TaskResult) { diff --git a/internal/handler/admin_dashboard_handler.go b/internal/handler/admin_dashboard_handler.go index aaf7b79..79f5371 100644 --- a/internal/handler/admin_dashboard_handler.go +++ b/internal/handler/admin_dashboard_handler.go @@ -36,14 +36,9 @@ func (h *AdminDashboardHandler) GetStats(c *gin.Context) { // GetUserActivityTrend 获取用户活跃度趋势 // GET /api/v1/admin/dashboard/user-activity func (h *AdminDashboardHandler) GetUserActivityTrend(c *gin.Context) { - // 解析天数参数,默认7天 + // 解析天数参数,默认7天,限制在1-30天 days, _ := strconv.Atoi(c.DefaultQuery("days", "7")) - if days <= 0 { - days = 7 - } - if days > 30 { - days = 30 - } + days = min(max(days, 1), 30) trend, err := h.dashboardService.GetUserActivityTrend(c.Request.Context(), days) if err != nil { @@ -69,14 +64,9 @@ func (h *AdminDashboardHandler) GetContentStats(c *gin.Context) { // GetPendingContent 获取待审核内容 // GET /api/v1/admin/dashboard/pending-content func (h *AdminDashboardHandler) GetPendingContent(c *gin.Context) { - // 解析limit参数,默认10条 + // 解析limit参数,默认10条,限制在1-50条 limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10")) - if limit <= 0 { - limit = 10 - } - if limit > 50 { - limit = 50 - } + limit = min(max(limit, 1), 50) content, err := h.dashboardService.GetPendingContent(c.Request.Context(), limit) if err != nil { diff --git a/internal/handler/group_handler.go b/internal/handler/group_handler.go index 7abe634..c5799f5 100644 --- a/internal/handler/group_handler.go +++ b/internal/handler/group_handler.go @@ -1,6 +1,7 @@ package handler import ( + "errors" "strconv" "github.com/gin-gonic/gin" @@ -90,7 +91,7 @@ func (h *GroupHandler) GetGroup(c *gin.Context) { group, err := h.groupService.GetGroupByID(groupID) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -129,7 +130,7 @@ func (h *GroupHandler) UpdateGroup(c *gin.Context) { return } - updates := make(map[string]interface{}) + updates := make(map[string]any) if req.Name != "" { updates["name"] = req.Name } @@ -145,7 +146,7 @@ func (h *GroupHandler) UpdateGroup(c *gin.Context) { response.Forbidden(c, "没有权限修改群组信息") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -178,7 +179,7 @@ func (h *GroupHandler) DissolveGroup(c *gin.Context) { response.Forbidden(c, "只有群主可以解散群组") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -215,7 +216,7 @@ func (h *GroupHandler) TransferOwner(c *gin.Context) { response.Forbidden(c, "只有群主可以转让群主") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -279,7 +280,7 @@ func (h *GroupHandler) InviteMembers(c *gin.Context) { response.Forbidden(c, "只有群成员可以邀请他人") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -314,7 +315,7 @@ func (h *GroupHandler) JoinGroup(c *gin.Context) { response.Forbidden(c, "该群不允许加入") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -353,7 +354,7 @@ func (h *GroupHandler) LeaveGroup(c *gin.Context) { response.BadRequest(c, "不是群成员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -390,7 +391,7 @@ func (h *GroupHandler) RemoveMember(c *gin.Context) { response.Forbidden(c, "只有群主或管理员可以移除成员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -429,7 +430,7 @@ func (h *GroupHandler) GetMembers(c *gin.Context) { members, total, err := h.groupService.GetMembers(groupID, page, pageSize) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -517,7 +518,7 @@ func (h *GroupHandler) HandleGetMyMemberInfo(c *gin.Context) { // 获取群组信息 group, err := h.groupService.GetGroupByID(groupID) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -542,7 +543,7 @@ func (h *GroupHandler) HandleGetMyMemberInfo(c *gin.Context) { } // 添加群组禁言状态信息 - response.Success(c, map[string]interface{}{ + response.Success(c, map[string]any{ "member": memberResp, "mute_all": group.MuteAll, "is_muted": member.Muted || group.MuteAll, @@ -570,7 +571,7 @@ func (h *GroupHandler) HandleDissolveGroup(c *gin.Context) { response.Forbidden(c, "只有群主可以解散群组") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -612,7 +613,7 @@ func (h *GroupHandler) HandleTransferOwner(c *gin.Context) { response.Forbidden(c, "只有群主可以转让群主") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -657,7 +658,7 @@ func (h *GroupHandler) HandleInviteMembers(c *gin.Context) { response.Forbidden(c, "只有群主或管理员可以邀请他人") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -696,7 +697,7 @@ func (h *GroupHandler) HandleJoinGroup(c *gin.Context) { response.Forbidden(c, "该群不允许加入") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -741,7 +742,7 @@ func (h *GroupHandler) HandleSetNickname(c *gin.Context) { response.BadRequest(c, "不是群成员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -778,7 +779,7 @@ func (h *GroupHandler) HandleSetJoinType(c *gin.Context) { response.Forbidden(c, "只有群主可以设置加群方式") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -824,7 +825,7 @@ func (h *GroupHandler) HandleCreateAnnouncement(c *gin.Context) { response.Forbidden(c, "只有群主或管理员可以发布公告") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -855,7 +856,7 @@ func (h *GroupHandler) HandleGetAnnouncements(c *gin.Context) { announcements, total, err := h.groupService.GetAnnouncements(groupID, page, pageSize) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -916,7 +917,7 @@ func (h *GroupHandler) GetMyMemberInfo(c *gin.Context) { // 获取群组信息 group, err := h.groupService.GetGroupByID(groupID) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -941,7 +942,7 @@ func (h *GroupHandler) GetMyMemberInfo(c *gin.Context) { } // 添加群组禁言状态信息 - response.Success(c, map[string]interface{}{ + response.Success(c, map[string]any{ "member": memberResp, "mute_all": group.MuteAll, "is_muted": member.Muted || group.MuteAll, @@ -981,7 +982,7 @@ func (h *GroupHandler) SetMemberRole(c *gin.Context) { response.Forbidden(c, "只有群主可以设置成员角色") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1022,7 +1023,7 @@ func (h *GroupHandler) SetNickname(c *gin.Context) { response.BadRequest(c, "不是群成员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1065,7 +1066,7 @@ func (h *GroupHandler) MuteMember(c *gin.Context) { response.Forbidden(c, "只有群主或管理员可以禁言成员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1116,7 +1117,7 @@ func (h *GroupHandler) SetMuteAll(c *gin.Context) { response.Forbidden(c, "只有群主可以设置全员禁言") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1157,7 +1158,7 @@ func (h *GroupHandler) SetJoinType(c *gin.Context) { response.Forbidden(c, "只有群主可以设置加群方式") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1205,7 +1206,7 @@ func (h *GroupHandler) CreateAnnouncement(c *gin.Context) { response.Forbidden(c, "只有群主或管理员可以发布公告") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1236,7 +1237,7 @@ func (h *GroupHandler) GetAnnouncements(c *gin.Context) { announcements, total, err := h.groupService.GetAnnouncements(groupID, page, pageSize) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1363,7 +1364,7 @@ func (h *GroupHandler) GetMembersByCursor(c *gin.Context) { // 调用游标分页服务 result, err := h.groupService.GetMembersByCursor(c.Request.Context(), groupID, req) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1406,7 +1407,7 @@ func (h *GroupHandler) GetAnnouncementsByCursor(c *gin.Context) { // 调用游标分页服务 result, err := h.groupService.GetAnnouncementsByCursor(c.Request.Context(), groupID, req) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1472,7 +1473,7 @@ func (h *GroupHandler) HandleSetGroupKick(c *gin.Context) { response.Forbidden(c, "只有群主或管理员可以移除成员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1543,7 +1544,7 @@ func (h *GroupHandler) HandleSetGroupBan(c *gin.Context) { response.Forbidden(c, "只有群主或管理员可以禁言成员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1593,7 +1594,7 @@ func (h *GroupHandler) HandleSetGroupWholeBan(c *gin.Context) { response.Forbidden(c, "只有群主可以设置全员禁言") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1646,7 +1647,7 @@ func (h *GroupHandler) HandleSetGroupAdmin(c *gin.Context) { response.Forbidden(c, "只有群主可以设置管理员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1691,7 +1692,7 @@ func (h *GroupHandler) HandleSetGroupName(c *gin.Context) { return } - updates := map[string]interface{}{ + updates := map[string]any{ "name": params.GroupName, } @@ -1701,7 +1702,7 @@ func (h *GroupHandler) HandleSetGroupName(c *gin.Context) { response.Forbidden(c, "没有权限修改群组信息") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1740,7 +1741,7 @@ func (h *GroupHandler) HandleSetGroupAvatar(c *gin.Context) { return } - updates := map[string]interface{}{ + updates := map[string]any{ "avatar": params.Avatar, } @@ -1750,7 +1751,7 @@ func (h *GroupHandler) HandleSetGroupAvatar(c *gin.Context) { response.Forbidden(c, "没有权限修改群组信息") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1784,7 +1785,7 @@ func (h *GroupHandler) HandleSetGroupLeave(c *gin.Context) { response.BadRequest(c, "不是群成员") return } - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1907,7 +1908,7 @@ func (h *GroupHandler) HandleGetGroupInfo(c *gin.Context) { group, err := h.groupService.GetGroupByID(groupID) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } @@ -1945,7 +1946,7 @@ func (h *GroupHandler) HandleGetGroupMemberList(c *gin.Context) { members, total, err := h.groupService.GetMembers(groupID, page, pageSize) if err != nil { - if err == service.ErrGroupNotFound { + if errors.Is(err, service.ErrGroupNotFound) { response.NotFound(c, "群组不存在") return } diff --git a/internal/handler/material_handler.go b/internal/handler/material_handler.go index 50809cd..a601559 100644 --- a/internal/handler/material_handler.go +++ b/internal/handler/material_handler.go @@ -1,6 +1,7 @@ package handler import ( + "errors" "strconv" "carrot_bbs/internal/dto" @@ -39,21 +40,21 @@ type subjectResponse struct { } type materialResponse struct { - ID string `json:"id"` - SubjectID string `json:"subject_id"` - Title string `json:"title"` - Description string `json:"description,omitempty"` - FileType string `json:"file_type"` - FileSize int64 `json:"file_size"` - FileURL string `json:"file_url"` - FileName string `json:"file_name"` - DownloadCount int `json:"download_count"` - AuthorID string `json:"author_id,omitempty"` - Tags []string `json:"tags,omitempty"` - Status string `json:"status"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - Subject *subjectResponse `json:"subject,omitempty"` + ID string `json:"id"` + SubjectID string `json:"subject_id"` + Title string `json:"title"` + Description string `json:"description,omitempty"` + FileType string `json:"file_type"` + FileSize int64 `json:"file_size"` + FileURL string `json:"file_url"` + FileName string `json:"file_name"` + DownloadCount int `json:"download_count"` + AuthorID string `json:"author_id,omitempty"` + Tags []string `json:"tags,omitempty"` + Status string `json:"status"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + Subject *subjectResponse `json:"subject,omitempty"` } // ===================================================== @@ -170,11 +171,11 @@ func (h *MaterialHandler) ListMaterials(c *gin.Context) { } response.Success(c, gin.H{ - "list": result, - "total": total, - "page": page, - "page_size": pageSize, - "has_more": int64(page*pageSize) < total, + "list": result, + "total": total, + "page": page, + "page_size": pageSize, + "has_more": int64(page*pageSize) < total, }) } @@ -305,7 +306,7 @@ func (h *MaterialHandler) AdminUpdateSubject(c *gin.Context) { func (h *MaterialHandler) AdminDeleteSubject(c *gin.Context) { id := c.Param("id") if err := h.materialService.DeleteSubject(id); err != nil { - if err == service.ErrSubjectHasMaterials { + if errors.Is(err, service.ErrSubjectHasMaterials) { response.BadRequest(c, "学科下存在资料,无法删除") return } diff --git a/internal/handler/sticker_handler.go b/internal/handler/sticker_handler.go index bb9084a..c820e09 100644 --- a/internal/handler/sticker_handler.go +++ b/internal/handler/sticker_handler.go @@ -1,6 +1,7 @@ package handler import ( + "errors" "net/http" "github.com/gin-gonic/gin" @@ -81,11 +82,11 @@ func (h *StickerHandler) AddSticker(c *gin.Context) { sticker, err := h.stickerService.AddSticker(userID, req.URL, req.Width, req.Height) if err != nil { - if err == service.ErrStickerAlreadyExists { + if errors.Is(err, service.ErrStickerAlreadyExists) { response.Error(c, http.StatusConflict, "sticker already exists") return } - if err == service.ErrInvalidStickerURL { + if errors.Is(err, service.ErrInvalidStickerURL) { response.BadRequest(c, "invalid sticker url, only http/https is allowed") return } diff --git a/internal/handler/ws_handler.go b/internal/handler/ws_handler.go index e3b86d3..8e1bb95 100644 --- a/internal/handler/ws_handler.go +++ b/internal/handler/ws_handler.go @@ -67,9 +67,9 @@ func (h *WSHandler) HandleWebSocket(c *gin.Context) { if token == "" { authHeader := c.GetHeader("Authorization") if authHeader != "" { - parts := strings.SplitN(authHeader, " ", 2) - if len(parts) == 2 && parts[0] == "Bearer" { - token = parts[1] + prefix, rest, found := strings.Cut(authHeader, " ") + if found && prefix == "Bearer" { + token = rest } } } @@ -489,7 +489,7 @@ func (h *WSHandler) handleCallInvite(ctx context.Context, client *ws.Client, pay EventID: h.wsHub.NextID(), Type: "call_invited", TS: time.Now().UnixMilli(), - Payload: map[string]interface{}{ + Payload: map[string]any{ "call_id": call.ID, "conversation_id": req.ConversationID, "callee_id": req.CalleeID, @@ -528,7 +528,7 @@ func (h *WSHandler) handleCallAnswer(ctx context.Context, client *ws.Client, pay EventID: h.wsHub.NextID(), Type: "call_accepted", TS: time.Now().UnixMilli(), - Payload: map[string]interface{}{ + Payload: map[string]any{ "call_id": call.ID, "started_at": call.StartedAt, }, @@ -582,7 +582,7 @@ func (h *WSHandler) handleCallSDP(ctx context.Context, client *ws.Client, payloa return } - signalPayload, _ := json.Marshal(map[string]interface{}{ + signalPayload, _ := json.Marshal(map[string]any{ "sdp_type": req.SDPType, "sdp": json.RawMessage(req.SDP), }) @@ -602,7 +602,7 @@ func (h *WSHandler) handleCallICE(ctx context.Context, client *ws.Client, payloa return } - signalPayload, _ := json.Marshal(map[string]interface{}{ + signalPayload, _ := json.Marshal(map[string]any{ "candidate": json.RawMessage(req.Candidate), }) if err := h.callService.RelaySignal(ctx, req.CallID, client.UserID, "call_ice", signalPayload); err != nil { @@ -631,7 +631,7 @@ func (h *WSHandler) handleCallEnd(ctx context.Context, client *ws.Client, payloa EventID: h.wsHub.NextID(), Type: "call_ended", TS: time.Now().UnixMilli(), - Payload: map[string]interface{}{ + Payload: map[string]any{ "call_id": call.ID, "duration": call.Duration, }, diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index df6ffd8..8e521de 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -21,15 +21,13 @@ func Auth(jwtService *service.JWTService) gin.HandlerFunc { } // 提取Token - parts := strings.SplitN(authHeader, " ", 2) - if len(parts) != 2 || parts[0] != "Bearer" { + prefix, token, found := strings.Cut(authHeader, " ") + if !found || prefix != "Bearer" { response.Unauthorized(c, "invalid authorization header format") c.Abort() return } - token := parts[1] - // 验证Token claims, err := jwtService.ParseToken(token) if err != nil { @@ -56,14 +54,12 @@ func OptionalAuth(jwtService *service.JWTService) gin.HandlerFunc { } // 提取Token - parts := strings.SplitN(authHeader, " ", 2) - if len(parts) != 2 || parts[0] != "Bearer" { + prefix, token, found := strings.Cut(authHeader, " ") + if !found || prefix != "Bearer" { c.Next() return } - token := parts[1] - // 验证Token claims, err := jwtService.ParseToken(token) if err != nil { diff --git a/internal/model/material.go b/internal/model/material.go index a6ede43..0dc2cbd 100644 --- a/internal/model/material.go +++ b/internal/model/material.go @@ -66,7 +66,7 @@ func (a StringArray) Value() (driver.Value, error) { } // Scan 实现 sql.Scanner 接口 -func (a *StringArray) Scan(value interface{}) error { +func (a *StringArray) Scan(value any) error { if value == nil { *a = nil return nil @@ -80,20 +80,20 @@ func (a *StringArray) Scan(value interface{}) error { // MaterialFile 文件资料 type MaterialFile struct { - ID string `json:"id" gorm:"type:varchar(36);primaryKey"` - SubjectID string `json:"subject_id" gorm:"type:varchar(36);index;not null"` - Title string `json:"title" gorm:"type:varchar(200);not null"` - Description string `json:"description" gorm:"type:text"` + ID string `json:"id" gorm:"type:varchar(36);primaryKey"` + SubjectID string `json:"subject_id" gorm:"type:varchar(36);index;not null"` + Title string `json:"title" gorm:"type:varchar(200);not null"` + Description string `json:"description" gorm:"type:text"` FileType MaterialFileType `json:"file_type" gorm:"type:varchar(20);not null;index"` - FileSize int64 `json:"file_size" gorm:"default:0"` // 文件大小(字节) - FileURL string `json:"file_url" gorm:"type:text;not null"` // 文件URL - FileName string `json:"file_name" gorm:"type:varchar(255)"` // 原始文件名 - DownloadCount int `json:"download_count" gorm:"default:0"` // 下载次数 - AuthorID string `json:"author_id" gorm:"type:varchar(36);index"` // 上传者ID - Tags StringArray `json:"tags" gorm:"type:json"` // 标签 - Status MaterialStatus `json:"status" gorm:"type:varchar(20);default:active;index"` // 状态 - CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;index"` - UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` + FileSize int64 `json:"file_size" gorm:"default:0"` // 文件大小(字节) + FileURL string `json:"file_url" gorm:"type:text;not null"` // 文件URL + FileName string `json:"file_name" gorm:"type:varchar(255)"` // 原始文件名 + DownloadCount int `json:"download_count" gorm:"default:0"` // 下载次数 + AuthorID string `json:"author_id" gorm:"type:varchar(36);index"` // 上传者ID + Tags StringArray `json:"tags" gorm:"type:json"` // 标签 + Status MaterialStatus `json:"status" gorm:"type:varchar(20);default:active;index"` // 状态 + CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime;index"` + UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` // 关联 Subject *MaterialSubject `json:"subject,omitempty" gorm:"foreignKey:SubjectID"` diff --git a/internal/model/message.go b/internal/model/message.go index 6aa34ea..6cb5ce7 100644 --- a/internal/model/message.go +++ b/internal/model/message.go @@ -97,7 +97,7 @@ func (e ExtraData) Value() (driver.Value, error) { } // Scan 实现sql.Scanner接口,用于数据库读取 -func (e *ExtraData) Scan(value interface{}) error { +func (e *ExtraData) Scan(value any) error { if value == nil { return nil } @@ -109,7 +109,7 @@ func (e *ExtraData) Scan(value interface{}) error { } // MessageSegmentData 单个消息段的数据 -type MessageSegmentData map[string]interface{} +type MessageSegmentData map[string]any // MessageSegment 消息段 type MessageSegment struct { @@ -126,7 +126,7 @@ func (s MessageSegments) Value() (driver.Value, error) { } // Scan 实现sql.Scanner接口,用于数据库读取 -func (s *MessageSegments) Scan(value interface{}) error { +func (s *MessageSegments) Scan(value any) error { if value == nil { *s = nil return nil @@ -148,11 +148,11 @@ type Message struct { Seq int64 `gorm:"not null;index:idx_msg_conversation_seq,priority:2" json:"seq"` // 会话内序号,用于排序和增量同步 // 消息内容字段 - Segments MessageSegments `gorm:"-" json:"segments"` // 消息链(内存中使用,不映射到数据库) - SegmentsEncrypted string `gorm:"column:segments;type:text" json:"-"` // 加密后的消息链(存储在数据库) + Segments MessageSegments `gorm:"-" json:"segments"` // 消息链(内存中使用,不映射到数据库) + SegmentsEncrypted string `gorm:"column:segments;type:text" json:"-"` // 加密后的消息链(存储在数据库) SegmentsKeyVersion int `gorm:"column:segments_key_version;default:0" json:"segments_key_version"` // 密钥版本,用于密钥轮换 - ReplyToID *string `json:"reply_to_id,omitempty"` // 回复的消息ID(string类型) + ReplyToID *string `json:"reply_to_id,omitempty"` // 回复的消息ID(string类型) Status MessageStatus `gorm:"type:varchar(20);default:'normal'" json:"status"` // 消息状态 // 新增字段:消息分类和系统消息类型 diff --git a/internal/model/system_notification.go b/internal/model/system_notification.go index 0b1608d..58de5be 100644 --- a/internal/model/system_notification.go +++ b/internal/model/system_notification.go @@ -75,7 +75,7 @@ func (e SystemNotificationExtra) Value() (driver.Value, error) { } // Scan 实现sql.Scanner接口 -func (e *SystemNotificationExtra) Scan(value interface{}) error { +func (e *SystemNotificationExtra) Scan(value any) error { if value == nil { return nil } diff --git a/internal/pkg/crypto/batch_decrypt.go b/internal/pkg/crypto/batch_decrypt.go index 61fcc5f..5779823 100644 --- a/internal/pkg/crypto/batch_decrypt.go +++ b/internal/pkg/crypto/batch_decrypt.go @@ -86,7 +86,7 @@ func (e *MessageEncryptor) DecryptMessageSegments(ciphertext string) ([]byte, er // TryParseMessageSegments 尝试解析消息段 // 先尝试解密,如果失败则尝试直接解析(兼容未加密的旧数据) -func TryParseMessageSegments(ciphertext string, segments interface{}) error { +func TryParseMessageSegments(ciphertext string, segments any) error { if ciphertext == "" { return nil } diff --git a/internal/pkg/cursor/pagination.go b/internal/pkg/cursor/pagination.go index 9300adf..887bb3e 100644 --- a/internal/pkg/cursor/pagination.go +++ b/internal/pkg/cursor/pagination.go @@ -93,14 +93,14 @@ func (r *PageRequest) IsBackward() bool { // PageResponse 游标分页响应结构 type PageResponse struct { - Items interface{} `json:"items"` - NextCursor string `json:"next_cursor"` - PrevCursor string `json:"prev_cursor,omitempty"` - HasMore bool `json:"has_more"` + Items any `json:"items"` + NextCursor string `json:"next_cursor"` + PrevCursor string `json:"prev_cursor,omitempty"` + HasMore bool `json:"has_more"` } // NewPageResponse 创建分页响应 -func NewPageResponse(items interface{}, nextCursor, prevCursor string, hasMore bool) *PageResponse { +func NewPageResponse(items any, nextCursor, prevCursor string, hasMore bool) *PageResponse { return &PageResponse{ Items: items, NextCursor: nextCursor, diff --git a/internal/pkg/hook/metrics.go b/internal/pkg/hook/metrics.go index d55de7f..fe13620 100644 --- a/internal/pkg/hook/metrics.go +++ b/internal/pkg/hook/metrics.go @@ -103,7 +103,7 @@ func (m *Metrics) GetHookMetrics() []MetricSnapshot { } func parseKey(key string) (HookType, string) { - for i := 0; i < len(key); i++ { + for i := range len(key) { if key[i] == ':' { return HookType(key[:i]), key[i+1:] } diff --git a/internal/pkg/openai/client.go b/internal/pkg/openai/client.go index a5ff8f6..6fe5a6a 100644 --- a/internal/pkg/openai/client.go +++ b/internal/pkg/openai/client.go @@ -210,8 +210,8 @@ type responseFormatConfig struct { } type chatMessage struct { - Role string `json:"role"` - Content interface{} `json:"content"` + Role string `json:"role"` + Content any `json:"content"` } type contentPart struct { diff --git a/internal/pkg/redis/redis.go b/internal/pkg/redis/redis.go index 1b7ebc2..98430c5 100644 --- a/internal/pkg/redis/redis.go +++ b/internal/pkg/redis/redis.go @@ -73,7 +73,7 @@ func (c *Client) Get(ctx context.Context, key string) (string, error) { } // Set 设置值 -func (c *Client) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) error { +func (c *Client) Set(ctx context.Context, key string, value any, expiration time.Duration) error { return c.rdb.Set(ctx, key, value, expiration).Err() } @@ -121,12 +121,12 @@ func (c *Client) IsMiniRedis() bool { // ==================== Hash 操作 ==================== // HSet 设置 Hash 字段 -func (c *Client) HSet(ctx context.Context, key string, field string, value interface{}) error { +func (c *Client) HSet(ctx context.Context, key string, field string, value any) error { return c.rdb.HSet(ctx, key, field, value).Err() } // HMSet 批量设置 Hash 字段 -func (c *Client) HMSet(ctx context.Context, key string, values map[string]interface{}) error { +func (c *Client) HMSet(ctx context.Context, key string, values map[string]any) error { return c.rdb.HMSet(ctx, key, values).Err() } @@ -136,7 +136,7 @@ func (c *Client) HGet(ctx context.Context, key string, field string) (string, er } // HMGet 批量获取 Hash 字段值 -func (c *Client) HMGet(ctx context.Context, key string, fields ...string) ([]interface{}, error) { +func (c *Client) HMGet(ctx context.Context, key string, fields ...string) ([]any, error) { return c.rdb.HMGet(ctx, key, fields...).Result() } @@ -203,7 +203,7 @@ func (c *Client) ZRevRange(ctx context.Context, key string, start, stop int64) ( } // ZRem 删除 Sorted Set 成员 -func (c *Client) ZRem(ctx context.Context, key string, members ...interface{}) error { +func (c *Client) ZRem(ctx context.Context, key string, members ...any) error { return c.rdb.ZRem(ctx, key, members...).Err() } diff --git a/internal/pkg/response/response.go b/internal/pkg/response/response.go index 1514fc3..8684336 100644 --- a/internal/pkg/response/response.go +++ b/internal/pkg/response/response.go @@ -10,20 +10,20 @@ import ( // Response 统一响应结构 type Response struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data,omitempty"` + Code int `json:"code"` + Message string `json:"message"` + Data any `json:"data,omitempty"` } // ResponseSnakeCase 统一响应结构(snake_case) type ResponseSnakeCase struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data,omitempty"` + Code int `json:"code"` + Message string `json:"message"` + Data any `json:"data,omitempty"` } // Success 成功响应 -func Success(c *gin.Context, data interface{}) { +func Success(c *gin.Context, data any) { c.JSON(http.StatusOK, Response{ Code: 0, Message: "success", @@ -32,7 +32,7 @@ func Success(c *gin.Context, data interface{}) { } // SuccessWithMessage 成功响应带消息 -func SuccessWithMessage(c *gin.Context, message string, data interface{}) { +func SuccessWithMessage(c *gin.Context, message string, data any) { c.JSON(http.StatusOK, Response{ Code: 0, Message: message, @@ -95,15 +95,15 @@ func InternalServerError(c *gin.Context, message string) { // PaginatedResponse 分页响应 type PaginatedResponse struct { - List interface{} `json:"list"` - Total int64 `json:"total"` - Page int `json:"page"` - PageSize int `json:"page_size"` - TotalPages int `json:"total_pages"` + List any `json:"list"` + Total int64 `json:"total"` + Page int `json:"page"` + PageSize int `json:"page_size"` + TotalPages int `json:"total_pages"` } // Paginated 分页成功响应 -func Paginated(c *gin.Context, list interface{}, total int64, page, pageSize int) { +func Paginated(c *gin.Context, list any, total int64, page, pageSize int) { totalPages := int(total) / pageSize if int(total)%pageSize > 0 { totalPages++ diff --git a/internal/pkg/ws/hub.go b/internal/pkg/ws/hub.go index 1e8c0ee..11dfaa6 100644 --- a/internal/pkg/ws/hub.go +++ b/internal/pkg/ws/hub.go @@ -16,11 +16,11 @@ const ( // Event 表示一个WebSocket事件 type Event struct { - ID uint64 `json:"event_id"` - Type string `json:"type"` - Event string `json:"event"` // 事件名称(兼容多种协议) - TS int64 `json:"ts"` - Payload interface{} `json:"payload"` + ID uint64 `json:"event_id"` + Type string `json:"type"` + Event string `json:"event"` // 事件名称(兼容多种协议) + TS int64 `json:"ts"` + Payload any `json:"payload"` } // Client 表示一个WebSocket客户端连接 @@ -39,10 +39,10 @@ type Message struct { // ResponseMessage 表示发送给客户端的消息 type ResponseMessage struct { - EventID uint64 `json:"event_id"` - Type string `json:"type"` - TS int64 `json:"ts"` - Payload interface{} `json:"payload,omitempty"` + EventID uint64 `json:"event_id"` + Type string `json:"type"` + TS int64 `json:"ts"` + Payload any `json:"payload,omitempty"` } // ErrorMessage 表示错误消息 @@ -76,11 +76,11 @@ type Hub struct { seq uint64 mu sync.RWMutex - clients map[string]map[uint64]*Client // userID -> clientID -> Client - history map[string][]Event // userID -> []Event (用于断线重连历史回放) + clients map[string]map[uint64]*Client // userID -> clientID -> Client + history map[string][]Event // userID -> []Event (用于断线重连历史回放) subscribers map[string]map[uint64]*subscriber // userID -> subscriberID -> subscriber - disconnectHandlers []DisconnectHandler // 断开连接事件处理器列表 - connectHandlers []ConnectHandler // 连接事件处理器列表 + disconnectHandlers []DisconnectHandler // 断开连接事件处理器列表 + connectHandlers []ConnectHandler // 连接事件处理器列表 } // NewHub 创建WebSocket Hub @@ -213,7 +213,7 @@ func (h *Hub) GetClientCount(userID string) int { } // PublishToUser 向指定用户发送事件 -func (h *Hub) PublishToUser(userID string, eventType string, payload interface{}) Event { +func (h *Hub) PublishToUser(userID string, eventType string, payload any) Event { ev := Event{ ID: h.NextID(), Type: eventType, @@ -225,7 +225,7 @@ func (h *Hub) PublishToUser(userID string, eventType string, payload interface{} } // PublishToUsers 向多个用户发送事件 -func (h *Hub) PublishToUsers(userIDs []string, eventType string, payload interface{}) { +func (h *Hub) PublishToUsers(userIDs []string, eventType string, payload any) { for _, uid := range userIDs { h.PublishToUser(uid, eventType, payload) } @@ -233,7 +233,7 @@ func (h *Hub) PublishToUsers(userIDs []string, eventType string, payload interfa // PublishToUserOnline 仅在用户在线时发送事件,不存入历史回放 // 适用于通话信令等实时性消息,避免断线重连时重放过期消息 -func (h *Hub) PublishToUserOnline(userID string, eventType string, payload interface{}) bool { +func (h *Hub) PublishToUserOnline(userID string, eventType string, payload any) bool { h.mu.RLock() targets := make([]*Client, 0, len(h.clients[userID])) for _, c := range h.clients[userID] { @@ -269,7 +269,7 @@ func (h *Hub) PublishToUserOnline(userID string, eventType string, payload inter // PublishToUserOnlineReliable 可靠地发送事件给在线用户(阻塞发送) // 用于重要的信令消息(如 SDP, ICE candidate),确保消息送达 // 如果用户不在线,返回 false -func (h *Hub) PublishToUserOnlineReliable(userID string, eventType string, payload interface{}) bool { +func (h *Hub) PublishToUserOnlineReliable(userID string, eventType string, payload any) bool { h.mu.RLock() targets := make([]*Client, 0, len(h.clients[userID])) for _, c := range h.clients[userID] { @@ -376,7 +376,7 @@ func (h *Hub) SendError(client *Client, code string, message string) { } // Broadcast 广播消息给所有连接 -func (h *Hub) Broadcast(eventType string, payload interface{}) { +func (h *Hub) Broadcast(eventType string, payload any) { h.mu.RLock() userIDs := make([]string, 0, len(h.clients)) for uid := range h.clients { @@ -454,4 +454,4 @@ func EncodeData(ev Event) (string, error) { return "", err } return string(body), nil -} \ No newline at end of file +} diff --git a/internal/repository/comment_repo.go b/internal/repository/comment_repo.go index eb3a0cc..8eab433 100644 --- a/internal/repository/comment_repo.go +++ b/internal/repository/comment_repo.go @@ -94,7 +94,7 @@ func (r *commentRepository) Delete(id string) error { // 减少帖子的评论数并同步热度分 // 评论数属于统计字段,不应影响帖子内容更新时间(updated_at) if err := tx.Model(&model.Post{}).Where("id = ?", comment.PostID). - UpdateColumns(map[string]interface{}{ + UpdateColumns(map[string]any{ "comments_count": gorm.Expr("comments_count - 1"), "updated_at": gorm.Expr("updated_at"), }).Error; err != nil { diff --git a/internal/repository/device_token_repo.go b/internal/repository/device_token_repo.go index cbba104..8c78816 100644 --- a/internal/repository/device_token_repo.go +++ b/internal/repository/device_token_repo.go @@ -125,7 +125,7 @@ func (r *deviceTokenRepository) Upsert(token *model.DeviceToken) error { } // 更新现有记录 - return r.db.Model(&existing).Updates(map[string]interface{}{ + return r.db.Model(&existing).Updates(map[string]any{ "push_token": token.PushToken, "is_active": true, "device_name": token.DeviceName, @@ -151,7 +151,7 @@ func (r *deviceTokenRepository) Deactivate(deviceID string) error { func (r *deviceTokenRepository) Activate(deviceID string) error { return r.db.Model(&model.DeviceToken{}). Where("device_id = ?", deviceID). - Updates(map[string]interface{}{ + Updates(map[string]any{ "is_active": true, "last_used_at": time.Now(), }).Error diff --git a/internal/repository/message_repo.go b/internal/repository/message_repo.go index f0a7390..cdbed0d 100644 --- a/internal/repository/message_repo.go +++ b/internal/repository/message_repo.go @@ -91,7 +91,7 @@ func (r *messageRepository) CreateConversationWithParticipants(conv *model.Conve participant := model.ConversationParticipant{ ConversationID: conv.ID, UserID: userID, - LastReadSeq: 0, + LastReadSeq: 0, } if err := tx.Create(&participant).Error; err != nil { return err @@ -291,7 +291,7 @@ func (r *messageRepository) UpdateLastReadSeq(conversationID string, userID stri {Name: "conversation_id"}, {Name: "user_id"}, }, - DoUpdates: clause.Assignments(map[string]interface{}{ + DoUpdates: clause.Assignments(map[string]any{ "last_read_seq": lastReadSeq, "updated_at": gorm.Expr("CURRENT_TIMESTAMP"), }), @@ -324,7 +324,7 @@ func (r *messageRepository) UpdatePinned(conversationID string, userID string, i {Name: "conversation_id"}, {Name: "user_id"}, }, - DoUpdates: clause.Assignments(map[string]interface{}{ + DoUpdates: clause.Assignments(map[string]any{ "is_pinned": isPinned, "updated_at": gorm.Expr("CURRENT_TIMESTAMP"), }), @@ -358,7 +358,7 @@ func (r *messageRepository) GetUnreadCount(conversationID string, userID string) func (r *messageRepository) UpdateConversationLastSeq(conversationID string, seq int64) error { return r.db.Model(&model.Conversation{}). Where("id = ?", conversationID). - Updates(map[string]interface{}{ + Updates(map[string]any{ "last_seq": seq, "last_msg_time": gorm.Expr("CURRENT_TIMESTAMP"), }).Error @@ -393,7 +393,7 @@ func (r *messageRepository) CreateMessageWithSeq(msg *model.Message) error { // 更新会话的last_seq if err := tx.Model(&model.Conversation{}). Where("id = ?", msg.ConversationID). - Updates(map[string]interface{}{ + Updates(map[string]any{ "last_seq": msg.Seq, "last_msg_time": gorm.Expr("CURRENT_TIMESTAMP"), }).Error; err != nil { @@ -455,7 +455,7 @@ func (r *messageRepository) UpdateMessageStatus(messageID string, status model.M func (r *messageRepository) RecallMessage(messageID string, userID string) error { return r.db.Model(&model.Message{}). Where("id = ? AND sender_id = ?", messageID, userID). - Updates(map[string]interface{}{ + Updates(map[string]any{ "status": model.MessageStatusRecalled, "segments": model.MessageSegments{}, }).Error @@ -526,7 +526,7 @@ func (r *messageRepository) MarkAllSystemMessagesAsRead(userID string) error { {Name: "conversation_id"}, {Name: "user_id"}, }, - DoUpdates: clause.Assignments(map[string]interface{}{ + DoUpdates: clause.Assignments(map[string]any{ "last_read_seq": maxSeq, "updated_at": gorm.Expr("CURRENT_TIMESTAMP"), }), @@ -653,7 +653,7 @@ func (r *messageRepository) BatchUpdateParticipants(ctx context.Context, updates var cases []string var whereClauses []string - var args []interface{} + var args []any for _, u := range updates { cases = append(cases, "WHEN (conversation_id = ? AND user_id = ?) THEN ?") @@ -678,7 +678,7 @@ func (r *messageRepository) UpdateConversationLastSeqWithContext(ctx context.Con return r.db.WithContext(ctx). Model(&model.Conversation{}). Where("id = ?", convID). - Updates(map[string]interface{}{ + Updates(map[string]any{ "last_seq": lastSeq, "last_msg_time": lastMsgTime, "updated_at": time.Now(), @@ -701,7 +701,7 @@ func (r *messageRepository) BatchUpdateParticipantsWithTx(tx *gorm.DB, updates [ var cases []string var whereClauses []string - var args []interface{} + var args []any for _, u := range updates { cases = append(cases, "WHEN (conversation_id = ? AND user_id = ?) THEN ?") @@ -725,7 +725,7 @@ func (r *messageRepository) BatchUpdateParticipantsWithTx(tx *gorm.DB, updates [ func (r *messageRepository) UpdateConversationLastSeqWithTx(tx *gorm.DB, convID string, lastSeq int64, lastMsgTime time.Time) error { return tx.Model(&model.Conversation{}). Where("id = ?", convID). - Updates(map[string]interface{}{ + Updates(map[string]any{ "last_seq": lastSeq, "last_msg_time": lastMsgTime, "updated_at": time.Now(), diff --git a/internal/repository/post_repo.go b/internal/repository/post_repo.go index 77b459c..c6ade3e 100644 --- a/internal/repository/post_repo.go +++ b/internal/repository/post_repo.go @@ -166,7 +166,7 @@ func (r *postRepository) UpdateWithImages(post *model.Post, images *[]string) er // UpdateModerationStatus 更新帖子审核状态 func (r *postRepository) UpdateModerationStatus(postID string, status model.PostStatus, rejectReason string, reviewedBy string) error { // 审核状态更新属于管理操作,不应影响帖子内容更新时间(updated_at) - updates := map[string]interface{}{ + updates := map[string]any{ "status": status, "reviewed_at": gorm.Expr("CURRENT_TIMESTAMP"), "reviewed_by": reviewedBy, @@ -455,7 +455,7 @@ func (r *postRepository) IsFavoritedBatch(postIDs []string, userID string) map[s // IncrementViews 增加帖子观看量 func (r *postRepository) IncrementViews(postID string) error { return r.db.Model(&model.Post{}).Where("id = ?", postID). - UpdateColumns(map[string]interface{}{ + UpdateColumns(map[string]any{ "views_count": gorm.Expr("views_count + 1"), "updated_at": gorm.Expr("updated_at"), }).Error @@ -467,7 +467,7 @@ func (r *postRepository) IncrementShares(postID string) (int, error) { err := r.db.Transaction(func(tx *gorm.DB) error { res := tx.Model(&model.Post{}). Where("id = ? AND status = ?", postID, model.PostStatusPublished). - Updates(map[string]interface{}{ + Updates(map[string]any{ "shares_count": gorm.Expr("shares_count + 1"), "updated_at": gorm.Expr("updated_at"), }) @@ -909,11 +909,11 @@ func (r *postRepository) BatchUpdateStatus(ids []string, status model.PostStatus result := r.db.Model(&model.Post{}). Where("id IN ?", ids). Updates(map[string]any{ - "status": status, - "reviewed_at": gorm.Expr("CURRENT_TIMESTAMP"), - "reviewed_by": reviewedBy, + "status": status, + "reviewed_at": gorm.Expr("CURRENT_TIMESTAMP"), + "reviewed_by": reviewedBy, "reject_reason": "", - "updated_at": gorm.Expr("updated_at"), + "updated_at": gorm.Expr("updated_at"), }) if result.Error != nil { diff --git a/internal/repository/push_repo.go b/internal/repository/push_repo.go index 8f7d431..4c17727 100644 --- a/internal/repository/push_repo.go +++ b/internal/repository/push_repo.go @@ -113,7 +113,7 @@ func (r *pushRecordRepository) BatchUpdateStatus(ids []int64, status model.PushS if len(ids) == 0 { return nil } - updates := map[string]interface{}{ + updates := map[string]any{ "push_status": status, } if status == model.PushStatusPushed { @@ -126,7 +126,7 @@ func (r *pushRecordRepository) BatchUpdateStatus(ids []int64, status model.PushS // UpdateStatus 更新单条记录状态 func (r *pushRecordRepository) UpdateStatus(id int64, status model.PushStatus) error { - updates := map[string]interface{}{ + updates := map[string]any{ "push_status": status, } if status == model.PushStatusPushed { @@ -141,7 +141,7 @@ func (r *pushRecordRepository) UpdateStatus(id int64, status model.PushStatus) e func (r *pushRecordRepository) MarkAsFailed(id int64, errMsg string) error { return r.db.Model(&model.PushRecord{}). Where("id = ?", id). - Updates(map[string]interface{}{ + Updates(map[string]any{ "push_status": model.PushStatusFailed, "error_message": errMsg, "retry_count": gorm.Expr("retry_count + 1"), @@ -152,7 +152,7 @@ func (r *pushRecordRepository) MarkAsFailed(id int64, errMsg string) error { func (r *pushRecordRepository) MarkAsDelivered(id int64) error { return r.db.Model(&model.PushRecord{}). Where("id = ?", id). - Updates(map[string]interface{}{ + Updates(map[string]any{ "push_status": model.PushStatusDelivered, "delivered_at": time.Now(), }).Error diff --git a/internal/repository/report_repo.go b/internal/repository/report_repo.go index c283530..ea1bd34 100644 --- a/internal/repository/report_repo.go +++ b/internal/repository/report_repo.go @@ -164,7 +164,7 @@ func (r *reportRepository) GetPendingReportsByTarget(targetType model.ReportTarg // UpdateStatus 更新举报状态 func (r *reportRepository) UpdateStatus(id string, status model.ReportStatus, handledBy string, result string) error { - updates := map[string]interface{}{ + updates := map[string]any{ "status": status, "handled_by": handledBy, "result": result, @@ -174,7 +174,7 @@ func (r *reportRepository) UpdateStatus(id string, status model.ReportStatus, ha // UpdateStatusWithContext 使用上下文更新举报状态 func (r *reportRepository) UpdateStatusWithContext(ctx context.Context, id string, status model.ReportStatus, handledBy string, result string) error { - updates := map[string]interface{}{ + updates := map[string]any{ "status": status, "handled_by": handledBy, "result": result, @@ -184,7 +184,7 @@ func (r *reportRepository) UpdateStatusWithContext(ctx context.Context, id strin // BatchUpdateStatus 批量更新举报状态 func (r *reportRepository) BatchUpdateStatus(ids []string, status model.ReportStatus, handledBy string, result string) (int64, error) { - updates := map[string]interface{}{ + updates := map[string]any{ "status": status, "handled_by": handledBy, "result": result, @@ -195,7 +195,7 @@ func (r *reportRepository) BatchUpdateStatus(ids []string, status model.ReportSt // BatchUpdateStatusWithContext 使用上下文批量更新举报状态 func (r *reportRepository) BatchUpdateStatusWithContext(ctx context.Context, ids []string, status model.ReportStatus, handledBy string, result string) (int64, error) { - updates := map[string]interface{}{ + updates := map[string]any{ "status": status, "handled_by": handledBy, "result": result, @@ -209,4 +209,4 @@ func (r *reportRepository) GetByIDsWithContext(ctx context.Context, ids []string var reports []*model.Report err := r.getDB(ctx).Where("id IN ?", ids).Find(&reports).Error return reports, err -} \ No newline at end of file +} diff --git a/internal/repository/system_notification_repo.go b/internal/repository/system_notification_repo.go index a69e62f..adaea7c 100644 --- a/internal/repository/system_notification_repo.go +++ b/internal/repository/system_notification_repo.go @@ -91,7 +91,7 @@ func (r *systemNotificationRepository) MarkAsRead(id int64, receiverID string) e now := model.SystemNotification{}.UpdatedAt return r.db.Model(&model.SystemNotification{}). Where("id = ? AND receiver_id = ?", id, receiverID). - Updates(map[string]interface{}{ + Updates(map[string]any{ "is_read": true, "read_at": now, }).Error @@ -102,7 +102,7 @@ func (r *systemNotificationRepository) MarkAllAsRead(receiverID string) error { now := model.SystemNotification{}.UpdatedAt return r.db.Model(&model.SystemNotification{}). Where("receiver_id = ? AND is_read = ?", receiverID, false). - Updates(map[string]interface{}{ + Updates(map[string]any{ "is_read": true, "read_at": now, }).Error diff --git a/internal/service/admin_dashboard_service.go b/internal/service/admin_dashboard_service.go index 37f2019..1a8b9c8 100644 --- a/internal/service/admin_dashboard_service.go +++ b/internal/service/admin_dashboard_service.go @@ -173,12 +173,7 @@ func (s *adminDashboardServiceImpl) GetStats(ctx context.Context) (*dto.Dashboar // GetUserActivityTrend 获取用户活跃度趋势 func (s *adminDashboardServiceImpl) GetUserActivityTrend(ctx context.Context, days int) ([]dto.UserActivityTrendResponse, error) { - if days <= 0 { - days = 7 - } - if days > 30 { - days = 30 - } + days = min(max(days, 1), 30) now := time.Now() results := make([]dto.UserActivityTrendResponse, days) @@ -282,12 +277,7 @@ func (s *adminDashboardServiceImpl) GetContentStats(ctx context.Context) (*dto.C // GetPendingContent 获取待审核内容 func (s *adminDashboardServiceImpl) GetPendingContent(ctx context.Context, limit int) ([]dto.PendingContentResponse, error) { - if limit <= 0 { - limit = 10 - } - if limit > 50 { - limit = 50 - } + limit = min(max(limit, 1), 50) results := make([]dto.PendingContentResponse, 0) diff --git a/internal/service/async_log_manager.go b/internal/service/async_log_manager.go index 05ac55c..1713f30 100644 --- a/internal/service/async_log_manager.go +++ b/internal/service/async_log_manager.go @@ -205,7 +205,7 @@ func (m *AsyncLogManager) flushDataChangeLogs(logs []*model.DataChangeLog, repo } // handleError 处理写入错误 -func (m *AsyncLogManager) handleError(logType string, logs interface{}, err error) { +func (m *AsyncLogManager) handleError(logType string, logs any, err error) { m.logger.Error("failed to batch write logs", zap.String("log_type", logType), zap.Error(err), @@ -219,7 +219,7 @@ func (m *AsyncLogManager) handleError(logType string, logs interface{}, err erro } // writeToFallback 写入降级文件 -func (m *AsyncLogManager) writeToFallback(logType string, logs interface{}) error { +func (m *AsyncLogManager) writeToFallback(logType string, logs any) error { return nil } diff --git a/internal/service/call_service.go b/internal/service/call_service.go index 437e652..5bc185a 100644 --- a/internal/service/call_service.go +++ b/internal/service/call_service.go @@ -35,7 +35,7 @@ type ActiveCall struct { MediaType string // voice 或 video CreatedAt time.Time StartedAt *time.Time - Duration int64 // 通话时长(秒) + Duration int64 // 通话时长(秒) // 参与者状态 Participants map[string]*ActiveParticipant // ICE Servers @@ -228,7 +228,7 @@ func (s *callService) Invite(ctx context.Context, callerID, calleeID, conversati calleeOnline := s.hub.HasClients(calleeID) // 发送来电通知 - payload := map[string]interface{}{ + payload := map[string]any{ "call_id": call.ID, "conversation_id": conversationID, "caller_id": callerID, @@ -286,14 +286,14 @@ func (s *callService) Accept(ctx context.Context, callID, userID string) (*Activ s.mu.Unlock() // 通知拨打方 - s.hub.PublishToUserOnline(call.CallerID, "call_accepted", map[string]interface{}{ + s.hub.PublishToUserOnline(call.CallerID, "call_accepted", map[string]any{ "call_id": callID, "started_at": now.UnixMilli(), "ice_servers": s.config.WebRTC.ICEServers, }) // 通知被叫方其他设备 - s.hub.PublishToUserOnline(userID, "call_answered_elsewhere", map[string]interface{}{ + s.hub.PublishToUserOnline(userID, "call_answered_elsewhere", map[string]any{ "call_id": callID, "reason": "answered_on_another_device", }) @@ -328,7 +328,7 @@ func (s *callService) Reject(ctx context.Context, callID, userID string) error { s.saveCallHistory(call, model.CallStatusRejected, 0) // 通知拨打方 - s.hub.PublishToUserOnline(call.CallerID, "call_rejected", map[string]interface{}{ + s.hub.PublishToUserOnline(call.CallerID, "call_rejected", map[string]any{ "call_id": callID, "reason": "rejected", }) @@ -362,7 +362,7 @@ func (s *callService) Busy(ctx context.Context, callID, userID string) error { s.saveCallHistory(call, model.CallStatusMissed, 0) // 通知拨打方 - s.hub.PublishToUserOnline(call.CallerID, "call_busy", map[string]interface{}{ + s.hub.PublishToUserOnline(call.CallerID, "call_busy", map[string]any{ "call_id": callID, }) @@ -420,7 +420,7 @@ func (s *callService) End(ctx context.Context, callID, userID string, reason str // 通知其他参与者 for pUserID := range call.Participants { if pUserID != userID { - s.hub.PublishToUserOnline(pUserID, "call_ended", map[string]interface{}{ + s.hub.PublishToUserOnline(pUserID, "call_ended", map[string]any{ "call_id": callID, "ended_by": userID, "reason": reason, @@ -452,7 +452,7 @@ func (s *callService) RelaySignal(ctx context.Context, callID, fromUserID string for pUserID := range call.Participants { if pUserID != fromUserID { - s.hub.PublishToUserOnlineReliable(pUserID, signalType, map[string]interface{}{ + s.hub.PublishToUserOnlineReliable(pUserID, signalType, map[string]any{ "call_id": callID, "from_id": fromUserID, "payload": json.RawMessage(payload), @@ -481,7 +481,7 @@ func (s *callService) SetMuted(ctx context.Context, callID, userID string, muted for pUserID := range call.Participants { if pUserID != userID { - s.hub.PublishToUserOnline(pUserID, "call_peer_muted", map[string]interface{}{ + s.hub.PublishToUserOnline(pUserID, "call_peer_muted", map[string]any{ "call_id": callID, "user_id": userID, "muted": muted, diff --git a/internal/service/chat_service.go b/internal/service/chat_service.go index e72cb4b..120e767 100644 --- a/internal/service/chat_service.go +++ b/internal/service/chat_service.go @@ -97,7 +97,7 @@ func NewChatService( } } -func (s *chatServiceImpl) publishToUsers(userIDs []string, event string, payload interface{}) { +func (s *chatServiceImpl) publishToUsers(userIDs []string, event string, payload any) { if s.wsHub == nil || len(userIDs) == 0 { return } @@ -329,7 +329,7 @@ func (s *chatServiceImpl) SendMessage(ctx context.Context, senderID string, conv if conv.Type == model.ConversationTypeGroup { detailType = "group" } - s.publishToUsers(targetIDs, "chat_message", map[string]interface{}{ + s.publishToUsers(targetIDs, "chat_message", map[string]any{ "detail_type": detailType, "message": dto.ConvertMessageToResponse(message), }) @@ -342,7 +342,7 @@ func (s *chatServiceImpl) SendMessage(ctx context.Context, senderID string, conv s.conversationCache.InvalidateUnreadCount(p.UserID, conversationID) } if totalUnread, uErr := s.repo.GetAllUnreadCount(p.UserID); uErr == nil { - s.publishToUsers([]string{p.UserID}, "conversation_unread", map[string]interface{}{ + s.publishToUsers([]string{p.UserID}, "conversation_unread", map[string]any{ "conversation_id": conversationID, "total_unread": totalUnread, }) @@ -490,7 +490,7 @@ func (s *chatServiceImpl) MarkAsRead(ctx context.Context, conversationID string, for _, p := range participants { targetIDs = append(targetIDs, p.UserID) } - s.publishToUsers(targetIDs, "message_read", map[string]interface{}{ + s.publishToUsers(targetIDs, "message_read", map[string]any{ "detail_type": detailType, "conversation_id": conversationID, "group_id": groupID, @@ -499,7 +499,7 @@ func (s *chatServiceImpl) MarkAsRead(ctx context.Context, conversationID string, }) } if totalUnread, uErr := s.repo.GetAllUnreadCount(userID); uErr == nil { - s.publishToUsers([]string{userID}, "conversation_unread", map[string]interface{}{ + s.publishToUsers([]string{userID}, "conversation_unread", map[string]any{ "conversation_id": conversationID, "total_unread": totalUnread, }) @@ -579,7 +579,7 @@ func (s *chatServiceImpl) RecallMessage(ctx context.Context, messageID string, u for _, p := range participants { targetIDs = append(targetIDs, p.UserID) } - s.publishToUsers(targetIDs, "message_recall", map[string]interface{}{ + s.publishToUsers(targetIDs, "message_recall", map[string]any{ "detail_type": detailType, "conversation_id": message.ConversationID, "group_id": groupID, @@ -652,7 +652,7 @@ func (s *chatServiceImpl) SendTyping(ctx context.Context, senderID string, conve continue } if s.wsHub != nil { - s.wsHub.PublishToUser(p.UserID, "typing", map[string]interface{}{ + s.wsHub.PublishToUser(p.UserID, "typing", map[string]any{ "detail_type": detailType, "conversation_id": conversationID, "user_id": senderID, diff --git a/internal/service/comment_service.go b/internal/service/comment_service.go index d5527c0..6e2800d 100644 --- a/internal/service/comment_service.go +++ b/internal/service/comment_service.go @@ -135,7 +135,7 @@ func (s *CommentService) reviewCommentAsync( Images: imageURLs, AuthorID: authorID, ParentID: parentID, - }, map[string]interface{}{ + }, map[string]any{ "result": result, }) diff --git a/internal/service/group_service.go b/internal/service/group_service.go index 63576ca..82e9c6f 100644 --- a/internal/service/group_service.go +++ b/internal/service/group_service.go @@ -56,7 +56,7 @@ type GroupService interface { // 群组管理 CreateGroup(ownerID string, name string, description string, memberIDs []string) (*model.Group, error) GetGroupByID(id string) (*model.Group, error) - UpdateGroup(userID string, groupID string, updates map[string]interface{}) error + UpdateGroup(userID string, groupID string, updates map[string]any) error DissolveGroup(userID string, groupID string) error TransferOwner(userID string, groupID string, newOwnerID string) error GetUserGroups(userID string, page, pageSize int) ([]model.Group, int64, error) @@ -300,7 +300,7 @@ func (s *groupService) GetMemberCount(groupID string) (int, error) { } // UpdateGroup 更新群组信息 -func (s *groupService) UpdateGroup(userID string, groupID string, updates map[string]interface{}) error { +func (s *groupService) UpdateGroup(userID string, groupID string, updates map[string]any) error { // 检查群组是否存在 group, err := s.groupRepo.GetByID(groupID) if err != nil { @@ -448,7 +448,7 @@ func (s *groupService) broadcastMemberJoinNotice(groupID string, targetUserID st ConversationID: conv.ID, SenderID: model.SystemSenderIDStr, Segments: model.MessageSegments{ - {Type: "text", Data: map[string]interface{}{"text": noticeContent}}, + {Type: "text", Data: map[string]any{"text": noticeContent}}, }, Status: model.MessageStatusNormal, Category: model.CategoryNotification, @@ -1360,7 +1360,7 @@ func (s *groupService) MuteMember(userID string, groupID string, targetUserID st ConversationID: conv.ID, SenderID: model.SystemSenderIDStr, Segments: model.MessageSegments{ - {Type: "text", Data: map[string]interface{}{"text": noticeContent}}, + {Type: "text", Data: map[string]any{"text": noticeContent}}, }, Status: model.MessageStatusNormal, Category: model.CategoryNotification, diff --git a/internal/service/hot_rank_worker.go b/internal/service/hot_rank_worker.go index 02bbcdb..510deee 100644 --- a/internal/service/hot_rank_worker.go +++ b/internal/service/hot_rank_worker.go @@ -1,10 +1,11 @@ package service import ( + "cmp" "context" "errors" "math" - "sort" + "slices" "sync" "time" @@ -103,9 +104,7 @@ func (w *HotRankWorker) Refresh(ctx context.Context) error { if topN <= 0 { topN = 100 } - if topN > 500 { - topN = 500 - } + topN = min(topN, 500) recentHours := w.cfg.HotRank.RecentWindowHours if recentHours <= 0 { recentHours = 168 @@ -176,15 +175,8 @@ func (w *HotRankWorker) Refresh(ctx context.Context) error { raw[i] = base / denom } - minR, maxR := raw[0], raw[0] - for _, v := range raw[1:] { - if v < minR { - minR = v - } - if v > maxR { - maxR = v - } - } + minR := slices.Min(raw) + maxR := slices.Max(raw) ranked = make([]scored, len(snapshots)) for i := range snapshots { @@ -196,11 +188,16 @@ func (w *HotRankWorker) Refresh(ctx context.Context) error { } ranked[i] = scored{idx: i, norm: norm} } - sort.Slice(ranked, func(a, b int) bool { - if ranked[a].norm != ranked[b].norm { - return ranked[a].norm > ranked[b].norm + slices.SortFunc(ranked, func(a, b scored) int { + if a.norm != b.norm { + return cmp.Compare(b.norm, a.norm) // 降序 } - return snapshots[ranked[a].idx].CreatedAt.After(snapshots[ranked[b].idx].CreatedAt) + if snapshots[a.idx].CreatedAt.After(snapshots[b.idx].CreatedAt) { + return -1 + } else if snapshots[a.idx].CreatedAt.Before(snapshots[b.idx].CreatedAt) { + return 1 + } + return 0 }) } diff --git a/internal/service/log_cleanup_service.go b/internal/service/log_cleanup_service.go index a68f676..b3d0344 100644 --- a/internal/service/log_cleanup_service.go +++ b/internal/service/log_cleanup_service.go @@ -198,7 +198,7 @@ func NewLogService( } // GetLogCleanupServiceFromApp 从应用中获取日志清理服务 -func GetLogCleanupServiceFromApp(app interface{}) LogCleanupService { +func GetLogCleanupServiceFromApp(app any) LogCleanupService { // 这里需要根据实际的app结构来获取 // 暂时返回nil,实际使用时需要实现 return nil diff --git a/internal/service/post_service.go b/internal/service/post_service.go index 2ec6d0b..046e122 100644 --- a/internal/service/post_service.go +++ b/internal/service/post_service.go @@ -66,8 +66,7 @@ type PostService interface { IncrementViews(ctx context.Context, postID, userID string) error // RecordShare 记录分享(仅已发布帖子计数 +1),返回最新 shares_count RecordShare(ctx context.Context, postID, userID string) (sharesCount int, err error) - - } +} // postServiceImpl 帖子服务实现 type postServiceImpl struct { @@ -103,9 +102,9 @@ func (s *postServiceImpl) Create(ctx context.Context, userID, title, content str post := &model.Post{ UserID: userID, ChannelID: channelID, - Title: title, - Content: content, - Status: model.PostStatusPending, + Title: title, + Content: content, + Status: model.PostStatusPending, } err := s.postRepo.Create(post, images) @@ -166,7 +165,7 @@ func (s *postServiceImpl) reviewPostAsync(postID, userID, title, content string, Content: content, Images: images, AuthorID: authorID, - }, map[string]interface{}{ + }, map[string]any{ "result": result, }) diff --git a/internal/service/push_service.go b/internal/service/push_service.go index 1c3dc54..5f8e3b8 100644 --- a/internal/service/push_service.go +++ b/internal/service/push_service.go @@ -41,7 +41,7 @@ type PushService interface { PushToUser(ctx context.Context, userID string, message *model.Message, priority int) error // 系统消息推送 - PushSystemMessage(ctx context.Context, userID string, msgType, title, content string, data map[string]interface{}) error + PushSystemMessage(ctx context.Context, userID string, msgType, title, content string, data map[string]any) error // 系统通知推送(新接口,使用独立的 SystemNotification 模型) PushSystemNotification(ctx context.Context, userID string, notification *model.SystemNotification) error @@ -148,17 +148,17 @@ func (s *pushServiceImpl) pushViaWebSocket(ctx context.Context, userID string, m // 从 segments 中提取文本内容 content := dto.ExtractTextContentFromModel(message.Segments) - notification := map[string]interface{}{ + notification := map[string]any{ "id": fmt.Sprintf("%s", message.ID), "type": string(message.SystemType), "content": content, - "extra": map[string]interface{}{}, + "extra": map[string]any{}, "created_at": message.CreatedAt.UnixMilli(), } // 填充额外数据 if message.ExtraData != nil { - extra := notification["extra"].(map[string]interface{}) + extra := notification["extra"].(map[string]any) extra["actor_id"] = message.ExtraData.ActorID extra["actor_name"] = message.ExtraData.ActorName extra["avatar_url"] = message.ExtraData.AvatarURL @@ -167,7 +167,7 @@ func (s *pushServiceImpl) pushViaWebSocket(ctx context.Context, userID string, m extra["action_url"] = message.ExtraData.ActionURL extra["action_time"] = message.ExtraData.ActionTime if message.ExtraData.ActorID > 0 { - notification["trigger_user"] = map[string]interface{}{ + notification["trigger_user"] = map[string]any{ "id": fmt.Sprintf("%d", message.ExtraData.ActorID), "username": message.ExtraData.ActorName, "avatar": message.ExtraData.AvatarURL, @@ -200,7 +200,7 @@ func (s *pushServiceImpl) pushViaWebSocket(ctx context.Context, userID string, m SenderID: message.SenderID, } - s.wsHub.PublishToUser(userID, "chat_message", map[string]interface{}{ + s.wsHub.PublishToUser(userID, "chat_message", map[string]any{ "detail_type": detailType, "message": event, }) @@ -432,7 +432,7 @@ func (s *pushServiceImpl) doRetry() { } // PushSystemMessage 推送系统消息 -func (s *pushServiceImpl) PushSystemMessage(ctx context.Context, userID string, msgType, title, content string, data map[string]interface{}) error { +func (s *pushServiceImpl) PushSystemMessage(ctx context.Context, userID string, msgType, title, content string, data map[string]any) error { // 首先尝试WebSocket推送 if s.pushSystemViaWebSocket(ctx, userID, msgType, title, content, data) { return nil @@ -444,12 +444,12 @@ func (s *pushServiceImpl) PushSystemMessage(ctx context.Context, userID string, } // pushSystemViaWebSocket 通过WebSocket推送系统消息 -func (s *pushServiceImpl) pushSystemViaWebSocket(ctx context.Context, userID string, msgType, title, content string, data map[string]interface{}) bool { +func (s *pushServiceImpl) pushSystemViaWebSocket(ctx context.Context, userID string, msgType, title, content string, data map[string]any) bool { if s.wsHub == nil || !s.wsHub.HasClients(userID) { return false } - sysMsg := map[string]interface{}{ + sysMsg := map[string]any{ "type": msgType, "title": title, "content": content, @@ -477,18 +477,18 @@ func (s *pushServiceImpl) pushSystemNotificationViaWebSocket(ctx context.Context return false } - wsNotification := map[string]interface{}{ + wsNotification := map[string]any{ "id": fmt.Sprintf("%d", notification.ID), "type": string(notification.Type), "title": notification.Title, "content": notification.Content, - "extra": map[string]interface{}{}, + "extra": map[string]any{}, "created_at": notification.CreatedAt.UnixMilli(), } // 填充额外数据 if notification.ExtraData != nil { - extra := wsNotification["extra"].(map[string]interface{}) + extra := wsNotification["extra"].(map[string]any) extra["actor_id_str"] = notification.ExtraData.ActorIDStr extra["actor_name"] = notification.ExtraData.ActorName extra["avatar_url"] = notification.ExtraData.AvatarURL @@ -499,7 +499,7 @@ func (s *pushServiceImpl) pushSystemNotificationViaWebSocket(ctx context.Context // 设置触发用户信息 if notification.ExtraData.ActorIDStr != "" { - wsNotification["trigger_user"] = map[string]interface{}{ + wsNotification["trigger_user"] = map[string]any{ "id": notification.ExtraData.ActorIDStr, "username": notification.ExtraData.ActorName, "avatar": notification.ExtraData.AvatarURL, diff --git a/internal/service/qrcode_login_service.go b/internal/service/qrcode_login_service.go index ea896a5..ce7d5c3 100644 --- a/internal/service/qrcode_login_service.go +++ b/internal/service/qrcode_login_service.go @@ -54,7 +54,7 @@ type QRCodeSession struct { // QRCodeLoginService 二维码登录服务 type QRCodeLoginService struct { redis *redis.Client - wsHub *ws.Hub + wsHub *ws.Hub jwtService *JWTService userService UserService activityService UserActivityService @@ -65,7 +65,7 @@ type QRCodeLoginService struct { func NewQRCodeLoginService(redis *redis.Client, wsHub *ws.Hub, jwtService *JWTService, userService UserService, activityService UserActivityService, logService *LogService) *QRCodeLoginService { return &QRCodeLoginService{ redis: redis, - wsHub: wsHub, + wsHub: wsHub, jwtService: jwtService, userService: userService, activityService: activityService, @@ -87,7 +87,7 @@ func (s *QRCodeLoginService) CreateSession(ctx context.Context) (*QRCodeSession, } key := qrcodeSessionPrefix + sessionID - data := map[string]interface{}{ + data := map[string]any{ "status": string(session.Status), "user_id": "", "created_at": session.CreatedAt, @@ -275,7 +275,7 @@ func (s *QRCodeLoginService) Cancel(ctx context.Context, sessionID, userID strin } // 推送取消事件 - s.wsHub.PublishToUser(sessionID, "cancelled", map[string]interface{}{}) + s.wsHub.PublishToUser(sessionID, "cancelled", map[string]any{}) return nil } diff --git a/internal/service/sensitive_service.go b/internal/service/sensitive_service.go index fc57ae8..a95998d 100644 --- a/internal/service/sensitive_service.go +++ b/internal/service/sensitive_service.go @@ -389,7 +389,7 @@ func (s *sensitiveServiceImpl) AddWord(ctx context.Context, word string, categor // 同步到 Redis if s.redis != nil && s.config.RedisKeyPrefix != "" { key := fmt.Sprintf("%s:%s", s.config.RedisKeyPrefix, word) - data := map[string]interface{}{ + data := map[string]any{ "word": word, "category": category, "level": level, @@ -498,7 +498,7 @@ func (s *sensitiveServiceImpl) loadFromRedis(ctx context.Context) error { continue } - var wordData map[string]interface{} + var wordData map[string]any if err := json.Unmarshal([]byte(data), &wordData); err != nil { continue }