fix: golangci-lint 零告警通过 (57→0) + gofumpt/goimports 全量格式化
## CI 修复 (P0/P1) P0 — 编译阻塞: - interfaces.go: postUseCase ISP 接口移除不用的 Create/Update/Delete P1 — 必须修复: - ST1000: 为 13 个包添加包注释 (common/config/model/service/...) - ST1005: redis_store.go 全部错误消息改为小写开头 - errcheck (19处): defer Close()→闭包忽略, notifier.Create→_=, r.Run→检查error - errorlint (9处): switch-on-error→errors.Is 链, ==→errors.Is - ST1020/ST1022: 导出符号注释以符号名开头 P2 — 安全评审: - gosec (12处): G203/G301/G304/G306 添加 nolint 注释并附理由 P3 — 清理: - unused: 移除 hasUnicode/energyStore/current/energyAdminUseCase - gofumpt + goimports 全量格式化 (35+ 文件)
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
// Package common 提供通用工具函数、错误哨兵和响应辅助方法。
|
||||
package common
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
@ -37,4 +37,3 @@ func ClearSessionCookie(c *gin.Context, cfg *config.Config, siteSettings *config
|
||||
secure := siteSettings.CookieSecure()
|
||||
c.SetCookie(SessionCookieName, "", -1, "/", "", secure, true)
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ var (
|
||||
ErrEmailExists = errors.New("该邮箱已注册")
|
||||
ErrUsernameTaken = errors.New("该用户名已被占用")
|
||||
ErrUsernameInvalid = errors.New("用户名格式无效(支持中英文、数字、下划线、连字符,1-16个字符)")
|
||||
ErrBioTooLong = errors.New("个性签名不能超过 128 个字符")
|
||||
ErrBioTooLong = errors.New("个性签名不能超过 128 个字符")
|
||||
ErrInvalidCred = errors.New("邮箱或密码错误")
|
||||
ErrUserNotFound = errors.New("用户不存在")
|
||||
ErrUserBanned = errors.New("该账号已被封禁")
|
||||
@ -24,10 +24,10 @@ var (
|
||||
ErrPermissionDenied = errors.New("权限不足")
|
||||
|
||||
// 审核相关
|
||||
ErrAuditNotFound = errors.New("审核记录不存在")
|
||||
ErrAuditNotFound = errors.New("审核记录不存在")
|
||||
ErrAuditNotPending = errors.New("该审核记录已处理")
|
||||
ErrAuditDisabled = errors.New("审核功能未开启")
|
||||
ErrAuditTypeOff = errors.New("该类型审核未开启")
|
||||
ErrAuditDisabled = errors.New("审核功能未开启")
|
||||
ErrAuditTypeOff = errors.New("该类型审核未开启")
|
||||
|
||||
// 密码 & 注销相关
|
||||
ErrIncorrectPassword = errors.New("当前密码错误")
|
||||
@ -38,24 +38,24 @@ var (
|
||||
ErrMaintenanceMode = errors.New("社区正在维护中,仅站长可登录")
|
||||
|
||||
// 帖子相关
|
||||
ErrPostNotFound = errors.New("帖子不存在")
|
||||
ErrPostCannotEdit = errors.New("当前状态不允许编辑")
|
||||
ErrScheduledTooSoon = errors.New("定时发布时间至少需晚于当前 30 分钟")
|
||||
ErrPostCannotSubmit = errors.New("仅草稿和已退回帖子可提交审核")
|
||||
ErrPostCannotApprove = errors.New("仅待审核帖子可通过")
|
||||
ErrPostCannotReject = errors.New("仅待审核和已发布帖子可退回")
|
||||
ErrPostCannotLock = errors.New("待审核帖子不允许锁定")
|
||||
ErrPostCannotUnlock = errors.New("仅锁定状态可解锁")
|
||||
ErrPostNotFound = errors.New("帖子不存在")
|
||||
ErrPostCannotEdit = errors.New("当前状态不允许编辑")
|
||||
ErrScheduledTooSoon = errors.New("定时发布时间至少需晚于当前 30 分钟")
|
||||
ErrPostCannotSubmit = errors.New("仅草稿和已退回帖子可提交审核")
|
||||
ErrPostCannotApprove = errors.New("仅待审核帖子可通过")
|
||||
ErrPostCannotReject = errors.New("仅待审核和已发布帖子可退回")
|
||||
ErrPostCannotLock = errors.New("待审核帖子不允许锁定")
|
||||
ErrPostCannotUnlock = errors.New("仅锁定状态可解锁")
|
||||
|
||||
// 域能相关
|
||||
ErrInvalidEnergyAmount = errors.New("无效的赋能数量")
|
||||
ErrCannotEnergizeSelf = errors.New("不能给自己的文章赋能")
|
||||
ErrInsufficientEnergy = errors.New("域能不足,可通过每日签到或创作被赋能获取")
|
||||
ErrEnergizeLimitReached = errors.New("对该文章赋能已达上限")
|
||||
ErrCreatePostNoExp = errors.New("经验不足,Lv1 解锁投稿")
|
||||
ErrInsufficientFund = errors.New("公户余额不足,无法执行操作")
|
||||
ErrInvalidEnergyAmount = errors.New("无效的赋能数量")
|
||||
ErrCannotEnergizeSelf = errors.New("不能给自己的文章赋能")
|
||||
ErrInsufficientEnergy = errors.New("域能不足,可通过每日签到或创作被赋能获取")
|
||||
ErrEnergizeLimitReached = errors.New("对该文章赋能已达上限")
|
||||
ErrCreatePostNoExp = errors.New("经验不足,Lv1 解锁投稿")
|
||||
ErrInsufficientFund = errors.New("公户余额不足,无法执行操作")
|
||||
|
||||
// 评论相关
|
||||
ErrCommentNotFound = errors.New("评论不存在")
|
||||
ErrCommentEmpty = errors.New("评论内容不能为空")
|
||||
ErrCommentNotFound = errors.New("评论不存在")
|
||||
ErrCommentEmpty = errors.New("评论内容不能为空")
|
||||
)
|
||||
|
||||
@ -7,11 +7,11 @@ import (
|
||||
|
||||
// SaveUploadedFile 将 multipart.File 内容写入目标路径
|
||||
func SaveUploadedFile(file multipart.File, dst string) error {
|
||||
out, err := os.Create(dst)
|
||||
out, err := os.Create(dst) //nolint:gosec // dst 为服务器内部路径
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
defer func() { _ = out.Close() }()
|
||||
|
||||
buf := make([]byte, 32*1024)
|
||||
for {
|
||||
|
||||
@ -35,7 +35,7 @@ func ComputeAssetHashes(templateDir string) {
|
||||
|
||||
// walkStaticDir 遍历目录,计算每个 .js/.css 的 CRC32,存入 assetHashes
|
||||
func walkStaticDir(dir, urlPrefix string) {
|
||||
filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||
_ = filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil || d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
@ -43,7 +43,7 @@ func walkStaticDir(dir, urlPrefix string) {
|
||||
if ext != ".js" && ext != ".css" {
|
||||
return nil
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
data, err := os.ReadFile(path) //nolint:gosec // path 来自 filepath.WalkDir 遍历,非用户输入
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -57,5 +57,5 @@ func PageCount(total int64, pageSize int) int {
|
||||
return int((total + int64(pageSize) - 1) / int64(pageSize))
|
||||
}
|
||||
|
||||
// 固定时间格式,前后端统一
|
||||
// TimeFormat 固定时间格式,前后端统一。
|
||||
const TimeFormat = time.RFC3339
|
||||
|
||||
@ -20,8 +20,8 @@ func NewRedisClient(cfg config.RedisConfig) (*redis.Client, error) {
|
||||
DialTimeout: 1 * time.Second, // 连接超时降低(默认 5s),配合 FallbackStore 快速降级
|
||||
ReadTimeout: 1 * time.Second,
|
||||
WriteTimeout: 1 * time.Second,
|
||||
MaxRetries: 1, // 最多重试 1 次(默认 3 次),减少故障阻塞时间
|
||||
PoolSize: 5, // 会话存储不需要大连接池(默认 10*GOMAXPROCS)
|
||||
MaxRetries: 1, // 最多重试 1 次(默认 3 次),减少故障阻塞时间
|
||||
PoolSize: 5, // 会话存储不需要大连接池(默认 10*GOMAXPROCS)
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
@ -29,7 +29,7 @@ func NewRedisClient(cfg config.RedisConfig) (*redis.Client, error) {
|
||||
|
||||
if err := client.Ping(ctx).Err(); err != nil {
|
||||
log.Printf("[Redis] 连接失败: %v,将降级为内存存储", err)
|
||||
return client, fmt.Errorf("Redis 连接失败: %w", err)
|
||||
return client, fmt.Errorf("redis 连接失败: %w", err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 统一 JSON 响应
|
||||
|
||||
@ -7,8 +7,10 @@ import (
|
||||
)
|
||||
|
||||
// usernameChars 随机用户名字符集(小写字母 + 数字)
|
||||
const usernameChars = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
const usernameLen = 10
|
||||
const (
|
||||
usernameChars = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
usernameLen = 10
|
||||
)
|
||||
|
||||
// UsernameChecker 用户名查重接口(避免 common 反向依赖 repository)
|
||||
type UsernameChecker interface {
|
||||
|
||||
Reference in New Issue
Block a user