Repository: apache/answer

Issue:
After installation, the default-generated Q&A does not have initial version information when edited.
## Describe the bug

After installation, the default-generated Q&A does not have initial version information when edited.

## Expected behavior

Like a normal post with an edit history.

## Screenshots

<img width="788" height="557" alt="Image" src="https://github.com/user-attachments/assets/68aef33e-3590-438e-b27d-d23887d8508e" />

## Platform

- Version: v1.7.0


Discussion:
@krypt0n123: GN！The fix (PR #1447) has been merged. Should we close this issue now, or wait for the next release?@fenbox: @krypt0n123 We will close when the next version release. This can avoid duplicate issues.

Solution patch:
diff --git a/.golangci.yaml b/.golangci.yaml
index 611b49bc..09fca51c 100644
--- a/.golangci.yaml
+++ b/.golangci.yaml
@@ -29,6 +29,13 @@ linters:
     - bodyclose # checks whether HTTP response body is closed successfully
     - canonicalheader # checks whether net/http.Header uses canonical header
     - copyloopvar # detects places where loop variables are copied (Go 1.22+)
+    - gocritic # provides diagnostics that check for bugs, performance and style issues
+    - misspell # finds commonly misspelled English words in comments and strings
+    - modernize # detects code that can be modernized to use newer Go features
+    - testifylint # checks usage of github.com/stretchr/testify
+    - unconvert # removes unnecessary type conversions
+    - unparam # reports unused function parameters
+    - whitespace # detects leading and trailing whitespace
 
 formatters:
   enable:
diff --git a/i18n/cs_CZ.yaml b/i18n/cs_CZ.yaml
index d9f972a6..ab53cb63 100644
--- a/i18n/cs_CZ.yaml
+++ b/i18n/cs_CZ.yaml
@@ -234,7 +234,7 @@ backend:
         other: Nemáte oprávnění pro aktualizaci.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/cy_GB.yaml b/i18n/cy_GB.yaml
index 267070a0..5a5b9a65 100644
--- a/i18n/cy_GB.yaml
+++ b/i18n/cy_GB.yaml
@@ -234,7 +234,7 @@ backend:
         other: Dim caniatâd i ddiweddaru.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/da_DK.yaml b/i18n/da_DK.yaml
index d3f410e4..37adc7db 100644
--- a/i18n/da_DK.yaml
+++ b/i18n/da_DK.yaml
@@ -234,7 +234,7 @@ backend:
         other: Ingen tilladelse til at opdatere.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/de_DE.yaml b/i18n/de_DE.yaml
index d7683f03..542dca9b 100644
--- a/i18n/de_DE.yaml
+++ b/i18n/de_DE.yaml
@@ -234,7 +234,7 @@ backend:
         other: Keine Berechtigung zum Aktualisieren.
       content_cannot_empty:
         other: Der Inhalt darf nicht leer sein.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/en_US.yaml b/i18n/en_US.yaml
index 40017b75..6ff6ef3c 100644
--- a/i18n/en_US.yaml
+++ b/i18n/en_US.yaml
@@ -235,7 +235,7 @@ backend:
         other: No permission to update.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/es_ES.yaml b/i18n/es_ES.yaml
index 99071e2f..f53a2810 100644
--- a/i18n/es_ES.yaml
+++ b/i18n/es_ES.yaml
@@ -234,7 +234,7 @@ backend:
         other: Sin permiso para actualizar.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/fa_IR.yaml b/i18n/fa_IR.yaml
index 600d5cc1..d013d017 100644
--- a/i18n/fa_IR.yaml
+++ b/i18n/fa_IR.yaml
@@ -234,7 +234,7 @@ backend:
         other: اجازه بروزرسانی ندارید.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/fr_FR.yaml b/i18n/fr_FR.yaml
index ecb87bef..879906fa 100644
--- a/i18n/fr_FR.yaml
+++ b/i18n/fr_FR.yaml
@@ -234,7 +234,7 @@ backend:
         other: Pas de permission pour mettre à jour.
       content_cannot_empty:
         other: Le contenu ne peut pas être vide.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/hi_IN.yaml b/i18n/hi_IN.yaml
index 09be6201..eb0cb50b 100644
--- a/i18n/hi_IN.yaml
+++ b/i18n/hi_IN.yaml
@@ -234,7 +234,7 @@ backend:
         other: No permission to update.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/id_ID.yaml b/i18n/id_ID.yaml
index f8a4a8a8..43c0d70d 100644
--- a/i18n/id_ID.yaml
+++ b/i18n/id_ID.yaml
@@ -234,7 +234,7 @@ backend:
         other: Tidak diizinkan untuk memperbarui.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/it_IT.yaml b/i18n/it_IT.yaml
index 29cd1f52..50f60aa6 100644
--- a/i18n/it_IT.yaml
+++ b/i18n/it_IT.yaml
@@ -234,7 +234,7 @@ backend:
         other: Nessun permesso per l'aggiornamento.
       content_cannot_empty:
         other: Il contenuto non può essere vuoto.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/ja_JP.yaml b/i18n/ja_JP.yaml
index 8e2fb52c..4bfe45c9 100644
--- a/i18n/ja_JP.yaml
+++ b/i18n/ja_JP.yaml
@@ -234,7 +234,7 @@ backend:
         other: 更新する権限がありません。
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/ko_KR.yaml b/i18n/ko_KR.yaml
index be180745..0ddefa61 100644
--- a/i18n/ko_KR.yaml
+++ b/i18n/ko_KR.yaml
@@ -234,7 +234,7 @@ backend:
         other: 업데이트 권한이 없습니다.
       content_cannot_empty:
         other: 내용은 비워둘 수 없습니다.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/ml_IN.yaml b/i18n/ml_IN.yaml
index 42135031..e2cac0e0 100644
--- a/i18n/ml_IN.yaml
+++ b/i18n/ml_IN.yaml
@@ -234,7 +234,7 @@ backend:
         other: No permission to update.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/pl_PL.yaml b/i18n/pl_PL.yaml
index ae26c6d1..e5972d9b 100644
--- a/i18n/pl_PL.yaml
+++ b/i18n/pl_PL.yaml
@@ -234,7 +234,7 @@ backend:
         other: Brak uprawnień do edycji.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/pt_PT.yaml b/i18n/pt_PT.yaml
index 997bb055..5989071e 100644
--- a/i18n/pt_PT.yaml
+++ b/i18n/pt_PT.yaml
@@ -234,7 +234,7 @@ backend:
         other: Sem permissão para atualizar.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/ro_RO.yaml b/i18n/ro_RO.yaml
index cd0afb8a..43af2180 100644
--- a/i18n/ro_RO.yaml
+++ b/i18n/ro_RO.yaml
@@ -234,7 +234,7 @@ backend:
         other: Nu aveți permisiunea de a actualiza.
       content_cannot_empty:
         other: Conținutul nu poate fi gol.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/ru_RU.yaml b/i18n/ru_RU.yaml
index c554ac8d..458fd2e6 100644
--- a/i18n/ru_RU.yaml
+++ b/i18n/ru_RU.yaml
@@ -234,7 +234,7 @@ backend:
         other: Нет разрешения на обновление.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/sk_SK.yaml b/i18n/sk_SK.yaml
index 72bd4726..cd629fc9 100644
--- a/i18n/sk_SK.yaml
+++ b/i18n/sk_SK.yaml
@@ -234,7 +234,7 @@ backend:
         other: Žiadne povolenie na aktualizáciu.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/sv_SE.yaml b/i18n/sv_SE.yaml
index 243703ce..abf58112 100644
--- a/i18n/sv_SE.yaml
+++ b/i18n/sv_SE.yaml
@@ -162,7 +162,7 @@ backend:
       cannot_modify_self_status:
         other: Du får inte ändra din status.
       email_or_password_wrong:
-        other: Fel e-post eller lösenord. 
+        other: Fel e-post eller lösenord.
     answer:
       not_found:
         other: Svar hittades inte.
@@ -189,12 +189,12 @@ backend:
       need_to_be_verified:
         other: E-postadressen ska vara verifierad.
       verify_url_expired:
-        other: Länken för att verifiera e-postadressen har gått ut. Vänligen skicka igen. 
+        other: Länken för att verifiera e-postadressen har gått ut. Vänligen skicka igen.
       illegal_email_domain_error:
-        other: E-post från den domänen tillåts inte. Vänligen använt en annan. 
+        other: E-post från den domänen tillåts inte. Vänligen använt en annan.
     lang:
       not_found:
-        other: Språkfilen hittas inte. 
+        other: Språkfilen hittas inte.
     object:
       captcha_verification_failed:
         other: Fel Captcha.
@@ -234,7 +234,7 @@ backend:
         other: No permission to update.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/te_IN.yaml b/i18n/te_IN.yaml
index dbf4acb1..9e80aa8d 100644
--- a/i18n/te_IN.yaml
+++ b/i18n/te_IN.yaml
@@ -234,7 +234,7 @@ backend:
         other: No permission to update.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/tr_TR.yaml b/i18n/tr_TR.yaml
index fdecee53..92d97ebe 100644
--- a/i18n/tr_TR.yaml
+++ b/i18n/tr_TR.yaml
@@ -234,7 +234,7 @@ backend:
         other: Güncelleme izni yok.
       content_cannot_empty:
         other: İçerik boş olamaz.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/uk_UA.yaml b/i18n/uk_UA.yaml
index ea0e4591..67496262 100644
--- a/i18n/uk_UA.yaml
+++ b/i18n/uk_UA.yaml
@@ -234,7 +234,7 @@ backend:
         other: Немає дозволу на оновлення.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/vi_VN.yaml b/i18n/vi_VN.yaml
index 6f5e5cbb..af01b1da 100644
--- a/i18n/vi_VN.yaml
+++ b/i18n/vi_VN.yaml
@@ -234,7 +234,7 @@ backend:
         other: Không có quyền cập nhật.
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/zh_CN.yaml b/i18n/zh_CN.yaml
index 0f7a2515..35321ac1 100644
--- a/i18n/zh_CN.yaml
+++ b/i18n/zh_CN.yaml
@@ -234,7 +234,7 @@ backend:
         other: 没有更新权限。
       content_cannot_empty:
         other: 内容不能为空。
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: 输入的内容不足。
     rank:
       fail_to_meet_the_condition:
diff --git a/i18n/zh_TW.yaml b/i18n/zh_TW.yaml
index cc362ea1..4b239c1e 100644
--- a/i18n/zh_TW.yaml
+++ b/i18n/zh_TW.yaml
@@ -234,7 +234,7 @@ backend:
         other: 無更新權限。
       content_cannot_empty:
         other: Content cannot be empty.
-      content_less_than_minumum:
+      content_less_than_minimum:
         other: Not enough content entered.
     rank:
       fail_to_meet_the_condition:
diff --git a/internal/base/middleware/avatar.go b/internal/base/middleware/avatar.go
index 98430638..42b28da9 100644
--- a/internal/base/middleware/avatar.go
+++ b/internal/base/middleware/avatar.go
@@ -80,7 +80,6 @@ func (am *AvatarMiddleware) AvatarThumb() gin.HandlerFunc {
 			}
 			ctx.Abort()
 			return
-
 		} else {
 			urlInfo, err := url.Parse(uri)
 			if err != nil {
diff --git a/internal/base/reason/reason.go b/internal/base/reason/reason.go
index 42e29f4c..97aaa75a 100644
--- a/internal/base/reason/reason.go
+++ b/internal/base/reason/reason.go
@@ -47,7 +47,7 @@ const (
 	QuestionAlreadyDeleted           = "error.question.already_deleted"
 	QuestionUnderReview              = "error.question.under_review"
 	QuestionContentCannotEmpty       = "error.question.content_cannot_empty"
-	QuestionContentLessThanMinimum   = "error.question.content_less_than_minumum"
+	QuestionContentLessThanMinimum   = "error.question.content_less_than_minimum"
 	AnswerNotFound                   = "error.answer.not_found"
 	AnswerCannotDeleted              = "error.answer.cannot_deleted"
 	AnswerCannotUpdate               = "error.answer.cannot_update"
diff --git a/internal/base/server/http.go b/internal/base/server/http.go
index 088bbc9e..4fbb04cb 100644
--- a/internal/base/server/http.go
+++ b/internal/base/server/http.go
@@ -44,7 +44,6 @@ func NewHTTPServer(debug bool,
 	pluginAPIRouter *router.PluginAPIRouter,
 	uiConf *UI,
 ) *gin.Engine {
-
 	if debug {
 		gin.SetMode(gin.DebugMode)
 	} else {
diff --git a/internal/base/server/http_funcmap.go b/internal/base/server/http_funcmap.go
index db460457..a5d530b5 100644
--- a/internal/base/server/http_funcmap.go
+++ b/internal/base/server/http_funcmap.go
@@ -134,9 +134,7 @@ var funcMap = template.FuncMap{
 			"timezone": tz,
 		}
 	},
-	"urlTitle": func(title string) string {
-		return htmltext.UrlTitle(title)
-	},
+	"urlTitle": htmltext.UrlTitle,
 }
 
 func FormatLinkNofollow(html string) string {
diff --git a/internal/controller/question_controller.go b/internal/controller/question_controller.go
index 4b1869fa..581cf548 100644
--- a/internal/controller/question_controller.go
+++ b/internal/controller/question_controller.go
@@ -287,7 +287,6 @@ func (qc *QuestionController) GetQuestionInviteUserInfo(ctx *gin.Context) {
 	questionID := uid.DeShortID(ctx.Query("id"))
 	resp, err := qc.questionService.InviteUserInfo(ctx, questionID)
 	handler.HandleResponse(ctx, err, resp)
-
 }
 
 // SimilarQuestion godoc
@@ -578,7 +577,7 @@ func (qc *QuestionController) AddQuestionByAnswer(ctx *gin.Context) {
 		handler.HandleResponse(ctx, errors.BadRequest(reason.RequestFormatError), errFields)
 		return
 	}
-	//add the question id to the answer
+	// add the question id to the answer
 	questionInfo, ok := resp.(*schema.QuestionInfoResp)
 	if ok {
 		answerReq := &schema.AnswerAddReq{}
diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go
index 801e129c..f6a442c2 100644
--- a/internal/controller/template_controller.go
+++ b/internal/controller/template_controller.go
@@ -263,14 +263,13 @@ func (tc *TemplateController) QuestionInfoRedirect(ctx *gin.Context, siteInfo *s
 		if needChangeShortID {
 			return true, url
 		}
-		//not have title
+		// not have title
 		if titleIsAnswerID || len(title) == 0 {
 			return false, ""
 		}
 
 		return true, url
 	} else {
-
 		detail, err := tc.templateRenderController.QuestionDetail(ctx, questionID)
 		if err != nil {
 			tc.Page404(ctx)
@@ -284,7 +283,7 @@ func (tc *TemplateController) QuestionInfoRedirect(ctx *gin.Context, siteInfo *s
 		if len(ctx.Request.URL.Query()) > 0 {
 			url = fmt.Sprintf("%s?%s", url, ctx.Request.URL.RawQuery)
 		}
-		//have title
+		// have title
 		if len(title) > 0 && !titleIsAnswerID && correctTitle {
 			if needChangeShortID {
 				return true, url
@@ -370,7 +369,7 @@ func (tc *TemplateController) QuestionInfo(ctx *gin.Context) {
 	UrlUseTitle := siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitle ||
 		siteInfo.SiteSeo.Permalink == constant.PermalinkQuestionIDAndTitleByShortID
 
-	//related question
+	// related question
 	userID := middleware.GetLoginUserIDFromContext(ctx)
 	relatedQuestion, _, _ := tc.questionService.SimilarQuestion(ctx, id, userID)
 
@@ -553,7 +552,6 @@ func (tc *TemplateController) UserInfo(ctx *gin.Context) {
 		"topQuestions": questionList,
 		"topAnswers":   answerList,
 	})
-
 }
 
 func (tc *TemplateController) Page404(ctx *gin.Context) {
diff --git a/internal/controller/template_render/comment.go b/internal/controller/template_render/comment.go
index 2862ad8d..c1265bd0 100644
--- a/internal/controller/template_render/comment.go
+++ b/internal/controller/template_render/comment.go
@@ -33,7 +33,6 @@ func (t *TemplateRenderController) CommentList(
 	comments map[string][]*schema.GetCommentResp,
 	err error,
 ) {
-
 	comments = make(map[string][]*schema.GetCommentResp, len(objectIDs))
 
 	for _, objectID := range objectIDs {
diff --git a/internal/controller/template_render/controller.go b/internal/controller/template_render/controller.go
index 3412010d..297b3f9a 100644
--- a/internal/controller/template_render/controller.go
+++ b/internal/controller/template_render/controller.go
@@ -78,10 +78,10 @@ func Paginator(page, pageSize int, nums int64) *schema.Paginator {
 		pageSize = 10
 	}
 
-	var prevpage int //Previous page address
-	var nextpage int //Address on the last page
-	//Generate the total number of pages based on the total number of nums and the number of prepage pages
-	totalpages := int(math.Ceil(float64(nums) / float64(pageSize))) //Total number of Pages
+	var prevpage int // Previous page address
+	var nextpage int // Address on the last page
+	// Generate the total number of pages based on the total number of nums and the number of prepage pages
+	totalpages := int(math.Ceil(float64(nums) / float64(pageSize))) // Total number of Pages
 	if page > totalpages {
 		page = totalpages
 	}
@@ -90,7 +90,7 @@ func Paginator(page, pageSize int, nums int64) *schema.Paginator {
 	}
 	var pages []int
 	switch {
-	case page >= totalpages-5 && totalpages > 5: //The last 5 pages
+	case page >= totalpages-5 && totalpages > 5: // The last 5 pages
 		start := totalpages - 5 + 1
 		prevpage = page - 1
 		nextpage = int(math.Min(float64(totalpages), float64(page+1)))
diff --git a/internal/controller/user_controller.go b/internal/controller/user_controller.go
index e4a3b3d3..cc89caf1 100644
--- a/internal/controller/user_controller.go
+++ b/internal/controller/user_controller.go
@@ -509,7 +509,6 @@ func (uc *UserController) ActionRecord(ctx *gin.Context) {
 		resp, err := uc.actionService.ActionRecord(ctx, req)
 		handler.HandleResponse(ctx, err, resp)
 	}
-
 }
 
 // GetUserNotificationConfig get user's notification config
diff --git a/internal/entity/collection_entity.go b/internal/entity/collection_entity.go
index 5fbd5b0e..24ae232f 100644
--- a/internal/entity/collection_entity.go
+++ b/internal/entity/collection_entity.go
@@ -33,8 +33,8 @@ type Collection struct {
 
 type CollectionSearch struct {
 	Collection
-	Page     int `json:"page" form:"page"`           //Query number of pages
-	PageSize int `json:"page_size" form:"page_size"` //Search page size
+	Page     int `json:"page" form:"page"`           // Query number of pages
+	PageSize int `json:"page_size" form:"page_size"` // Search page size
 }
 
 // TableName collection table name
diff --git a/internal/install/install_req.go b/internal/install/install_req.go
index e5b8839e..39657a54 100644
--- a/internal/install/install_req.go
+++ b/internal/install/install_req.go
@@ -65,13 +65,14 @@ func (r *CheckDatabaseReq) GetConnection() string {
 	}
 	if r.DbType == string(schemas.POSTGRES) {
 		host, port := parsePgSQLHostPort(r.DbHost)
-		if !r.Ssl {
+		switch {
+		case !r.Ssl:
 			return fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
 				host, port, r.DbUsername, r.DbPassword, r.DbName)
-		} else if r.SslMode == "require" {
+		case r.SslMode == "require":
 			return fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s",
 				host, port, r.DbUsername, r.DbPassword, r.DbName, r.SslMode)
-		} else if r.SslMode == "verify-ca" || r.SslMode == "verify-full" {
+		case r.SslMode == "verify-ca" || r.SslMode == "verify-full":
 			connection := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s",
 				host, port, r.DbUsername, r.DbPassword, r.DbName, r.SslMode)
 			if len(r.SslRootCert) > 0 && dir.CheckFileExist(r.SslRootCert) {
@@ -150,7 +151,7 @@ func (r *InitBaseInfoReq) FormatSiteUrl() {
 	}
 	r.SiteURL = fmt.Sprintf("%s://%s", parsedUrl.Scheme, parsedUrl.Host)
 	if len(parsedUrl.Path) > 0 {
-		r.SiteURL = r.SiteURL + parsedUrl.Path
+		r.SiteURL += parsedUrl.Path
 		r.SiteURL = strings.TrimSuffix(r.SiteURL, "/")
 	}
 }
diff --git a/internal/migrations/init.go b/internal/migrations/init.go
index 184c986b..8a72794f 100644
--- a/internal/migrations/init.go
+++ b/internal/migrations/init.go
@@ -28,6 +28,7 @@ import (
 	"github.com/apache/answer/internal/base/constant"
 
 	"github.com/apache/answer/internal/base/data"
+	"github.com/apache/answer/internal/repo/revision"
 	"github.com/apache/answer/internal/repo/unique"
 	"github.com/apache/answer/internal/schema"
 	"github.com/segmentfault/pacman/log"
@@ -311,6 +312,7 @@ func (m *Mentor) initSiteInfoWrite() {
 
 func (m *Mentor) initDefaultContent() {
 	uniqueIDRepo := unique.NewUniqueIDRepo(&data.Data{DB: m.engine})
+	revisionRepo := revision.NewRevisionRepo(&data.Data{DB: m.engine}, uniqueIDRepo)
 	now := time.Now()
 
 	tagId, err := uniqueIDRepo.GenUniqueIDStr(m.ctx, entity.Tag{}.TableName())
@@ -343,7 +345,7 @@ func (m *Mentor) initDefaultContent() {
 		return
 	}
 
-	tag := entity.Tag{
+	tag := &entity.Tag{
 		ID:            tagId,
 		SlugName:      "support",
 		DisplayName:   "support",
@@ -419,16 +421,74 @@ func (m *Mentor) initDefaultContent() {
 	if m.err != nil {
 		return
 	}
+	tagContent, err := json.Marshal(tag)
+	if err != nil {
+		m.err = err
+		return
+	}
+	m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{
+		UserID:   tag.UserID,
+		ObjectID: tag.ID,
+		Title:    tag.SlugName,
+		Content:  string(tagContent),
+		Status:   entity.RevisionReviewPassStatus,
+	}, true)
+	if m.err != nil {
+		return
+	}
+	tagForRevision := &entity.TagSimpleInfoForRevision{
+		ID:              tag.ID,
+		MainTagID:       tag.MainTagID,
+		MainTagSlugName: tag.MainTagSlugName,
+		SlugName:        tag.SlugName,
+		DisplayName:     tag.DisplayName,
+		Recommend:       tag.Recommend,
+		Reserved:        tag.Reserved,
+		RevisionID:      tag.RevisionID,
+	}
 
 	_, m.err = m.engine.Context(m.ctx).Insert(q1)
 	if m.err != nil {
 		return
 	}
+	q1Revision := &entity.QuestionWithTagsRevision{
+		Question: *q1,
+		Tags:     []*entity.TagSimpleInfoForRevision{tagForRevision},
+	}
+	q1Content, err := json.Marshal(q1Revision)
+	if err != nil {
+		m.err = err
+		return
+	}
+	m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{
+		UserID:   q1.UserID,
+		ObjectID: q1.ID,
+		Title:    q1.Title,
+		Content:  string(q1Content),
+		Status:   entity.RevisionReviewPassStatus,
+	}, true)
+	if m.err != nil {
+		return
+	}
 
 	_, m.err = m.engine.Context(m.ctx).Insert(a1)
 	if m.err != nil {
 		return
 	}
+	a1Content, err := json.Marshal(a1)
+	if err != nil {
+		m.err = err
+		return
+	}
+	m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{
+		UserID:   a1.UserID,
+		ObjectID: a1.ID,
+		Content:  string(a1Content),
+		Status:   entity.RevisionReviewPassStatus,
+	}, true)
+	if m.err != nil {
+		return
+	}
 
 	_, m.err = m.engine.Context(m.ctx).Insert(entity.TagRel{
 		ObjectID: q1.ID,
@@ -443,11 +503,44 @@ func (m *Mentor) initDefaultContent() {
 	if m.err != nil {
 		return
 	}
+	q2Revision := &entity.QuestionWithTagsRevision{
+		Question: *q2,
+		Tags:     []*entity.TagSimpleInfoForRevision{tagForRevision},
+	}
+	q2Content, err := json.Marshal(q2Revision)
+	if err != nil {
+		m.err = err
+		return
+	}
+	m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{
+		UserID:   q2.UserID,
+		ObjectID: q2.ID,
+		Title:    q2.Title,
+		Content:  string(q2Content),
+		Status:   entity.RevisionReviewPassStatus,
+	}, true)
+	if m.err != nil {
+		return
+	}
 
 	_, m.err = m.engine.Context(m.ctx).Insert(a2)
 	if m.err != nil {
 		return
 	}
+	a2Content, err := json.Marshal(a2)
+	if err != nil {
+		m.err = err
+		return
+	}
+	m.err = revisionRepo.AddRevision(m.ctx, &entity.Revision{
+		UserID:   a2.UserID,
+		ObjectID: a2.ID,
+		Content:  string(a2Content),
+		Status:   entity.RevisionReviewPassStatus,
+	}, true)
+	if m.err != nil {
+		return
+	}
 
 	_, m.err = m.engine.Context(m.ctx).Insert(entity.TagRel{
 		ObjectID: q2.ID,
diff --git a/internal/migrations/v12.go b/internal/migrations/v12.go
index 2dd3ce71..23e8acdc 100644
--- a/internal/migrations/v12.go
+++ b/internal/migrations/v12.go
@@ -75,7 +75,6 @@ func updateQuestionPostTime(ctx context.Context, x *xorm.Engine) error {
 				return fmt.Errorf("update question failed: %w", err)
 			}
 		}
-
 	}
 
 	return nil
diff --git a/internal/migrations/v13.go b/internal/migrations/v13.go
index 57d24848..16ba177e 100644
--- a/internal/migrations/v13.go
+++ b/internal/migrations/v13.go
@@ -136,7 +136,7 @@ func addPrivilegeForInviteSomeoneToAnswer(ctx context.Context, x *xorm.Engine) e
 }
 
 func updateQuestionCount(ctx context.Context, x *xorm.Engine) error {
-	//question answer count
+	// question answer count
 	answers := make([]AnswerV13, 0)
 	err := x.Context(ctx).Find(&answers, &AnswerV13{Status: entity.AnswerStatusAvailable})
 	if err != nil {
@@ -216,7 +216,7 @@ func updateTagCount(ctx context.Context, x *xorm.Engine) error {
 		}
 	}
 
-	//select tag count
+	// select tag count
 	newTagRelList := make([]entity.TagRel, 0)
 	err = x.Context(ctx).Find(&newTagRelList, &entity.TagRel{Status: entity.TagRelStatusAvailable})
 	if err != nil {
diff --git a/internal/repo/activity/follow_repo.go b/internal/repo/activity/follow_repo.go
index 7af2189a..4c6fc431 100644
--- a/internal/repo/activity/follow_repo.go
+++ b/internal/repo/activity/follow_repo.go
@@ -168,7 +168,7 @@ func (ar *FollowRepo) FollowCancel(ctx context.Context, objectID, userID string)
 	return err
 }
 
-func (ar *FollowRepo) updateFollows(ctx context.Context, session *xorm.Session, objectID string, follows int) error {
+func (ar *FollowRepo) updateFollows(_ context.Context, session *xorm.Session, objectID string, follows int) error {
 	objectType, err := obj.GetObjectTypeStrByObjectID(objectID)
 	if err != nil {
 		return err
diff --git a/internal/repo/activity_common/follow.go b/internal/repo/activity_common/follow.go
index 99e5a6e6..a185c3d8 100644
--- a/internal/repo/activity_common/follow.go
+++ b/internal/repo/activity_common/follow.go
@@ -66,19 +66,19 @@ func (ar *FollowRepo) GetFollowAmount(ctx context.Context, objectID string) (fol
 		model := &entity.Question{}
 		_, err = ar.data.DB.Context(ctx).Where("id = ?", objectID).Cols("`follow_count`").Get(model)
 		if err == nil {
-			follows = int(model.FollowCount)
+			follows = model.FollowCount
 		}
 	case "user":
 		model := &entity.User{}
 		_, err = ar.data.DB.Context(ctx).Where("id = ?", objectID).Cols("`follow_count`").Get(model)
 		if err == nil {
-			follows = int(model.FollowCount)
+			follows = model.FollowCount
 		}
 	case "tag":
 		model := &entity.Tag{}
 		_, err = ar.data.DB.Context(ctx).Where("id = ?", objectID).Cols("`follow_count`").Get(model)
 		if err == nil {
-			follows = int(model.FollowCount)
+			follows = model.FollowCount
 		}
 	default:
 		err = errors.InternalServer(reason.DisallowFollow).WithMsg("this object can't be followed")
diff --git a/internal/repo/answer/answer_repo.go b/internal/repo/answer/answer_repo.go
index 0f1ae814..52963c44 100644
--- a/internal/repo/answer/answer_repo.go
+++ b/internal/repo/answer/answer_repo.go
@@ -335,7 +335,7 @@ func (ar *answerRepo) SearchList(ctx context.Context, search *entity.AnswerSearc
 	var err error
 	rows := make([]*entity.Answer, 0)
 	if search.Page > 0 {
-		search.Page = search.Page - 1
+		search.Page--
 	} else {
 		search.Page = 0
 	}
diff --git a/internal/repo/collection/collection_repo.go b/internal/repo/collection/collection_repo.go
index f30692c9..482cb075 100644
--- a/internal/repo/collection/collection_repo.go
+++ b/internal/repo/collection/collection_repo.go
@@ -167,7 +167,7 @@ func (cr *collectionRepo) GetCollectionPage(ctx context.Context, page, pageSize
 
 // SearchObjectCollected check object is collected or not
 func (cr *collectionRepo) SearchObjectCollected(ctx context.Context, userID string, objectIds []string) (map[string]bool, error) {
-	for i := 0; i < len(objectIds); i++ {
+	for i := range objectIds {
 		objectIds[i] = uid.DeShortID(objectIds[i])
 	}
 
@@ -193,7 +193,7 @@ func (cr *collectionRepo) SearchList(ctx context.Context, search *entity.Collect
 	var err error
 	rows := make([]*entity.Collection, 0)
 	if search.Page > 0 {
-		search.Page = search.Page - 1
+		search.Page--
 	} else {
 		search.Page = 0
 	}
diff --git a/internal/repo/question/question_repo.go b/internal/repo/question/question_repo.go
index 3935e610..3449efb8 100644
--- a/internal/repo/question/question_repo.go
+++ b/internal/repo/question/question_repo.go
@@ -89,9 +89,9 @@ func (qr *questionRepo) RemoveQuestion(ctx context.Context, id string) (err erro
 }
 
 // UpdateQuestion update question
-func (qr *questionRepo) UpdateQuestion(ctx context.Context, question *entity.Question, Cols []string) (err error) {
+func (qr *questionRepo) UpdateQuestion(ctx context.Context, question *entity.Question, cols []string) (err error) {
 	question.ID = uid.DeShortID(question.ID)
-	_, err = qr.data.DB.Context(ctx).Where("id =?", question.ID).Cols(Cols...).Update(question)
+	_, err = qr.data.DB.Context(ctx).Where("id =?", question.ID).Cols(cols...).Update(question)
 	if err != nil {
 		return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
 	}
@@ -344,7 +344,7 @@ func (qr *questionRepo) GetUserQuestionCount(ctx context.Context, userID string,
 
 func (qr *questionRepo) SitemapQuestions(ctx context.Context, page, pageSize int) (
 	questionIDList []*schema.SiteMapQuestionInfo, err error) {
-	page = page - 1
+	page--
 	questionIDList = make([]*schema.SiteMapQuestionInfo, 0)
 
 	// try to get sitemap data from cache
@@ -524,7 +524,7 @@ func (qr *questionRepo) AdminQuestionPage(ctx context.Context, search *schema.Ad
 
 	rows := make([]*entity.Question, 0)
 	if search.Page > 0 {
-		search.Page = search.Page - 1
+		search.Page--
 	} else {
 		search.Page = 0
 	}
diff --git a/internal/repo/rank/user_rank_repo.go b/internal/repo/rank/user_rank_repo.go
index cb9ca1b3..5e86f592 100644
--- a/internal/repo/rank/user_rank_repo.go
+++ b/internal/repo/rank/user_rank_repo.go
@@ -141,7 +141,7 @@ func (ur *UserRankRepo) TriggerUserRank(ctx context.Context,
 	return false, nil
 }
 
-func (ur *UserRankRepo) checkUserMinRank(ctx context.Context, session *xorm.Session, userID string, deltaRank int) (
+func (ur *UserRankRepo) checkUserMinRank(_ context.Context, session *xorm.Session, userID string, deltaRank int) (
 	isReachStandard bool, err error,
 ) {
 	bean := &entity.User{ID: userID}
diff --git a/internal/repo/search_common/search_repo.go b/internal/repo/search_common/search_repo.go
index 80651723..a56b8edb 100644
--- a/internal/repo/search_common/search_repo.go
+++ b/internal/repo/search_common/search_repo.go
@@ -190,7 +190,7 @@ func (sr *searchRepo) SearchContents(ctx context.Context, words []string, tagIDs
 		argsA = append(argsA, votes)
 	}
 
-	//b = b.Union("all", ub)
+	// b = b.Union("all", ub)
 	ubSQL, _, err := ub.ToSQL()
 	if err != nil {
 		return
@@ -447,7 +447,7 @@ func (sr *searchRepo) SearchAnswers(ctx context.Context, words []string, tagIDs
 	return
 }
 
-func (sr *searchRepo) parseOrder(ctx context.Context, order string) (res string) {
+func (sr *searchRepo) parseOrder(_ context.Context, order string) (res string) {
 	switch order {
 	case "newest":
 		res = "created_at desc"
diff --git a/internal/schema/backyard_user_schema.go b/internal/schema/backyard_user_schema.go
index 6ec84872..d36ff808 100644
--- a/internal/schema/backyard_user_schema.go
+++ b/internal/schema/backyard_user_schema.go
@@ -222,7 +222,7 @@ func (req *AddUsersReq) ParseUsers(ctx context.Context) (errFields []*validator.
 	}
 
 	// check users amount
-	if len(req.Users) <= 0 || len(req.Users) > constant.DefaultBulkUser {
+	if len(req.Users) == 0 || len(req.Users) > constant.DefaultBulkUser {
 		errFields = append([]*validator.FormErrorField{}, &validator.FormErrorField{
 			ErrorField: "users",
 			ErrorMsg: translator.TrWithData(handler.GetLangByCtx(ctx), reason.AddBulkUsersAmountError,
diff --git a/internal/schema/meta_schema.go b/internal/schema/meta_schema.go
index 286e2e7d..e5a07252 100644
--- a/internal/schema/meta_schema.go
+++ b/internal/schema/meta_schema.go
@@ -19,6 +19,8 @@
 
 package schema
 
+import "slices"
+
 type UpdateReactionReq struct {
 	ObjectID string `validate:"required" json:"object_id"`
 	Emoji    string `validate:"required,oneof=heart smile frown" json:"emoji"`
@@ -48,13 +50,7 @@ func (r *ReactionsSummaryMeta) AddReactionSummary(emoji, userID string) {
 		if reaction.Emoji != emoji {
 			continue
 		}
-		exist := false
-		for _, id := range reaction.UserIDs {
-			if id == userID {
-				exist = true
-				break
-			}
-		}
+		exist := slices.Contains(reaction.UserIDs, userID)
 		if !exist {
 			reaction.UserIDs = append(reaction.UserIDs, userID)
 		}
@@ -94,10 +90,8 @@ func (r *ReactionsSummaryMeta) CheckUserInReactionSummary(emoji, userID string)
 		if reaction.Emoji != emoji {
 			continue
 		}
-		for _, id := range reaction.UserIDs {
-			if id == userID {
-				return true
-			}
+		if slices.Contains(reaction.UserIDs, userID) {
+			return true
 		}
 	}
 	return false
diff --git a/internal/schema/notification_schema.go b/internal/schema/notification_schema.go
index e5d60615..b9e02938 100644
--- a/internal/schema/notification_schema.go
+++ b/internal/schema/notification_schema.go
@@ -53,7 +53,7 @@ var NotificationInboxType = map[string]int{
 
 type NotificationContent struct {
 	ID                 string         `json:"id"`
-	TriggerUserID      string         `json:"-"` //show userid
+	TriggerUserID      string         `json:"-"` // show userid
 	ReceiverUserID     string         `json:"-"` // receiver userid
 	UserInfo           *UserBasicInfo `json:"user_info,omitempty"`
 	ObjectInfo         ObjectInfo     `json:"object_info"`
@@ -169,8 +169,8 @@ func (r *RedDotBadgeAwardCache) RemoveBadgeAward(notificationID string) {
 }
 
 type NotificationSearch struct {
-	Page         int    `json:"page" form:"page"`           //Query number of pages
-	PageSize     int    `json:"page_size" form:"page_size"` //Search page size
+	Page         int    `json:"page" form:"page"`           // Query number of pages
+	PageSize     int    `json:"page_size" form:"page_size"` // Search page size
 	Type         int    `json:"-" form:"-"`
 	TypeStr      string `json:"type" form:"type"`             // inbox achievement
 	InboxTypeStr string `json:"inbox_type" form:"inbox_type"` // inbox achievement
diff --git a/internal/schema/revision_schema.go b/internal/schema/revision_schema.go
index b3ac0aad..6f3246e5 100644
--- a/internal/schema/revision_schema.go
+++ b/internal/schema/revision_schema.go
@@ -53,7 +53,7 @@ const RevisionAuditReject = "reject"
 type RevisionAuditReq struct {
 	// object id
 	ID                string `validate:"required" comment:"id" form:"id"`
-	Operation         string `validate:"required" comment:"operation" form:"operation"` //approve or reject
+	Operation         string `validate:"required" comment:"operation" form:"operation"` // approve or reject
 	UserID            string `json:"-"`
 	CanReviewQuestion bool   `json:"-"`
 	CanReviewAnswer   bool   `json:"-"`
diff --git a/internal/schema/siteinfo_schema.go b/internal/schema/siteinfo_schema.go
index 0e43bb42..7ab65751 100644
--- a/internal/schema/siteinfo_schema.go
+++ b/internal/schema/siteinfo_schema.go
@@ -52,7 +52,7 @@ func (r *SiteGeneralReq) FormatSiteUrl() {
 	}
 	r.SiteUrl = fmt.Sprintf("%s://%s", parsedUrl.Scheme, parsedUrl.Host)
 	if len(parsedUrl.Path) > 0 {
-		r.SiteUrl = r.SiteUrl + parsedUrl.Path
+		r.SiteUrl += parsedUrl.Path
 		r.SiteUrl = strings.TrimSuffix(r.SiteUrl, "/")
 	}
 }
diff --git a/internal/schema/tag_schema.go b/internal/schema/tag_schema.go
index a51b2d2d..8eb3212c 100644
--- a/internal/schema/tag_schema.go
+++ b/internal/schema/tag_schema.go
@@ -109,7 +109,7 @@ type GetTagPageResp struct {
 	DisplayName string `json:"display_name"`
 	// excerpt
 	Excerpt string `json:"excerpt"`
-	//description
+	// description
 	Description string `json:"description"`
 	// original text
 	OriginalText string `json:"original_text"`
diff --git a/internal/service/action/captcha_strategy.go b/internal/service/action/captcha_strategy.go
index b423b583..edda7325 100644
--- a/internal/service/action/captcha_strategy.go
+++ b/internal/service/action/captcha_strategy.go
@@ -67,9 +67,8 @@ func (cs *CaptchaService) ValidationStrategy(ctx context.Context, unit, actionTy
 		return cs.CaptchaActionDelete(ctx, unit, info)
 	case entity.CaptchaActionVote:
 		return cs.CaptchaActionVote(ctx, unit, info)
-
 	}
-	//actionType not found
+	// actionType not found
 	return false
 }
 
@@ -83,7 +82,7 @@ func (cs *CaptchaService) CaptchaActionPassword(ctx context.Context, unit string
 		return true
 	}
 	setNum := 3
-	setTime := int64(60 * 30) //seconds
+	setTime := int64(60 * 30) // seconds
 	now := time.Now().Unix()
 	if now-actionInfo.LastTime <= setTime && actionInfo.Num >= setNum {
 		return false
@@ -101,7 +100,7 @@ func (cs *CaptchaService) CaptchaActionEditUserinfo(ctx context.Context, unit st
 		return true
 	}
 	setNum := 3
-	setTime := int64(60 * 30) //seconds
+	setTime := int64(60 * 30) // seconds
 	now := time.Now().Unix()
 	if now-actionInfo.LastTime <= setTime && actionInfo.Num >= setNum {
 		return false
@@ -119,7 +118,7 @@ func (cs *CaptchaService) CaptchaActionQuestion(ctx context.Context, unit string
 		return true
 	}
 	setNum := 10
-	setTime := int64(5) //seconds
+	setTime := int64(5) // seconds
 	now := time.Now().Unix()
 	if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum {
 		return false
@@ -132,7 +131,7 @@ func (cs *CaptchaService) CaptchaActionAnswer(ctx context.Context, unit string,
 		return true
 	}
 	setNum := 10
-	setTime := int64(5) //seconds
+	setTime := int64(5) // seconds
 	now := time.Now().Unix()
 	if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum {
 		return false
@@ -145,7 +144,7 @@ func (cs *CaptchaService) CaptchaActionComment(ctx context.Context, unit string,
 		return true
 	}
 	setNum := 30
-	setTime := int64(1) //seconds
+	setTime := int64(1) // seconds
 	now := time.Now().Unix()
 	if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum {
 		return false
@@ -175,8 +174,8 @@ func (cs *CaptchaService) CaptchaActionSearch(ctx context.Context, unit string,
 	}
 	now := time.Now().Unix()
 	setNum := 20
-	setTime := int64(60) //seconds
-	if now-int64(actionInfo.LastTime) <= setTime && actionInfo.Num >= setNum {
+	setTime := int64(60) // seconds
+	if now-actionInfo.LastTime <= setTime && actionInfo.Num >= setNum {
 		return false
 	}
 	if now-actionInfo.LastTime > setTime {
@@ -192,7 +191,7 @@ func (cs *CaptchaService) CaptchaActionReport(ctx context.Context, unit string,
 		return true
 	}
 	setNum := 30
-	setTime := int64(1) //seconds
+	setTime := int64(1) // seconds
 	now := time.Now().Unix()
 	if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum {
 		return false
@@ -205,7 +204,7 @@ func (cs *CaptchaService) CaptchaActionDelete(ctx context.Context, unit string,
 		return true
 	}
 	setNum := 5
-	setTime := int64(5) //seconds
+	setTime := int64(5) // seconds
 	now := time.Now().Unix()
 	if now-actionInfo.LastTime <= setTime || actionInfo.Num >= setNum {
 		return false
diff --git a/internal/service/auth/auth.go b/internal/service/auth/auth.go
index 9ee5f3ee..b94f7912 100644
--- a/internal/service/auth/auth.go
+++ b/internal/service/auth/auth.go
@@ -138,7 +138,7 @@ func (as *AuthService) RemoveTokensExceptCurrentUser(ctx context.Context, userID
 	as.authRepo.RemoveUserTokens(ctx, userID, accessToken)
 }
 
-//Admin
+// Admin
 
 func (as *AuthService) GetAdminUserCacheInfo(ctx context.Context, accessToken string) (userInfo *entity.UserCacheInfo, err error) {
 	return as.authRepo.GetAdminUserCacheInfo(ctx, accessToken)
diff --git a/internal/service/comment/comment_service.go b/internal/service/comment/comment_service.go
index 3a5b3e6c..dc599e6d 100644
--- a/internal/service/comment/comment_service.go
+++ b/internal/service/comment/comment_service.go
@@ -178,9 +178,8 @@ func (cs *CommentService) AddComment(ctx context.Context, req *schema.AddComment
 		time.Now(), req.CanEdit, req.CanDelete)
 
 	if comment.Status == entity.CommentStatusAvailable {
-		commentResp, err := cs.addCommentNotification(ctx, req, resp, comment, objInfo)
-		if err != nil {
-			return commentResp, err
+		if err := cs.addCommentNotification(ctx, req, resp, comment, objInfo); err != nil {
+			return nil, err
 		}
 	}
 
@@ -220,7 +219,7 @@ func (cs *CommentService) AddComment(ctx context.Context, req *schema.AddComment
 
 func (cs *CommentService) addCommentNotification(
 	ctx context.Context, req *schema.AddCommentReq, resp *schema.GetCommentResp,
-	comment *entity.Comment, objInfo *schema.SimpleObjectInfo) (*schema.GetCommentResp, error) {
+	comment *entity.Comment, objInfo *schema.SimpleObjectInfo) error {
 	// The priority of the notification
 	// 1. reply to user
 	// 2. comment mention to user
@@ -231,7 +230,7 @@ func (cs *CommentService) addCommentNotification(
 	if len(resp.ReplyUserID) > 0 && resp.ReplyUserID != req.UserID {
 		replyUser, exist, err := cs.userCommon.GetUserBasicInfoByID(ctx, resp.ReplyUserID)
 		if err != nil {
-			return nil, err
+			return err
 		}
 		if exist {
 			resp.ReplyUsername = replyUser.Username
@@ -241,7 +240,7 @@ func (cs *CommentService) addCommentNotification(
 		cs.notificationCommentReply(ctx, replyUser.ID, comment.ID, req.UserID,
 			objInfo.QuestionID, objInfo.Title, htmltext.FetchExcerpt(comment.ParsedText, "...", 240))
 		alreadyNotifiedUserID[replyUser.ID] = true
-		return nil, nil
+		return nil
 	}
 
 	if len(req.MentionUsernameList) > 0 {
@@ -250,7 +249,7 @@ func (cs *CommentService) addCommentNotification(
 		for _, userID := range alreadyNotifiedUserIDs {
 			alreadyNotifiedUserID[userID] = true
 		}
-		return nil, nil
+		return nil
 	}
 
 	if objInfo.ObjectType == constant.QuestionObjectType && !alreadyNotifiedUserID[objInfo.ObjectCreatorUserID] {
@@ -260,7 +259,7 @@ func (cs *CommentService) addCommentNotification(
 		cs.notificationAnswerComment(ctx, objInfo.QuestionID, objInfo.Title, objInfo.AnswerID,
 			objInfo.ObjectCreatorUserID, comment.ID, req.UserID, htmltext.FetchExcerpt(comment.ParsedText, "...", 240))
 	}
-	return nil, nil
+	return nil
 }
 
 // RemoveComment delete comment
diff --git a/internal/service/content/answer_service.go b/internal/service/content/answer_service.go
index 982bbf88..f904b82f 100644
--- a/internal/service/content/answer_service.go
+++ b/internal/service/content/answer_service.go
@@ -146,7 +146,6 @@ func (as *AnswerService) RemoveAnswer(ctx context.Context, req *schema.RemoveAns
 		if !exist {
 			return errors.BadRequest(reason.AnswerCannotDeleted)
 		}
-
 	}
 
 	err = as.answerRepo.RemoveAnswer(ctx, req.ID)
@@ -180,10 +179,10 @@ func (as *AnswerService) RemoveAnswer(ctx context.Context, req *schema.RemoveAns
 
 	// #2372 In order to simplify the process and complexity, as well as to consider if it is in-house,
 	// facing the problem of recovery.
-	//err = as.answerActivityService.DeleteAnswer(ctx, answerInfo.ID, answerInfo.CreatedAt, answerInfo.VoteCount)
-	//if err != nil {
-	//	log.Errorf("delete answer activity change failed: %s", err.Error())
-	//}
+	// err = as.answerActivityService.DeleteAnswer(ctx, answerInfo.ID, answerInfo.CreatedAt, answerInfo.VoteCount)
+	// if err != nil {
+	// 	log.Errorf("delete answer activity change failed: %s", err.Error())
+	// }
 	as.activityQueueService.Send(ctx, &schema.ActivityMsg{
 		UserID:           req.UserID,
 		TriggerUserID:    converter.StringToInt64(req.UserID),
@@ -264,7 +263,7 @@ func (as *AnswerService) Insert(ctx context.Context, req *schema.AnswerAddReq) (
 	insertData.RevisionID = "0"
 	insertData.LastEditUserID = "0"
 	insertData.Status = entity.AnswerStatusPending
-	//insertData.UpdatedAt = now
+	// insertData.UpdatedAt = now
 	if err = as.answerRepo.AddAnswer(ctx, insertData); err != nil {
 		return "", err
 	}
@@ -365,7 +364,7 @@ func (as *AnswerService) Update(ctx context.Context, req *schema.AnswerUpdateReq
 		return "", errors.BadRequest(reason.QuestionNotFound)
 	}
 
-	//If the content is the same, ignore it
+	// If the content is the same, ignore it
 	if answerInfo.OriginalText == req.Content {
 		return "", nil
 	}
diff --git a/internal/service/content/question_service.go b/internal/service/content/question_service.go
index da15fae5..b8372a72 100644
--- a/internal/service/content/question_service.go
+++ b/internal/service/content/question_service.go
@@ -216,9 +216,9 @@ func (qs *QuestionService) ReopenQuestion(ctx context.Context, req *schema.Reope
 	return nil
 }
 
-func (qs *QuestionService) AddQuestionCheckTags(ctx context.Context, Tags []*entity.Tag) ([]string, error) {
+func (qs *QuestionService) AddQuestionCheckTags(ctx context.Context, tags []*entity.Tag) ([]string, error) {
 	list := make([]string, 0)
-	for _, tag := range Tags {
+	for _, tag := range tags {
 		if tag.Reserved {
 			list = append(list, tag.DisplayName)
 		}
@@ -374,14 +374,14 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question
 	question.AcceptedAnswerID = "0"
 	question.LastAnswerID = "0"
 	question.LastEditUserID = "0"
-	//question.PostUpdateTime = nil
+	// question.PostUpdateTime = nil
 	question.Status = entity.QuestionStatusPending
 	question.RevisionID = "0"
 	question.CreatedAt = now
 	question.PostUpdateTime = now
 	question.Pin = entity.QuestionUnPin
 	question.Show = entity.QuestionShow
-	//question.UpdatedAt = nil
+	// question.UpdatedAt = nil
 	err = qs.questionRepo.AddQuestion(ctx, question)
 	if err != nil {
 		return
@@ -416,10 +416,7 @@ func (qs *QuestionService) AddQuestion(ctx context.Context, req *schema.Question
 		Title:    question.Title,
 	}
 
-	questionWithTagsRevision, err := qs.changeQuestionToRevision(ctx, question, tags)
-	if err != nil {
-		return nil, err
-	}
+	questionWithTagsRevision := qs.changeQuestionToRevision(ctx, question, tags)
 	infoJSON, _ := json.Marshal(questionWithTagsRevision)
 	revisionDTO.Content = string(infoJSON)
 	revisionID, err := qs.revisionService.AddRevision(ctx, revisionDTO, true)
@@ -554,7 +551,7 @@ func (qs *QuestionService) RemoveQuestion(ctx context.Context, req *schema.Remov
 	if err != nil {
 		return err
 	}
-	//if the status is deleted, return directly
+	// if the status is deleted, return directly
 	if questionInfo.Status == entity.QuestionStatusDeleted {
 		return nil
 	}
@@ -613,7 +610,7 @@ func (qs *QuestionService) RemoveQuestion(ctx context.Context, req *schema.Remov
 		}
 	}
 
-	//tag count
+	// tag count
 	tagIDs := make([]string, 0)
 	Tags, tagerr := qs.tagCommon.GetObjectEntityTag(ctx, req.ID)
 	if tagerr != nil {
@@ -684,7 +681,7 @@ func (qs *QuestionService) UpdateQuestionCheckTags(ctx context.Context, req *sch
 
 	isChange := qs.tagCommon.CheckTagsIsChange(ctx, tagNameList, oldtagNameList)
 
-	//If the content is the same, ignore it
+	// If the content is the same, ignore it
 	if dbinfo.Title == req.Title && dbinfo.OriginalText == req.Content && !isChange {
 		return
 	}
@@ -798,7 +795,7 @@ func (qs *QuestionService) UpdateQuestionInviteUser(ctx context.Context, req *sc
 		return errors.BadRequest(reason.QuestionNotFound)
 	}
 
-	//verify invite user
+	// verify invite user
 	inviteUserInfoList, err := qs.userCommon.BatchGetUserBasicInfoByUserNames(ctx, req.InviteUser)
 	if err != nil {
 		log.Error("BatchGetUserBasicInfoByUserNames error", err.Error())
@@ -826,7 +823,7 @@ func (qs *QuestionService) UpdateQuestionInviteUser(ctx context.Context, req *sc
 	if saveerr != nil {
 		return saveerr
 	}
-	//send notification
+	// send notification
 	oldInviteUserIDsStr := originQuestion.InviteUserID
 	oldInviteUserIDs := make([]string, 0)
 	needSendNotificationUserIDs := make([]string, 0)
@@ -964,7 +961,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest
 
 	isChange := qs.tagCommon.CheckTagsIsChange(ctx, tagNameList, oldtagNameList)
 
-	//If the content is the same, ignore it
+	// If the content is the same, ignore it
 	if dbinfo.Title == req.Title && dbinfo.OriginalText == req.Content && !isChange {
 		return
 	}
@@ -1015,7 +1012,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest
 		return errorlist, err
 	}
 
-	//Administrators and themselves do not need to be audited
+	// Administrators and themselves do not need to be audited
 
 	revisionDTO := &schema.AddRevisionDTO{
 		UserID:   question.UserID,
@@ -1031,11 +1028,11 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest
 	// It's not you or the administrator that needs to be reviewed
 	if !canUpdate {
 		revisionDTO.Status = entity.RevisionUnreviewedStatus
-		revisionDTO.UserID = req.UserID //use revision userid
+		revisionDTO.UserID = req.UserID // use revision userid
 	} else {
-		//Direct modification
+		// Direct modification
 		revisionDTO.Status = entity.RevisionReviewPassStatus
-		//update question to db
+		// update question to db
 		question.ParsedText, err = qs.questioncommon.UpdateQuestionLink(ctx, question.ID, "", question.ParsedText, question.OriginalText)
 		if err != nil {
 			return questionInfo, err
@@ -1054,10 +1051,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest
 		}
 	}
 
-	questionWithTagsRevision, err := qs.changeQuestionToRevision(ctx, question, Tags)
-	if err != nil {
-		return nil, err
-	}
+	questionWithTagsRevision := qs.changeQuestionToRevision(ctx, question, Tags)
 	infoJSON, _ := json.Marshal(questionWithTagsRevision)
 	revisionDTO.Content = string(infoJSON)
 	revisionID, err := qs.revisionService.AddRevision(ctx, revisionDTO, true)
@@ -1165,7 +1159,6 @@ func (qs *QuestionService) CheckChangeReservedTag(ctx context.Context, oldobject
 // PersonalQuestionPage get question list by user
 func (qs *QuestionService) PersonalQuestionPage(ctx context.Context, req *schema.PersonalQuestionPageReq) (
 	pageModel *pager.PageModel, err error) {
-
 	userinfo, exist, err := qs.userCommon.GetUserBasicInfoByUserName(ctx, req.Username)
 	if err != nil {
 		return nil, err
@@ -1250,7 +1243,6 @@ func (qs *QuestionService) PersonalAnswerPage(ctx context.Context, req *schema.P
 		info.QuestionID = item.QuestionID
 		if item.QuestionInfo.Status == entity.QuestionStatusDeleted {
 			info.QuestionInfo.Title = "Deleted question"
-
 		}
 		userAnswerlist = append(userAnswerlist, info)
 	}
@@ -1489,7 +1481,8 @@ func (qs *QuestionService) GetQuestionPage(ctx context.Context, req *schema.Ques
 			if err != nil {
 				return nil, 0, err
 			}
-			tagIDs = append(synTagIds, tagInfo.ID)
+			tagIDs = append(tagIDs, synTagIds...)
+			tagIDs = append(tagIDs, tagInfo.ID)
 		} else {
 			return questions, 0, nil
 		}
@@ -1585,10 +1578,10 @@ func (qs *QuestionService) AdminSetQuestionStatus(ctx context.Context, req *sche
 	if setStatus == entity.QuestionStatusDeleted {
 		// #2372 In order to simplify the process and complexity, as well as to consider if it is in-house,
 		// facing the problem of recovery.
-		//err = qs.answerActivityService.DeleteQuestion(ctx, questionInfo.ID, questionInfo.CreatedAt, questionInfo.VoteCount)
-		//if err != nil {
-		//	log.Errorf("admin delete question then rank rollback error %s", err.Error())
-		//}
+		// err = qs.answerActivityService.DeleteQuestion(ctx, questionInfo.ID, questionInfo.CreatedAt, questionInfo.VoteCount)
+		// if err != nil {
+		// 	log.Errorf("admin delete question then rank rollback error %s", err.Error())
+		// }
 		qs.activityQueueService.Send(ctx, &schema.ActivityMsg{
 			UserID:           questionInfo.UserID,
 			TriggerUserID:    converter.StringToInt64(req.UserID),
@@ -1642,7 +1635,6 @@ func (qs *QuestionService) AdminSetQuestionStatus(ctx context.Context, req *sche
 func (qs *QuestionService) AdminQuestionPage(
 	ctx context.Context, req *schema.AdminQuestionPageReq) (
 	resp *pager.PageModel, err error) {
-
 	list := make([]*schema.AdminQuestionInfo, 0)
 	questionList, count, err := qs.questionRepo.AdminQuestionPage(ctx, req)
 	if err != nil {
@@ -1708,8 +1700,8 @@ func (qs *QuestionService) AdminAnswerPage(ctx context.Context, req *schema.Admi
 	return pager.NewPageModel(count, answerResp), nil
 }
 
-func (qs *QuestionService) changeQuestionToRevision(ctx context.Context, questionInfo *entity.Question, tags []*entity.Tag) (
-	questionRevision *entity.QuestionWithTagsRevision, err error) {
+func (qs *QuestionService) changeQuestionToRevision(_ context.Context, questionInfo *entity.Question, tags []*entity.Tag) (
+	questionRevision *entity.QuestionWithTagsRevision) {
 	questionRevision = &entity.QuestionWithTagsRevision{}
 	questionRevision.Question = *questionInfo
 
@@ -1718,7 +1710,7 @@ func (qs *QuestionService) changeQuestionToRevision(ctx context.Context, questio
 		_ = copier.Copy(item, tag)
 		questionRevision.Tags = append(questionRevision.Tags, item)
 	}
-	return questionRevision, nil
+	return questionRevision
 }
 
 func (qs *QuestionService) SitemapCron(ctx context.Context) {
diff --git a/internal/service/content/revision_service.go b/internal/service/content/revision_service.go
index a5cefeb4..4ac08e76 100644
--- a/internal/service/content/revision_service.go
+++ b/internal/service/content/revision_service.go
@@ -235,7 +235,6 @@ func (rs *RevisionService) revisionAuditQuestion(ctx context.Context, revisionit
 func (rs *RevisionService) revisionAuditAnswer(ctx context.Context, revisionitem *schema.GetRevisionResp) (err error) {
 	answerinfo, ok := revisionitem.ContentParsed.(*schema.AnswerInfo)
 	if ok {
-
 		var PostUpdateTime time.Time
 		dbquestion, exist, dberr := rs.questionRepo.GetQuestion(ctx, answerinfo.QuestionID)
 		if dberr != nil || !exist {
diff --git a/internal/service/content/search_service.go b/internal/service/content/search_service.go
index ccafcd82..866f1c6e 100644
--- a/internal/service/content/search_service.go
+++ b/internal/service/content/search_service.go
@@ -68,13 +68,14 @@ func (ss *SearchService) Search(ctx context.Context, dto *schema.SearchDTO) (res
 	resp = &schema.SearchResp{}
 	// search plugin is not found, call system search
 	if finder == nil {
-		if cond.SearchAll() {
+		switch {
+		case cond.SearchAll():
 			resp.SearchResults, resp.Total, err =
 				ss.searchRepo.SearchContents(ctx, cond.Words, cond.Tags, cond.UserID, cond.VoteAmount, dto.Page, dto.Size, dto.Order)
-		} else if cond.SearchQuestion() {
+		case cond.SearchQuestion():
 			resp.SearchResults, resp.Total, err =
 				ss.searchRepo.SearchQuestions(ctx, cond.Words, cond.Tags, cond.NotAccepted, cond.Views, cond.AnswerAmount, dto.Page, dto.Size, dto.Order)
-		} else if cond.SearchAnswer() {
+		case cond.SearchAnswer():
 			resp.SearchResults, resp.Total, err =
 				ss.searchRepo.SearchAnswers(ctx, cond.Words, cond.Tags, cond.Accepted, cond.QuestionID, dto.Page, dto.Size, dto.Order)
 		}
@@ -86,11 +87,12 @@ func (ss *SearchService) Search(ctx context.Context, dto *schema.SearchDTO) (res
 func (ss *SearchService) searchByPlugin(ctx context.Context, finder plugin.Search, cond *schema.SearchCondition, dto *schema.SearchDTO) (resp *schema.SearchResp, err error) {
 	var res []plugin.SearchResult
 	resp = &schema.SearchResp{}
-	if cond.SearchAll() {
+	switch {
+	case cond.SearchAll():
 		res, resp.Total, err = finder.SearchContents(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order))
-	} else if cond.SearchQuestion() {
+	case cond.SearchQuestion():
 		res, resp.Total, err = finder.SearchQuestions(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order))
-	} else if cond.SearchAnswer() {
+	case cond.SearchAnswer():
 		res, resp.Total, err = finder.SearchAnswers(ctx, cond.Convert2PluginSearchCond(dto.Page, dto.Size, dto.Order))
 	}
 	if err != nil {
diff --git a/internal/service/content/user_service.go b/internal/service/content/user_service.go
index 81f7ac82..e9cc3578 100644
--- a/internal/service/content/user_service.go
+++ b/internal/service/content/user_service.go
@@ -314,7 +314,6 @@ func (us *UserService) UserModifyPassword(ctx context.Context, req *schema.UserM
 // UpdateInfo update user info
 func (us *UserService) UpdateInfo(ctx context.Context, req *schema.UpdateInfoRequest) (
 	errFields []*validator.FormErrorField, err error) {
-
 	if len(req.Username) > 0 {
 		if checker.IsInvalidUsername(req.Username) {
 			return append(errFields, &validator.FormErrorField{
@@ -598,7 +597,7 @@ func (us *UserService) UserVerifyEmail(ctx context.Context, req *schema.UserVeri
 
 // verifyPassword
 // Compare whether the password is correct
-func (us *UserService) verifyPassword(ctx context.Context, loginPass, userPass string) bool {
+func (us *UserService) verifyPassword(_ context.Context, loginPass, userPass string) bool {
 	if len(loginPass) == 0 && len(userPass) == 0 {
 		return true
 	}
@@ -608,8 +607,8 @@ func (us *UserService) verifyPassword(ctx context.Context, loginPass, userPass s
 
 // encryptPassword
 // The password does irreversible encryption.
-func (us *UserService) encryptPassword(ctx context.Context, Pass string) (string, error) {
-	hashPwd, err := bcrypt.GenerateFromPassword([]byte(Pass), bcrypt.DefaultCost)
+func (us *UserService) encryptPassword(_ context.Context, pass string) (string, error) {
+	hashPwd, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost)
 	// This encrypted string can be saved to the database and can be used as password matching verification
 	return string(hashPwd), err
 }
diff --git a/internal/service/dashboard/dashboard_service.go b/internal/service/dashboard/dashboard_service.go
index 91f0e338..8b08ba02 100644
--- a/internal/service/dashboard/dashboard_service.go
+++ b/internal/service/dashboard/dashboard_service.go
@@ -264,7 +264,7 @@ func (ds *dashboardService) voteCount(ctx context.Context) int64 {
 	return voteCount
 }
 
-func (ds *dashboardService) remoteVersion(ctx context.Context) string {
+func (ds *dashboardService) remoteVersion(_ context.Context) string {
 	req, _ := http.NewRequest("GET", "https://answer.apache.org/data/latest.json?from_version="+constant.Version, nil)
 	req.Header.Set("User-Agent", "Answer/"+constant.Version)
 	httpClient := &http.Client{}
@@ -359,11 +359,9 @@ func (ds *dashboardService) GetDatabaseSize() (dbSize string) {
 		res, err := ds.data.DB.QueryInterface(sql)
 		if err != nil {
 			log.Warnf("get db size failed: %s", err)
-		} else {
-			if len(res) > 0 && res[0]["db_size"] != nil {
-				dbSizeStr, _ := res[0]["db_size"].(string)
-				dbSize = dir.FormatFileSize(converter.StringToInt64(dbSizeStr))
-			}
+		} else if len(res) > 0 && res[0]["db_size"] != nil {
+			dbSizeStr, _ := res[0]["db_size"].(string)
+			dbSize = dir.FormatFileSize(converter.StringToInt64(dbSizeStr))
 		}
 	case schemas.POSTGRES:
 		sql := fmt.Sprintf("SELECT pg_database_size('%s') AS db_size",
@@ -371,11 +369,9 @@ func (ds *dashboardService) GetDatabaseSize() (dbSize string) {
 		res, err := ds.data.DB.QueryInterface(sql)
 		if err != nil {
 			log.Warnf("get db size failed: %s", err)
-		} else {
-			if len(res) > 0 && res[0]["db_size"] != nil {
-				dbSizeStr, _ := res[0]["db_size"].(int32)
-				dbSize = dir.FormatFileSize(int64(dbSizeStr))
-			}
+		} else if len(res) > 0 && res[0]["db_size"] != nil {
+			dbSizeStr, _ := res[0]["db_size"].(int32)
+			dbSize = dir.FormatFileSize(int64(dbSizeStr))
 		}
 	case schemas.SQLITE:
 		dirSize, err := dir.DirSize(ds.data.DB.DataSourceName())
diff --git a/internal/service/notification/invite_answer_notification.go b/internal/service/notification/invite_answer_notification.go
index f68feb06..6b0407f9 100644
--- a/internal/service/notification/invite_answer_notification.go
+++ b/internal/service/notification/invite_answer_notification.go
@@ -45,8 +45,7 @@ func (ns *ExternalNotificationService) handleInviteAnswerNotification(ctx contex
 		if !channel.Enable {
 			continue
 		}
-		switch channel.Key {
-		case constant.EmailChannel:
+		if channel.Key == constant.EmailChannel {
 			ns.sendInviteAnswerNotificationEmail(ctx, msg.ReceiverUserID, msg.ReceiverEmail, msg.ReceiverLang, msg.NewInviteAnswerTemplateRawData)
 		}
 	}
diff --git a/internal/service/notification/new_answer_notification.go b/internal/service/notification/new_answer_notification.go
index c54fd961..4ae9ca9e 100644
--- a/internal/service/notification/new_answer_notification.go
+++ b/internal/service/notification/new_answer_notification.go
@@ -45,8 +45,7 @@ func (ns *ExternalNotificationService) handleNewAnswerNotification(ctx context.C
 		if !channel.Enable {
 			continue
 		}
-		switch channel.Key {
-		case constant.EmailChannel:
+		if channel.Key == constant.EmailChannel {
 			ns.sendNewAnswerNotificationEmail(ctx, msg.ReceiverUserID, msg.ReceiverEmail, msg.ReceiverLang, msg.NewAnswerTemplateRawData)
 		}
 	}
diff --git a/internal/service/notification/new_comment_notification.go b/internal/service/notification/new_comment_notification.go
index e622ed4f..9734e54e 100644
--- a/internal/service/notification/new_comment_notification.go
+++ b/internal/service/notification/new_comment_notification.go
@@ -45,8 +45,7 @@ func (ns *ExternalNotificationService) handleNewCommentNotification(ctx context.
 		if !channel.Enable {
 			continue
 		}
-		switch channel.Key {
-		case constant.EmailChannel:
+		if channel.Key == constant.EmailChannel {
 			ns.sendNewCommentNotificationEmail(ctx, msg.ReceiverUserID, msg.ReceiverEmail, msg.ReceiverLang, msg.NewCommentTemplateRawData)
 		}
 	}
diff --git a/internal/service/notification/new_question_notification.go b/internal/service/notification/new_question_notification.go
index debfb8c2..2f83042b 100644
--- a/internal/service/notification/new_question_notification.go
+++ b/internal/service/notification/new_question_notification.go
@@ -55,8 +55,7 @@ func (ns *ExternalNotificationService) handleNewQuestionNotification(ctx context
 			if !channel.Enable {
 				continue
 			}
-			switch channel.Key {
-			case constant.EmailChannel:
+			if channel.Key == constant.EmailChannel {
 				ns.sendNewQuestionNotificationEmail(ctx, subscriber.UserID, &schema.NewQuestionTemplateRawData{
 					QuestionTitle:   msg.NewQuestionTemplateRawData.QuestionTitle,
 					QuestionID:      msg.NewQuestionTemplateRawData.QuestionID,
diff --git a/internal/service/notification/notification_service.go b/internal/service/notification/notification_service.go
index 0369d455..6a69cbae 100644
--- a/internal/service/notification/notification_service.go
+++ b/internal/service/notification/notification_service.go
@@ -226,15 +226,12 @@ func (ns *NotificationService) GetNotificationPage(ctx context.Context, searchCo
 	if err != nil {
 		return nil, err
 	}
-	resp, err = ns.formatNotificationPage(ctx, notifications)
-	if err != nil {
-		return nil, err
-	}
+	resp = ns.formatNotificationPage(ctx, notifications)
 	return pager.NewPageModel(total, resp), nil
 }
 
 func (ns *NotificationService) formatNotificationPage(ctx context.Context, notifications []*entity.Notification) (
-	resp []*schema.NotificationContent, err error) {
+	resp []*schema.NotificationContent) {
 	lang := handler.GetLangByCtx(ctx)
 	enableShortID := handler.GetEnableShortID(ctx)
 	userIDs := make([]string, 0)
@@ -287,13 +284,13 @@ func (ns *NotificationService) formatNotificationPage(ctx context.Context, notif
 	}
 
 	if len(userIDs) == 0 {
-		return resp, nil
+		return resp
 	}
 
 	users, err := ns.userRepo.BatchGetByID(ctx, userIDs)
 	if err != nil {
 		log.Error(err)
-		return resp, nil
+		return resp
 	}
 	userIDMapping := make(map[string]*entity.User, len(users))
 	for _, user := range users {
@@ -314,5 +311,5 @@ func (ns *NotificationService) formatNotificationPage(ctx context.Context, notif
 			}
 		}
 	}
-	return resp, nil
+	return resp
 }
diff --git a/internal/service/notification_common/notification.go b/internal/service/notification_common/notification.go
index 55d63842..0bbd1865 100644
--- a/internal/service/notification_common/notification.go
+++ b/internal/service/notification_common/notification.go
@@ -155,7 +155,7 @@ func (ns *NotificationCommon) AddNotification(ctx context.Context, msg *schema.N
 		}
 		req.Rank = rank
 		if exist {
-			//modify notification
+			// modify notification
 			updateContent := &schema.NotificationContent{}
 			err := json.Unmarshal([]byte(notificationInfo.Content), updateContent)
 			if err != nil {
diff --git a/internal/service/plugin_common/plugin_common_service.go b/internal/service/plugin_common/plugin_common_service.go
index d3aa839b..7d39a5aa 100644
--- a/internal/service/plugin_common/plugin_common_service.go
+++ b/internal/service/plugin_common/plugin_common_service.go
@@ -69,7 +69,6 @@ func NewPluginCommonService(
 	data *data.Data,
 	importerService *importer.ImporterService,
 ) *PluginCommonService {
-
 	p := &PluginCommonService{
 		configService:        configService,
 		pluginConfigRepo:     pluginConfigRepo,
diff --git a/internal/service/question_common/question.go b/internal/service/question_common/question.go
index 33380644..846dea89 100644
--- a/internal/service/question_common/question.go
+++ b/internal/service/question_common/question.go
@@ -179,17 +179,17 @@ func (qs *QuestionCommon) UpdateCollectionCount(ctx context.Context, questionID
 	return qs.questionRepo.UpdateCollectionCount(ctx, questionID)
 }
 
-func (qs *QuestionCommon) UpdateAccepted(ctx context.Context, questionID, AnswerID string) error {
+func (qs *QuestionCommon) UpdateAccepted(ctx context.Context, questionID, answerID string) error {
 	question := &entity.Question{}
 	question.ID = questionID
-	question.AcceptedAnswerID = AnswerID
+	question.AcceptedAnswerID = answerID
 	return qs.questionRepo.UpdateAccepted(ctx, question)
 }
 
-func (qs *QuestionCommon) UpdateLastAnswer(ctx context.Context, questionID, AnswerID string) error {
+func (qs *QuestionCommon) UpdateLastAnswer(ctx context.Context, questionID, answerID string) error {
 	question := &entity.Question{}
 	question.ID = questionID
-	question.LastAnswerID = AnswerID
+	question.LastAnswerID = answerID
 	return qs.questionRepo.UpdateLastAnswer(ctx, question)
 }
 
@@ -232,7 +232,7 @@ func (qs *QuestionCommon) InviteUserInfo(ctx context.Context, questionID string)
 	if !has {
 		return InviteUserInfo, errors.NotFound(reason.QuestionNotFound)
 	}
-	//InviteUser
+	// InviteUser
 	if dbinfo.InviteUserID != "" {
 		InviteUserIDs := make([]string, 0)
 		err := json.Unmarshal([]byte(dbinfo.InviteUserID), &InviteUserIDs)
@@ -681,7 +681,6 @@ func (qs *QuestionCommon) ShowFormat(ctx context.Context, data *entity.Question)
 				info.LastAnsweredUserID = answerInfo.UserID
 			}
 		}
-
 	}
 	info.Tags = make([]*schema.TagResp, 0)
 	return &info
diff --git a/internal/service/tag/tag_service.go b/internal/service/tag/tag_service.go
index 577199ec..e61bfa06 100644
--- a/internal/service/tag/tag_service.go
+++ b/internal/service/tag/tag_service.go
@@ -74,7 +74,7 @@ func NewTagService(
 
 // RemoveTag delete tag
 func (ts *TagService) RemoveTag(ctx context.Context, req *schema.RemoveTagReq) (err error) {
-	//If the tag has associated problems, it cannot be deleted
+	// If the tag has associated problems, it cannot be deleted
 	tagCount, err := ts.tagCommonService.CountTagRelByTagID(ctx, req.TagID)
 	if err != nil {
 		return err
@@ -83,7 +83,7 @@ func (ts *TagService) RemoveTag(ctx context.Context, req *schema.RemoveTagReq) (
 		return errors.BadRequest(reason.TagIsUsedCannotDelete)
 	}
 
-	//If the tag has associated problems, it cannot be deleted
+	// If the tag has associated problems, it cannot be deleted
 	tagSynonymCount, err := ts.tagRepo.GetTagSynonymCount(ctx, req.TagID)
 	if err != nil {
 		return err
diff --git a/internal/service/tag_common/tag_common.go b/internal/service/tag_common/tag_common.go
index fed5dfbf..87c10bcc 100644
--- a/internal/service/tag_common/tag_common.go
+++ b/internal/service/tag_common/tag_common.go
@@ -591,7 +591,6 @@ func (ts *TagCommonService) CheckTag(ctx context.Context, tags []string, userID
 		err = errors.BadRequest(reason.TagNotFound).WithMsg(fmt.Sprintf("tag [%s] does not exist",
 			strings.Join(addTagMsgList, ",")))
 		return err
-
 	}
 
 	return nil
@@ -660,9 +659,8 @@ func (ts *TagCommonService) CheckChangeReservedTag(ctx context.Context, oldobjec
 
 // ObjectChangeTag change object tag list
 func (ts *TagCommonService) ObjectChangeTag(ctx context.Context, objectTagData *schema.TagChange, minimumTags int) (errorlist []*validator.FormErrorField, err error) {
-	//checks if the tags sent in the put req are less than the minimum, if so, tag changes are not applied
+	// checks if the tags sent in the put req are less than the minimum, if so, tag changes are not applied
 	if len(objectTagData.Tags) < minimumTags {
-
 		errorlist := make([]*validator.FormErrorField, 0)
 		errorlist = append(errorlist, &validator.FormErrorField{
 			ErrorField: "tags",
@@ -884,11 +882,11 @@ func (ts *TagCommonService) UpdateTag(ctx context.Context, req *schema.UpdateTag
 		return errors.BadRequest(reason.TagNotFound)
 	}
 
-	//Adding equivalent slug formatting for tag update
+	// Adding equivalent slug formatting for tag update
 	slugName := strings.ReplaceAll(req.SlugName, " ", "-")
 	slugName = strings.ToLower(slugName)
 
-	//If the content is the same, ignore it
+	// If the content is the same, ignore it
 	if tagInfo.OriginalText == req.OriginalText &&
 		tagInfo.DisplayName == req.DisplayName &&
 		tagInfo.SlugName == slugName {
diff --git a/internal/service/uploader/upload.go b/internal/service/uploader/upload.go
index 30029193..8dea746c 100644
--- a/internal/service/uploader/upload.go
+++ b/internal/service/uploader/upload.go
@@ -135,7 +135,6 @@ func (us *uploaderService) UploadAvatarFile(ctx *gin.Context, userID string) (ur
 	}
 	us.fileRecordService.AddFileRecord(ctx, userID, avatarFilePath, url, string(plugin.UserAvatar))
 	return url, nil
-
 }
 
 func (us *uploaderService) AvatarThumbFile(ctx *gin.Context, fileName string, size int) (url string, err error) {
@@ -304,7 +303,6 @@ func (us *uploaderService) UploadBrandingFile(ctx *gin.Context, userID string) (
 	}
 	us.fileRecordService.AddFileRecord(ctx, userID, avatarFilePath, url, string(plugin.AdminBranding))
 	return url, nil
-
 }
 
 func (us *uploaderService) uploadImageFile(ctx *gin.Context, file *multipart.FileHeader, fileSubPath string) (
diff --git a/internal/service/user_admin/user_backyard.go b/internal/service/user_admin/user_backyard.go
index 6fce161c..fcced1c8 100644
--- a/internal/service/user_admin/user_backyard.go
+++ b/internal/service/user_admin/user_backyard.go
@@ -470,14 +470,15 @@ func (us *UserAdminService) GetUserPage(ctx context.Context, req *schema.GetUser
 	user := &entity.User{}
 	_ = copier.Copy(user, req)
 
-	if req.IsInactive() {
+	switch {
+	case req.IsInactive():
 		user.MailStatus = entity.EmailStatusToBeVerified
 		user.Status = entity.UserStatusAvailable
-	} else if req.IsSuspended() {
+	case req.IsSuspended():
 		user.Status = entity.UserStatusSuspended
-	} else if req.IsDeleted() {
+	case req.IsDeleted():
 		user.Status = entity.UserStatusDeleted
-	} else {
+	default:
 		user.MailStatus = entity.EmailStatusAvailable
 		user.Status = entity.UserStatusAvailable
 	}
@@ -486,8 +487,8 @@ func (us *UserAdminService) GetUserPage(ctx context.Context, req *schema.GetUser
 		if email, e := mail.ParseAddress(req.Query); e == nil {
 			user.EMail = email.Address
 			req.Query = ""
-		} else if strings.HasPrefix(req.Query, "user:") {
-			id := strings.TrimSpace(strings.TrimPrefix(req.Query, "user:"))
+		} else if after, ok := strings.CutPrefix(req.Query, "user:"); ok {
+			id := strings.TrimSpace(after)
 			idSearch := true
 			for _, r := range id {
 				if !unicode.IsDigit(r) {
@@ -521,18 +522,19 @@ func (us *UserAdminService) GetUserPage(ctx context.Context, req *schema.GetUser
 			DisplayName: u.DisplayName,
 			Avatar:      avatarMapping[u.ID].GetURL(),
 		}
-		if u.Status == entity.UserStatusDeleted {
+		switch {
+		case u.Status == entity.UserStatusDeleted:
 			t.Status = constant.UserDeleted
 			t.DeletedAt = u.DeletedAt.Unix()
-		} else if u.Status == entity.UserStatusSuspended {
+		case u.Status == entity.UserStatusSuspended:
 			t.Status = constant.UserSuspended
 			t.SuspendedAt = u.SuspendedAt.Unix()
 			if !u.SuspendedUntil.IsZero() {
 				t.SuspendedUntil = u.SuspendedUntil.Unix()
 			}
-		} else if u.MailStatus == entity.EmailStatusToBeVerified {
+		case u.MailStatus == entity.EmailStatusToBeVerified:
 			t.Status = constant.UserInactive
-		} else {
+		default:
 			t.Status = constant.UserNormal
 		}
 		resp = append(resp, t)
@@ -646,7 +648,6 @@ func (us *UserAdminService) CheckAndUnsuspendExpiredUsers(ctx context.Context) e
 		if user.Status == entity.UserStatusSuspended &&
 			!user.SuspendedUntil.IsZero() &&
 			user.SuspendedUntil.Before(now) {
-
 			log.Infof("Unsuspending user %s (ID: %s) - suspension expired at %v",
 				user.Username, user.ID, user.SuspendedUntil)
 
diff --git a/internal/service/user_common/user.go b/internal/service/user_common/user.go
index 124972a1..2e777f14 100644
--- a/internal/service/user_common/user.go
+++ b/internal/service/user_common/user.go
@@ -85,9 +85,9 @@ func NewUserCommon(
 	}
 }
 
-func (us *UserCommon) GetUserBasicInfoByID(ctx context.Context, ID string) (
+func (us *UserCommon) GetUserBasicInfoByID(ctx context.Context, id string) (
 	userBasicInfo *schema.UserBasicInfo, exist bool, err error) {
-	userInfo, exist, err := us.userRepo.GetByUserID(ctx, ID)
+	userInfo, exist, err := us.userRepo.GetByUserID(ctx, id)
 	if err != nil {
 		return nil, exist, err
 	}
diff --git a/internal/service/user_notification_config/user_notification_config_service.go b/internal/service/user_notification_config/user_notification_config_service.go
index c40df55c..8ab72fa9 100644
--- a/internal/service/user_notification_config/user_notification_config_service.go
+++ b/internal/service/user_notification_config/user_notification_config_service.go
@@ -96,7 +96,7 @@ func (us *UserNotificationConfigService) SetDefaultUserNotificationConfig(ctx co
 		string(constant.InboxSource), `[{"key":"email","enable":true}]`)
 }
 
-func (us *UserNotificationConfigService) convertToEntity(ctx context.Context, userID string,
+func (us *UserNotificationConfigService) convertToEntity(_ context.Context, userID string,
 	source constant.NotificationSource, channel schema.NotificationChannelConfig) (c *entity.UserNotificationConfig) {
 	var channels schema.NotificationChannels
 	channels = append(channels, &channel)
diff --git a/pkg/checker/file_type.go b/pkg/checker/file_type.go
index ac1fbcaf..8eaabcbf 100644
--- a/pkg/checker/file_type.go
+++ b/pkg/checker/file_type.go
@@ -28,6 +28,7 @@ import (
 	"io"
 	"os"
 	"path/filepath"
+	"slices"
 	"strings"
 
 	"github.com/segmentfault/pacman/log"
@@ -38,12 +39,7 @@ import (
 // WANING Only checks the file extension is not reliable, but `http.DetectContentType` and `mimetype` are not reliable for all file types.
 func IsUnAuthorizedExtension(fileName string, allowedExtensions []string) bool {
 	ext := strings.ToLower(strings.Trim(filepath.Ext(fileName), "."))
-	for _, extension := range allowedExtensions {
-		if extension == ext {
-			return false
-		}
-	}
-	return true
+	return !slices.Contains(allowedExtensions, ext)
 }
 
 // DecodeAndCheckImageFile currently answers support image type is
diff --git a/pkg/checker/path_ignore.go b/pkg/checker/path_ignore.go
index 8be757be..24b092f7 100644
--- a/pkg/checker/path_ignore.go
+++ b/pkg/checker/path_ignore.go
@@ -20,6 +20,7 @@
 package checker
 
 import (
+	"slices"
 	"sync"
 
 	"github.com/apache/answer/configs"
@@ -46,21 +47,11 @@ func initPathIgnore() {
 // IsUsersIgnorePath checks whether the username is in ignore path
 func IsUsersIgnorePath(username string) bool {
 	ignorePathInit.Do(initPathIgnore)
-	for _, u := range pathIgnore.Users {
-		if u == username {
-			return true
-		}
-	}
-	return false
+	return slices.Contains(pathIgnore.Users, username)
 }
 
 // IsQuestionsIgnorePath checks whether the questionID is in ignore path
 func IsQuestionsIgnorePath(questionID string) bool {
 	ignorePathInit.Do(initPathIgnore)
-	for _, u := range pathIgnore.Questions {
-		if u == questionID {
-			return true
-		}
-	}
-	return false
+	return slices.Contains(pathIgnore.Questions, questionID)
 }
diff --git a/pkg/checker/question_link.go b/pkg/checker/question_link.go
index 41b246c3..efd19b3c 100644
--- a/pkg/checker/question_link.go
+++ b/pkg/checker/question_link.go
@@ -44,15 +44,16 @@ func GetQuestionLink(content string) []QuestionLink {
 	left, right := 0, 0
 	for right < len(content) {
 		// find "/questions/" or "#"
-		if right+11 < len(content) && content[right:right+11] == "/questions/" {
+		switch {
+		case right+11 < len(content) && content[right:right+11] == "/questions/":
 			left = right
 			right += 11
 			processURL(content, &left, &right, uniqueIDs, &questionLinks)
-		} else if content[right] == '#' {
+		case content[right] == '#':
 			left = right + 1
 			right = left
 			processID(content, &left, &right, uniqueIDs, &questionLinks)
-		} else {
+		default:
 			right++
 		}
 	}
@@ -101,9 +102,7 @@ func addUniqueID(questionID, answerID string, linkType int, uniqueIDs map[string
 		objectType, err := obj.GetObjectTypeStrByObjectID(uid.DeShortID(answerID))
 		if err != nil {
 			answerID = ""
-		}
-
-		if objectType == constant.AnswerObjectType {
+		} else if objectType == constant.AnswerObjectType {
 			if _, ok := uniqueIDs[answerID]; !ok {
 				uniqueIDs[answerID] = struct{}{}
 				isAdd = true
diff --git a/pkg/converter/markdown.go b/pkg/converter/markdown.go
index d16915a8..adae3faf 100644
--- a/pkg/converter/markdown.go
+++ b/pkg/converter/markdown.go
@@ -107,7 +107,7 @@ func (r *DangerousHTMLRenderer) renderRawHTML(w util.BufWriter, source []byte, n
 	}
 	n := node.(*ast.RawHTML)
 	l := n.Segments.Len()
-	for i := 0; i < l; i++ {
+	for i := range l {
 		segment := n.Segments.At(i)
 		if string(source[segment.Start:segment.Stop]) == "<kbd>" || string(source[segment.Start:segment.Stop]) == "</kbd>" {
 			_, _ = w.Write(segment.Value(source))
@@ -122,15 +122,13 @@ func (r *DangerousHTMLRenderer) renderHTMLBlock(w util.BufWriter, source []byte,
 	n := node.(*ast.HTMLBlock)
 	if entering {
 		l := n.Lines().Len()
-		for i := 0; i < l; i++ {
+		for i := range l {
 			line := n.Lines().At(i)
 			r.Writer.SecureWrite(w, line.Value(source))
 		}
-	} else {
-		if n.HasClosure() {
-			closure := n.ClosureLine
-			r.Writer.SecureWrite(w, closure.Value(source))
-		}
+	} else if n.HasClosure() {
+		closure := n.ClosureLine
+		r.Writer.SecureWrite(w, closure.Value(source))
 	}
 	return ast.WalkContinue, nil
 }
@@ -184,8 +182,8 @@ func (r *DangerousHTMLRenderer) renderAutoLink(w util.BufWriter, source []byte,
 	return ast.WalkContinue, nil
 }
 
-func (r *DangerousHTMLRenderer) renderLinkIsUrl(verifyUrl string) bool {
-	isURL := govalidator.IsURL(verifyUrl)
-	isPath, _ := regexp.MatchString(`^/`, verifyUrl)
+func (r *DangerousHTMLRenderer) renderLinkIsUrl(verifyURL string) bool {
+	isURL := govalidator.IsURL(verifyURL)
+	isPath, _ := regexp.MatchString(`^/`, verifyURL)
 	return isURL || isPath
 }
diff --git a/pkg/day/day.go b/pkg/day/day.go
index 90afac0a..2fd86a6c 100644
--- a/pkg/day/day.go
+++ b/pkg/day/day.go
@@ -20,6 +20,7 @@
 package day
 
 import (
+	"strings"
 	"time"
 )
 
@@ -50,16 +51,16 @@ func Format(unix int64, format, tz string) (formatted string) {
 	for i := l; i >= 0; i-- {
 		format = strings.ReplaceAll(format, placeholders[i].old, placeholders[i].new)
 	}*/
-	toFormat := ""
+	var toFormat strings.Builder
 	from := []rune(format)
 	for len(from) > 0 {
 		to, suffix := nextStdChunk(from)
-		toFormat += string(to)
+		toFormat.WriteString(string(to))
 		from = suffix
 	}
 
 	_, _ = time.LoadLocation(tz)
-	formatted = time.Unix(unix, 0).Format(toFormat)
+	formatted = time.Unix(unix, 0).Format(toFormat.String())
 	return
 }
 
diff --git a/pkg/dir/dir.go b/pkg/dir/dir.go
index 928883c2..09591f6c 100644
--- a/pkg/dir/dir.go
+++ b/pkg/dir/dir.go
@@ -51,19 +51,19 @@ func DirSize(path string) (int64, error) {
 }
 
 func FormatFileSize(fileSize int64) (size string) {
-	if fileSize < 1024 {
-		//return strconv.FormatInt(fileSize, 10) + "B"
+	switch {
+	case fileSize < 1024:
+		// return strconv.FormatInt(fileSize, 10) + "B"
 		return fmt.Sprintf("%.2f B", float64(fileSize)/float64(1))
-	} else if fileSize < (1024 * 1024) {
+	case fileSize < (1024 * 1024):
 		return fmt.Sprintf("%.2f KB", float64(fileSize)/float64(1024))
-	} else if fileSize < (1024 * 1024 * 1024) {
+	case fileSize < (1024 * 1024 * 1024):
 		return fmt.Sprintf("%.2f MB", float64(fileSize)/float64(1024*1024))
-	} else if fileSize < (1024 * 1024 * 1024 * 1024) {
+	case fileSize < (1024 * 1024 * 1024 * 1024):
 		return fmt.Sprintf("%.2f GB", float64(fileSize)/float64(1024*1024*1024))
-	} else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) {
+	case fileSize < (1024 * 1024 * 1024 * 1024 * 1024):
 		return fmt.Sprintf("%.2f TB", float64(fileSize)/float64(1024*1024*1024*1024))
-	} else { //if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
+	default: // if fileSize < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
 		return fmt.Sprintf("%.2f EB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
 	}
-
 }
diff --git a/pkg/htmltext/htmltext.go b/pkg/htmltext/htmltext.go
index 56db4d2b..e2e017c8 100644
--- a/pkg/htmltext/htmltext.go
+++ b/pkg/htmltext/htmltext.go
@@ -77,14 +77,14 @@ func UrlTitle(title string) (text string) {
 }
 
 func clearEmoji(s string) string {
-	ret := ""
+	var ret strings.Builder
 	rs := []rune(s)
-	for i := 0; i < len(rs); i++ {
+	for i := range rs {
 		if len(string(rs[i])) != 4 {
-			ret += string(rs[i])
+			ret.WriteString(string(rs[i]))
 		}
 	}
-	return ret
+	return ret.String()
 }
 
 func convertChinese(content string) string {
@@ -164,7 +164,7 @@ func FetchRangedExcerpt(html, trimMarker string, offset int, limit int) (text st
 		text = trimMarker + text
 	}
 	if end < len(runeText) {
-		text = text + trimMarker
+		text += trimMarker
 	}
 
 	return
@@ -189,8 +189,8 @@ func FetchMatchedExcerpt(html string, words []string, trimMarker string, trimLen
 	return FetchRangedExcerpt(html, trimMarker, runeOffset, runeLimit)
 }
 
-func GetPicByUrl(Url string) string {
-	res, err := http.Get(Url)
+func GetPicByUrl(url string) string {
+	res, err := http.Get(url)
 	if err != nil {
 		return ""
 	}



Test patch:
diff --git a/internal/repo/repo_test/auth_test.go b/internal/repo/repo_test/auth_test.go
index 38733239..0c991902 100644
--- a/internal/repo/repo_test/auth_test.go
+++ b/internal/repo/repo_test/auth_test.go
@@ -26,6 +26,7 @@ import (
 	"github.com/apache/answer/internal/entity"
 	"github.com/apache/answer/internal/repo/auth"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 var (
@@ -38,10 +39,10 @@ func Test_authRepo_SetUserCacheInfo(t *testing.T) {
 	authRepo := auth.NewAuthRepo(testDataSource)
 
 	err := authRepo.SetUserCacheInfo(context.TODO(), accessToken, visitToken, &entity.UserCacheInfo{UserID: userID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	cacheInfo, err := authRepo.GetUserCacheInfo(context.TODO(), accessToken)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, userID, cacheInfo.UserID)
 }
 
@@ -49,13 +50,13 @@ func Test_authRepo_RemoveUserCacheInfo(t *testing.T) {
 	authRepo := auth.NewAuthRepo(testDataSource)
 
 	err := authRepo.SetUserCacheInfo(context.TODO(), accessToken, visitToken, &entity.UserCacheInfo{UserID: userID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	err = authRepo.RemoveUserCacheInfo(context.TODO(), accessToken)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	userInfo, err := authRepo.GetUserCacheInfo(context.TODO(), accessToken)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Nil(t, userInfo)
 }
 
@@ -63,23 +64,23 @@ func Test_authRepo_SetUserStatus(t *testing.T) {
 	authRepo := auth.NewAuthRepo(testDataSource)
 
 	err := authRepo.SetUserStatus(context.TODO(), userID, &entity.UserCacheInfo{UserID: userID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	cacheInfo, err := authRepo.GetUserStatus(context.TODO(), userID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, userID, cacheInfo.UserID)
 }
 func Test_authRepo_RemoveUserStatus(t *testing.T) {
 	authRepo := auth.NewAuthRepo(testDataSource)
 
 	err := authRepo.SetUserStatus(context.TODO(), userID, &entity.UserCacheInfo{UserID: userID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	err = authRepo.RemoveUserStatus(context.TODO(), userID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	userInfo, err := authRepo.GetUserStatus(context.TODO(), userID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Nil(t, userInfo)
 }
 
@@ -87,10 +88,10 @@ func Test_authRepo_SetAdminUserCacheInfo(t *testing.T) {
 	authRepo := auth.NewAuthRepo(testDataSource)
 
 	err := authRepo.SetAdminUserCacheInfo(context.TODO(), accessToken, &entity.UserCacheInfo{UserID: userID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	cacheInfo, err := authRepo.GetAdminUserCacheInfo(context.TODO(), accessToken)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, userID, cacheInfo.UserID)
 }
 
@@ -98,12 +99,12 @@ func Test_authRepo_RemoveAdminUserCacheInfo(t *testing.T) {
 	authRepo := auth.NewAuthRepo(testDataSource)
 
 	err := authRepo.SetAdminUserCacheInfo(context.TODO(), accessToken, &entity.UserCacheInfo{UserID: userID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	err = authRepo.RemoveAdminUserCacheInfo(context.TODO(), accessToken)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	userInfo, err := authRepo.GetAdminUserCacheInfo(context.TODO(), accessToken)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Nil(t, userInfo)
 }
diff --git a/internal/repo/repo_test/captcha_test.go b/internal/repo/repo_test/captcha_test.go
index 48e9dd80..e6954a23 100644
--- a/internal/repo/repo_test/captcha_test.go
+++ b/internal/repo/repo_test/captcha_test.go
@@ -25,6 +25,7 @@ import (
 
 	"github.com/apache/answer/internal/repo/captcha"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 var (
@@ -36,23 +37,23 @@ var (
 func Test_captchaRepo_DelActionType(t *testing.T) {
 	captchaRepo := captcha.NewCaptchaRepo(testDataSource)
 	err := captchaRepo.SetActionType(context.TODO(), ip, actionType, "", amount)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	actionInfo, err := captchaRepo.GetActionType(context.TODO(), ip, actionType)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, amount, actionInfo.Num)
 
 	err = captchaRepo.DelActionType(context.TODO(), ip, actionType)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_captchaRepo_SetCaptcha(t *testing.T) {
 	captchaRepo := captcha.NewCaptchaRepo(testDataSource)
 	key, capt := "key", "1234"
 	err := captchaRepo.SetCaptcha(context.TODO(), key, capt)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	gotCaptcha, err := captchaRepo.GetCaptcha(context.TODO(), key)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, capt, gotCaptcha)
 }
diff --git a/internal/repo/repo_test/comment_repo_test.go b/internal/repo/repo_test/comment_repo_test.go
index 3de15481..41ba0446 100644
--- a/internal/repo/repo_test/comment_repo_test.go
+++ b/internal/repo/repo_test/comment_repo_test.go
@@ -29,6 +29,7 @@ import (
 	"github.com/apache/answer/internal/repo/unique"
 	commentService "github.com/apache/answer/internal/service/comment"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func buildCommentEntity() *entity.Comment {
@@ -48,10 +49,10 @@ func Test_commentRepo_AddComment(t *testing.T) {
 	commentRepo := comment.NewCommentRepo(testDataSource, uniqueIDRepo)
 	testCommentEntity := buildCommentEntity()
 	err := commentRepo.AddComment(context.TODO(), testCommentEntity)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	err = commentRepo.RemoveComment(context.TODO(), testCommentEntity.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_commentRepo_GetCommentPage(t *testing.T) {
@@ -59,7 +60,7 @@ func Test_commentRepo_GetCommentPage(t *testing.T) {
 	commentRepo := comment.NewCommentRepo(testDataSource, uniqueIDRepo)
 	testCommentEntity := buildCommentEntity()
 	err := commentRepo.AddComment(context.TODO(), testCommentEntity)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	resp, total, err := commentRepo.GetCommentPage(context.TODO(), &commentService.CommentQuery{
 		PageCond: pager.PageCond{
@@ -67,12 +68,12 @@ func Test_commentRepo_GetCommentPage(t *testing.T) {
 			PageSize: 10,
 		},
 	})
-	assert.NoError(t, err)
-	assert.Equal(t, total, int64(1))
+	require.NoError(t, err)
+	assert.Equal(t, int64(1), total)
 	assert.Equal(t, resp[0].ID, testCommentEntity.ID)
 
 	err = commentRepo.RemoveComment(context.TODO(), testCommentEntity.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_commentRepo_UpdateComment(t *testing.T) {
@@ -81,19 +82,19 @@ func Test_commentRepo_UpdateComment(t *testing.T) {
 	commonCommentRepo := comment.NewCommentCommonRepo(testDataSource, uniqueIDRepo)
 	testCommentEntity := buildCommentEntity()
 	err := commentRepo.AddComment(context.TODO(), testCommentEntity)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	testCommentEntity.ParsedText = "test"
 	err = commentRepo.UpdateCommentContent(context.TODO(), testCommentEntity.ID, "test", "test")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	newComment, exist, err := commonCommentRepo.GetComment(context.TODO(), testCommentEntity.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, testCommentEntity.ParsedText, newComment.ParsedText)
 
 	err = commentRepo.RemoveComment(context.TODO(), testCommentEntity.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_commentRepo_CannotGetDeletedComment(t *testing.T) {
@@ -102,12 +103,12 @@ func Test_commentRepo_CannotGetDeletedComment(t *testing.T) {
 	testCommentEntity := buildCommentEntity()
 
 	err := commentRepo.AddComment(context.TODO(), testCommentEntity)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	err = commentRepo.RemoveComment(context.TODO(), testCommentEntity.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	_, exist, err := commentRepo.GetComment(context.TODO(), testCommentEntity.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.False(t, exist)
 }
diff --git a/internal/repo/repo_test/email_repo_test.go b/internal/repo/repo_test/email_repo_test.go
index 82fc6c57..03ca9efe 100644
--- a/internal/repo/repo_test/email_repo_test.go
+++ b/internal/repo/repo_test/email_repo_test.go
@@ -26,15 +26,16 @@ import (
 
 	"github.com/apache/answer/internal/repo/export"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func Test_emailRepo_VerifyCode(t *testing.T) {
 	emailRepo := export.NewEmailRepo(testDataSource)
 	code, content := "1111", "{\"source_type\":\"\",\"e_mail\":\"\",\"user_id\":\"1\",\"skip_validation_latest_code\":false}"
 	err := emailRepo.SetCode(context.TODO(), "1", code, content, time.Minute)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	verifyContent, err := emailRepo.VerifyCode(context.TODO(), code)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, content, verifyContent)
 }
diff --git a/internal/repo/repo_test/meta_repo_test.go b/internal/repo/repo_test/meta_repo_test.go
index e910dab3..68965f22 100644
--- a/internal/repo/repo_test/meta_repo_test.go
+++ b/internal/repo/repo_test/meta_repo_test.go
@@ -26,6 +26,7 @@ import (
 	"github.com/apache/answer/internal/entity"
 	"github.com/apache/answer/internal/repo/meta"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func buildMetaEntity() *entity.Meta {
@@ -41,15 +42,15 @@ func Test_metaRepo_GetMetaByObjectIdAndKey(t *testing.T) {
 	metaEnt := buildMetaEntity()
 
 	err := metaRepo.AddMeta(context.TODO(), metaEnt)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	gotMeta, exist, err := metaRepo.GetMetaByObjectIdAndKey(context.TODO(), metaEnt.ObjectID, metaEnt.Key)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, metaEnt.ID, gotMeta.ID)
 
 	err = metaRepo.RemoveMeta(context.TODO(), metaEnt.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_metaRepo_GetMetaList(t *testing.T) {
@@ -57,15 +58,15 @@ func Test_metaRepo_GetMetaList(t *testing.T) {
 	metaEnt := buildMetaEntity()
 
 	err := metaRepo.AddMeta(context.TODO(), metaEnt)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	gotMetaList, err := metaRepo.GetMetaList(context.TODO(), metaEnt)
-	assert.NoError(t, err)
-	assert.Equal(t, len(gotMetaList), 1)
+	require.NoError(t, err)
+	assert.Len(t, gotMetaList, 1)
 	assert.Equal(t, gotMetaList[0].ID, metaEnt.ID)
 
 	err = metaRepo.RemoveMeta(context.TODO(), metaEnt.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_metaRepo_GetMetaPage(t *testing.T) {
@@ -73,15 +74,15 @@ func Test_metaRepo_GetMetaPage(t *testing.T) {
 	metaEnt := buildMetaEntity()
 
 	err := metaRepo.AddMeta(context.TODO(), metaEnt)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	gotMetaList, err := metaRepo.GetMetaList(context.TODO(), metaEnt)
-	assert.NoError(t, err)
-	assert.Equal(t, len(gotMetaList), 1)
+	require.NoError(t, err)
+	assert.Len(t, gotMetaList, 1)
 	assert.Equal(t, gotMetaList[0].ID, metaEnt.ID)
 
 	err = metaRepo.RemoveMeta(context.TODO(), metaEnt.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_metaRepo_UpdateMeta(t *testing.T) {
@@ -89,17 +90,17 @@ func Test_metaRepo_UpdateMeta(t *testing.T) {
 	metaEnt := buildMetaEntity()
 
 	err := metaRepo.AddMeta(context.TODO(), metaEnt)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	metaEnt.Value = "testing"
 	err = metaRepo.UpdateMeta(context.TODO(), metaEnt)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	gotMeta, exist, err := metaRepo.GetMetaByObjectIdAndKey(context.TODO(), metaEnt.ObjectID, metaEnt.Key)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, gotMeta.Value, metaEnt.Value)
 
 	err = metaRepo.RemoveMeta(context.TODO(), metaEnt.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
diff --git a/internal/repo/repo_test/notification_repo_test.go b/internal/repo/repo_test/notification_repo_test.go
index a05913ba..4f843e77 100644
--- a/internal/repo/repo_test/notification_repo_test.go
+++ b/internal/repo/repo_test/notification_repo_test.go
@@ -27,6 +27,7 @@ import (
 	"github.com/apache/answer/internal/repo/notification"
 	"github.com/apache/answer/internal/schema"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func buildNotificationEntity() *entity.Notification {
@@ -44,13 +45,13 @@ func Test_notificationRepo_ClearIDUnRead(t *testing.T) {
 	notificationRepo := notification.NewNotificationRepo(testDataSource)
 	ent := buildNotificationEntity()
 	err := notificationRepo.AddNotification(context.TODO(), ent)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	err = notificationRepo.ClearIDUnRead(context.TODO(), ent.UserID, ent.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exists, err := notificationRepo.GetById(context.TODO(), ent.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exists)
 	assert.Equal(t, schema.NotificationRead, got.IsRead)
 }
@@ -59,13 +60,13 @@ func Test_notificationRepo_ClearUnRead(t *testing.T) {
 	notificationRepo := notification.NewNotificationRepo(testDataSource)
 	ent := buildNotificationEntity()
 	err := notificationRepo.AddNotification(context.TODO(), ent)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	err = notificationRepo.ClearUnRead(context.TODO(), ent.UserID, ent.Type)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exists, err := notificationRepo.GetById(context.TODO(), ent.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exists)
 	assert.Equal(t, schema.NotificationRead, got.IsRead)
 }
@@ -74,10 +75,10 @@ func Test_notificationRepo_GetById(t *testing.T) {
 	notificationRepo := notification.NewNotificationRepo(testDataSource)
 	ent := buildNotificationEntity()
 	err := notificationRepo.AddNotification(context.TODO(), ent)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exists, err := notificationRepo.GetById(context.TODO(), ent.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exists)
 	assert.Equal(t, got.ID, ent.ID)
 }
@@ -86,10 +87,10 @@ func Test_notificationRepo_GetByUserIdObjectIdTypeId(t *testing.T) {
 	notificationRepo := notification.NewNotificationRepo(testDataSource)
 	ent := buildNotificationEntity()
 	err := notificationRepo.AddNotification(context.TODO(), ent)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exists, err := notificationRepo.GetByUserIdObjectIdTypeId(context.TODO(), ent.UserID, ent.ObjectID, ent.Type)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exists)
 	assert.Equal(t, got.ObjectID, ent.ObjectID)
 }
@@ -98,11 +99,11 @@ func Test_notificationRepo_GetNotificationPage(t *testing.T) {
 	notificationRepo := notification.NewNotificationRepo(testDataSource)
 	ent := buildNotificationEntity()
 	err := notificationRepo.AddNotification(context.TODO(), ent)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	notificationPage, total, err := notificationRepo.GetNotificationPage(context.TODO(), &schema.NotificationSearch{UserID: ent.UserID})
-	assert.NoError(t, err)
-	assert.True(t, total > 0)
+	require.NoError(t, err)
+	assert.Positive(t, total)
 	assert.Equal(t, notificationPage[0].UserID, ent.UserID)
 }
 
@@ -110,14 +111,14 @@ func Test_notificationRepo_UpdateNotificationContent(t *testing.T) {
 	notificationRepo := notification.NewNotificationRepo(testDataSource)
 	ent := buildNotificationEntity()
 	err := notificationRepo.AddNotification(context.TODO(), ent)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	ent.Content = "test"
 	err = notificationRepo.UpdateNotificationContent(context.TODO(), ent)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exists, err := notificationRepo.GetById(context.TODO(), ent.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exists)
 	assert.Equal(t, got.Content, ent.Content)
 }
diff --git a/internal/repo/repo_test/reason_repo_test.go b/internal/repo/repo_test/reason_repo_test.go
index 636f8d27..acb8c861 100644
--- a/internal/repo/repo_test/reason_repo_test.go
+++ b/internal/repo/repo_test/reason_repo_test.go
@@ -28,12 +28,13 @@ import (
 
 	"github.com/apache/answer/internal/repo/reason"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func Test_reasonRepo_ListReasons(t *testing.T) {
 	configRepo := config.NewConfigRepo(testDataSource)
 	reasonRepo := reason.NewReasonRepo(serviceconfig.NewConfigService(configRepo))
 	reasonItems, err := reasonRepo.ListReasons(context.TODO(), "question", "close")
-	assert.NoError(t, err)
-	assert.Equal(t, 4, len(reasonItems))
+	require.NoError(t, err)
+	assert.Len(t, reasonItems, 4)
 }
diff --git a/internal/repo/repo_test/recommend_test.go b/internal/repo/repo_test/recommend_test.go
index a2169388..7675aa20 100644
--- a/internal/repo/repo_test/recommend_test.go
+++ b/internal/repo/repo_test/recommend_test.go
@@ -34,6 +34,7 @@ import (
 	"github.com/apache/answer/internal/repo/user"
 	config2 "github.com/apache/answer/internal/service/config"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func Test_questionRepo_GetRecommend(t *testing.T) {
@@ -61,8 +62,8 @@ func Test_questionRepo_GetRecommend(t *testing.T) {
 		IsAdmin:     false,
 	}
 	err := userRepo.AddUser(context.TODO(), user)
-	assert.NoError(t, err)
-	assert.NotEqual(t, "", user.ID)
+	require.NoError(t, err)
+	assert.NotEmpty(t, user.ID)
 
 	questions := make([]*entity.Question, 0)
 	// tag, unjoin, unfollow
@@ -140,8 +141,8 @@ func Test_questionRepo_GetRecommend(t *testing.T) {
 
 	for _, question := range questions {
 		err = questionRepo.AddQuestion(context.TODO(), question)
-		assert.NoError(t, err)
-		assert.NotEqual(t, "", question.ID)
+		require.NoError(t, err)
+		assert.NotEmpty(t, question.ID)
 	}
 
 	tags := []*entity.Tag{
@@ -161,7 +162,7 @@ func Test_questionRepo_GetRecommend(t *testing.T) {
 		},
 	}
 	err = tagCommenRepo.AddTagList(context.TODO(), tags)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	tagRels := make([]*entity.TagRel, 0)
 	for i, question := range questions {
@@ -173,7 +174,7 @@ func Test_questionRepo_GetRecommend(t *testing.T) {
 		tagRels = append(tagRels, tagRel)
 	}
 	err = tagRelRepo.AddTagRelList(context.TODO(), tagRels)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	followQuestionIDs := make([]string, 0)
 	for i := range questions {
@@ -181,15 +182,15 @@ func Test_questionRepo_GetRecommend(t *testing.T) {
 			continue
 		}
 		err = followRepo.Follow(context.TODO(), questions[i].ID, user.ID)
-		assert.NoError(t, err)
+		require.NoError(t, err)
 		followQuestionIDs = append(followQuestionIDs, questions[i].ID)
 	}
 
 	// get recommend
 	questionList, total, err := questionRepo.GetRecommendQuestionPageByTags(context.TODO(), user.ID, []string{tags[0].ID}, followQuestionIDs, 1, 20)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, int64(5), total)
-	assert.Equal(t, 5, len(questionList))
+	assert.Len(t, questionList, 5)
 
 	// recovery
 	t.Cleanup(func() {
@@ -197,19 +198,19 @@ func Test_questionRepo_GetRecommend(t *testing.T) {
 		for i, tagRel := range tagRels {
 			if i%2 == 1 {
 				err = followRepo.FollowCancel(context.TODO(), questions[i].ID, user.ID)
-				assert.NoError(t, err)
+				require.NoError(t, err)
 			}
 			tagRelIDs = append(tagRelIDs, tagRel.ID)
 		}
 		err = tagRelRepo.RemoveTagRelListByIDs(context.TODO(), tagRelIDs)
-		assert.NoError(t, err)
+		require.NoError(t, err)
 		for _, tag := range tags {
 			err = tagRepo.RemoveTag(context.TODO(), tag.ID)
-			assert.NoError(t, err)
+			require.NoError(t, err)
 		}
 		for _, q := range questions {
 			err = questionRepo.RemoveQuestion(context.TODO(), q.ID)
-			assert.NoError(t, err)
+			require.NoError(t, err)
 		}
 	})
 }
diff --git a/internal/repo/repo_test/repo_main_test.go b/internal/repo/repo_test/repo_main_test.go
index 919ca94e..e2f40f27 100644
--- a/internal/repo/repo_test/repo_main_test.go
+++ b/internal/repo/repo_test/repo_main_test.go
@@ -153,7 +153,7 @@ func initDatabaseImage(dbSetting TestDBSetting) (connection string, cleanup func
 		return "", nil, fmt.Errorf("could not connect to docker: %s", err)
 	}
 
-	//resource, err := pool.Run(dbSetting.ImageName, dbSetting.ImageVersion, dbSetting.ENV)
+	// resource, err := pool.Run(dbSetting.ImageName, dbSetting.ImageVersion, dbSetting.ENV)
 	resource, err := pool.RunWithOptions(&dockertest.RunOptions{
 		Repository: dbSetting.ImageName,
 		Tag:        dbSetting.ImageVersion,
diff --git a/internal/repo/repo_test/revision_repo_test.go b/internal/repo/repo_test/revision_repo_test.go
index 01d262d2..6fd067b3 100644
--- a/internal/repo/repo_test/revision_repo_test.go
+++ b/internal/repo/repo_test/revision_repo_test.go
@@ -29,6 +29,7 @@ import (
 	"github.com/apache/answer/internal/repo/revision"
 	"github.com/apache/answer/internal/repo/unique"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 var q = &entity.Question{
@@ -69,29 +70,29 @@ func Test_revisionRepo_AddRevision(t *testing.T) {
 
 	// create question
 	err := questionRepo.AddQuestion(context.TODO(), q)
-	assert.NoError(t, err)
-	assert.NotEqual(t, "", q.ID)
+	require.NoError(t, err)
+	assert.NotEmpty(t, q.ID)
 
 	content, err := json.Marshal(q)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	// auto update false
 	rev := getRev(q.ID, q.Title, string(content))
 	err = revisionRepo.AddRevision(context.TODO(), rev, false)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	qr, _, _ := questionRepo.GetQuestion(context.TODO(), q.ID)
 	assert.NotEqual(t, rev.ID, qr.RevisionID)
 
 	// auto update false
 	rev = getRev(q.ID, q.Title, string(content))
 	err = revisionRepo.AddRevision(context.TODO(), rev, true)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	qr, _, _ = questionRepo.GetQuestion(context.TODO(), q.ID)
 	assert.Equal(t, rev.ID, qr.RevisionID)
 
 	// recovery
 	t.Cleanup(func() {
 		err = questionRepo.RemoveQuestion(context.TODO(), q.ID)
-		assert.NoError(t, err)
+		require.NoError(t, err)
 	})
 }
 
@@ -103,7 +104,7 @@ func Test_revisionRepo_GetLastRevisionByObjectID(t *testing.T) {
 
 	Test_revisionRepo_AddRevision(t)
 	rev, exists, err := revisionRepo.GetLastRevisionByObjectID(context.TODO(), q.ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exists)
 	assert.NotNil(t, rev)
 }
@@ -115,6 +116,6 @@ func Test_revisionRepo_GetRevisionList(t *testing.T) {
 	)
 	Test_revisionRepo_AddRevision(t)
 	revs, err := revisionRepo.GetRevisionList(context.TODO(), &entity.Revision{ObjectID: q.ID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.GreaterOrEqual(t, len(revs), 1)
 }
diff --git a/internal/repo/repo_test/siteinfo_repo_test.go b/internal/repo/repo_test/siteinfo_repo_test.go
index cb5d8fc0..9fa59d17 100644
--- a/internal/repo/repo_test/siteinfo_repo_test.go
+++ b/internal/repo/repo_test/siteinfo_repo_test.go
@@ -26,6 +26,7 @@ import (
 	"github.com/apache/answer/internal/entity"
 	"github.com/apache/answer/internal/repo/site_info"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func Test_siteInfoRepo_SaveByType(t *testing.T) {
@@ -34,19 +35,19 @@ func Test_siteInfoRepo_SaveByType(t *testing.T) {
 	data := &entity.SiteInfo{Content: "site_info", Type: "test"}
 
 	err := siteInfoRepo.SaveByType(context.TODO(), data.Type, data)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exist, err := siteInfoRepo.GetByType(context.TODO(), data.Type)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, data.Content, got.Content)
 
 	data.Content = "new site_info"
 	err = siteInfoRepo.SaveByType(context.TODO(), data.Type, data)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exist, err = siteInfoRepo.GetByType(context.TODO(), data.Type)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, data.Content, got.Content)
 }
diff --git a/internal/repo/repo_test/tag_rel_repo_test.go b/internal/repo/repo_test/tag_rel_repo_test.go
index e3af67a1..47c09a6a 100644
--- a/internal/repo/repo_test/tag_rel_repo_test.go
+++ b/internal/repo/repo_test/tag_rel_repo_test.go
@@ -30,6 +30,7 @@ import (
 	"github.com/apache/answer/internal/entity"
 	"github.com/apache/answer/internal/repo/tag"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 var (
@@ -61,15 +62,15 @@ func Test_tagListRepo_BatchGetObjectTagRelList(t *testing.T) {
 	tagRelRepo := tag.NewTagRelRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 	relList, err :=
 		tagRelRepo.BatchGetObjectTagRelList(context.TODO(), []string{testTagRelList[0].ObjectID, testTagRelList[1].ObjectID})
-	assert.NoError(t, err)
-	assert.Equal(t, 2, len(relList))
+	require.NoError(t, err)
+	assert.Len(t, relList, 2)
 }
 
 func Test_tagListRepo_CountTagRelByTagID(t *testing.T) {
 	tagRelOnce.Do(addTagRelList)
 	tagRelRepo := tag.NewTagRelRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 	count, err := tagRelRepo.CountTagRelByTagID(context.TODO(), "10030000000000101")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, int64(1), count)
 }
 
@@ -79,8 +80,8 @@ func Test_tagListRepo_GetObjectTagRelList(t *testing.T) {
 
 	relList, err :=
 		tagRelRepo.GetObjectTagRelList(context.TODO(), testTagRelList[0].ObjectID)
-	assert.NoError(t, err)
-	assert.Equal(t, 1, len(relList))
+	require.NoError(t, err)
+	assert.Len(t, relList, 1)
 }
 
 func Test_tagListRepo_GetObjectTagRelWithoutStatus(t *testing.T) {
@@ -89,25 +90,25 @@ func Test_tagListRepo_GetObjectTagRelWithoutStatus(t *testing.T) {
 
 	relList, err :=
 		tagRelRepo.BatchGetObjectTagRelList(context.TODO(), []string{testTagRelList[0].ObjectID, testTagRelList[1].ObjectID})
-	assert.NoError(t, err)
-	assert.Equal(t, 2, len(relList))
+	require.NoError(t, err)
+	assert.Len(t, relList, 2)
 
 	ids := []int64{relList[0].ID, relList[1].ID}
 	err = tagRelRepo.RemoveTagRelListByIDs(context.TODO(), ids)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	count, err := tagRelRepo.CountTagRelByTagID(context.TODO(), "10030000000000101")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, int64(0), count)
 
 	_, exist, err := tagRelRepo.GetObjectTagRelWithoutStatus(context.TODO(), relList[0].ObjectID, relList[0].TagID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 
 	err = tagRelRepo.EnableTagRelByIDs(context.TODO(), ids, false)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	count, err = tagRelRepo.CountTagRelByTagID(context.TODO(), "10030000000000101")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, int64(1), count)
 }
diff --git a/internal/repo/repo_test/tag_repo_test.go b/internal/repo/repo_test/tag_repo_test.go
index b2475a22..aa1ec1a2 100644
--- a/internal/repo/repo_test/tag_repo_test.go
+++ b/internal/repo/repo_test/tag_repo_test.go
@@ -32,6 +32,7 @@ import (
 	"github.com/apache/answer/internal/repo/unique"
 	"github.com/apache/answer/pkg/converter"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 var (
@@ -75,7 +76,7 @@ func Test_tagRepo_GetTagByID(t *testing.T) {
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, testTagList[0].SlugName, gotTag.SlugName)
 }
@@ -85,7 +86,7 @@ func Test_tagRepo_GetTagBySlugName(t *testing.T) {
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTag, exist, err := tagCommonRepo.GetTagBySlugName(context.TODO(), testTagList[0].SlugName)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, testTagList[0].SlugName, gotTag.SlugName)
 }
@@ -95,7 +96,7 @@ func Test_tagRepo_GetTagList(t *testing.T) {
 	tagRepo := tag.NewTagRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTags, err := tagRepo.GetTagList(context.TODO(), &entity.Tag{ID: testTagList[0].ID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName)
 }
 
@@ -104,7 +105,7 @@ func Test_tagRepo_GetTagListByIDs(t *testing.T) {
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTags, err := tagCommonRepo.GetTagListByIDs(context.TODO(), []string{testTagList[0].ID})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName)
 }
 
@@ -113,7 +114,7 @@ func Test_tagRepo_GetTagListByName(t *testing.T) {
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTags, err := tagCommonRepo.GetTagListByName(context.TODO(), testTagList[0].SlugName, false, false)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName)
 }
 
@@ -122,7 +123,7 @@ func Test_tagRepo_GetTagListByNames(t *testing.T) {
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTags, err := tagCommonRepo.GetTagListByNames(context.TODO(), []string{testTagList[0].SlugName})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName)
 }
 
@@ -131,7 +132,7 @@ func Test_tagRepo_GetTagPage(t *testing.T) {
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTags, _, err := tagCommonRepo.GetTagPage(context.TODO(), 1, 1, &entity.Tag{SlugName: testTagList[0].SlugName}, "")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, testTagList[0].SlugName, gotTags[0].SlugName)
 }
 
@@ -140,12 +141,12 @@ func Test_tagRepo_RemoveTag(t *testing.T) {
 	uniqueIDRepo := unique.NewUniqueIDRepo(testDataSource)
 	tagRepo := tag.NewTagRepo(testDataSource, uniqueIDRepo)
 	err := tagRepo.RemoveTag(context.TODO(), testTagList[1].ID)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	_, exist, err := tagCommonRepo.GetTagBySlugName(context.TODO(), testTagList[1].SlugName)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.False(t, exist)
 }
 
@@ -155,12 +156,12 @@ func Test_tagRepo_UpdateTag(t *testing.T) {
 
 	testTagList[0].DisplayName = "golang"
 	err := tagRepo.UpdateTag(context.TODO(), testTagList[0])
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, testTagList[0].DisplayName, gotTag.DisplayName)
 }
@@ -170,10 +171,10 @@ func Test_tagRepo_UpdateTagQuestionCount(t *testing.T) {
 
 	testTagList[0].DisplayName = "golang"
 	err := tagCommonRepo.UpdateTagQuestionCount(context.TODO(), testTagList[0].ID, 100)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[0].ID, true)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, 100, gotTag.QuestionCount)
 }
@@ -184,16 +185,16 @@ func Test_tagRepo_UpdateTagSynonym(t *testing.T) {
 
 	testTagList[0].DisplayName = "golang"
 	err := tagRepo.UpdateTag(context.TODO(), testTagList[0])
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	err = tagRepo.UpdateTagSynonym(context.TODO(), []string{testTagList[2].SlugName},
 		converter.StringToInt64(testTagList[0].ID), testTagList[0].SlugName)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	tagCommonRepo := tag_common.NewTagCommonRepo(testDataSource, unique.NewUniqueIDRepo(testDataSource))
 
 	gotTag, exist, err := tagCommonRepo.GetTagByID(context.TODO(), testTagList[2].ID, true)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, testTagList[0].ID, fmt.Sprintf("%d", gotTag.MainTagID))
 }
diff --git a/internal/repo/repo_test/user_backyard_repo_test.go b/internal/repo/repo_test/user_backyard_repo_test.go
index 073a600c..eb4db102 100644
--- a/internal/repo/repo_test/user_backyard_repo_test.go
+++ b/internal/repo/repo_test/user_backyard_repo_test.go
@@ -28,12 +28,13 @@ import (
 	"github.com/apache/answer/internal/repo/auth"
 	"github.com/apache/answer/internal/repo/user"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func Test_userAdminRepo_GetUserInfo(t *testing.T) {
 	userAdminRepo := user.NewUserAdminRepo(testDataSource, auth.NewAuthRepo(testDataSource))
 	got, exist, err := userAdminRepo.GetUserInfo(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, "1", got.ID)
 }
@@ -41,7 +42,7 @@ func Test_userAdminRepo_GetUserInfo(t *testing.T) {
 func Test_userAdminRepo_GetUserPage(t *testing.T) {
 	userAdminRepo := user.NewUserAdminRepo(testDataSource, auth.NewAuthRepo(testDataSource))
 	got, total, err := userAdminRepo.GetUserPage(context.TODO(), 1, 1, &entity.User{Username: "admin"}, "", false)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.Equal(t, int64(1), total)
 	assert.Equal(t, "1", got[0].ID)
 }
@@ -49,25 +50,25 @@ func Test_userAdminRepo_GetUserPage(t *testing.T) {
 func Test_userAdminRepo_UpdateUserStatus(t *testing.T) {
 	userAdminRepo := user.NewUserAdminRepo(testDataSource, auth.NewAuthRepo(testDataSource))
 	got, exist, err := userAdminRepo.GetUserInfo(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, entity.UserStatusAvailable, got.Status)
 
 	err = userAdminRepo.UpdateUserStatus(context.TODO(), "1", entity.UserStatusSuspended, entity.EmailStatusAvailable,
 		"admin@admin.com", time.Now().Add(time.Minute*5))
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exist, err = userAdminRepo.GetUserInfo(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, entity.UserStatusSuspended, got.Status)
 
 	err = userAdminRepo.UpdateUserStatus(context.TODO(), "1", entity.UserStatusAvailable, entity.EmailStatusAvailable,
 		"admin@admin.com", time.Time{})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exist, err = userAdminRepo.GetUserInfo(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, entity.UserStatusAvailable, got.Status)
 }
diff --git a/internal/repo/repo_test/user_repo_test.go b/internal/repo/repo_test/user_repo_test.go
index 7b18833d..95a85ab9 100644
--- a/internal/repo/repo_test/user_repo_test.go
+++ b/internal/repo/repo_test/user_repo_test.go
@@ -26,6 +26,7 @@ import (
 	"github.com/apache/answer/internal/entity"
 	"github.com/apache/answer/internal/repo/user"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func Test_userRepo_AddUser(t *testing.T) {
@@ -40,21 +41,21 @@ func Test_userRepo_AddUser(t *testing.T) {
 		IsAdmin:     false,
 	}
 	err := userRepo.AddUser(context.TODO(), userInfo)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_userRepo_BatchGetByID(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	got, err := userRepo.BatchGetByID(context.TODO(), []string{"1"})
-	assert.NoError(t, err)
-	assert.Equal(t, 1, len(got))
+	require.NoError(t, err)
+	assert.Len(t, got, 1)
 	assert.Equal(t, "admin", got[0].Username)
 }
 
 func Test_userRepo_GetByEmail(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	got, exist, err := userRepo.GetByEmail(context.TODO(), "admin@admin.com")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, "admin", got.Username)
 }
@@ -62,7 +63,7 @@ func Test_userRepo_GetByEmail(t *testing.T) {
 func Test_userRepo_GetByUserID(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	got, exist, err := userRepo.GetByUserID(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, "admin", got.Username)
 }
@@ -70,7 +71,7 @@ func Test_userRepo_GetByUserID(t *testing.T) {
 func Test_userRepo_GetByUsername(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	got, exist, err := userRepo.GetByUsername(context.TODO(), "admin")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, "admin", got.Username)
 }
@@ -78,10 +79,10 @@ func Test_userRepo_GetByUsername(t *testing.T) {
 func Test_userRepo_IncreaseAnswerCount(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	err := userRepo.IncreaseAnswerCount(context.TODO(), "1", 1)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exist, err := userRepo.GetByUserID(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, 1, got.AnswerCount)
 }
@@ -89,10 +90,10 @@ func Test_userRepo_IncreaseAnswerCount(t *testing.T) {
 func Test_userRepo_IncreaseQuestionCount(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	err := userRepo.IncreaseQuestionCount(context.TODO(), "1", 1)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exist, err := userRepo.GetByUserID(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, 1, got.AnswerCount)
 }
@@ -100,22 +101,22 @@ func Test_userRepo_IncreaseQuestionCount(t *testing.T) {
 func Test_userRepo_UpdateEmail(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	err := userRepo.UpdateEmail(context.TODO(), "1", "admin@admin.com")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_userRepo_UpdateEmailStatus(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	err := userRepo.UpdateEmailStatus(context.TODO(), "1", entity.EmailStatusToBeVerified)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_userRepo_UpdateInfo(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	err := userRepo.UpdateInfo(context.TODO(), &entity.User{ID: "1", Bio: "test"})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	got, exist, err := userRepo.GetByUserID(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	assert.True(t, exist)
 	assert.Equal(t, "test", got.Bio)
 }
@@ -123,17 +124,17 @@ func Test_userRepo_UpdateInfo(t *testing.T) {
 func Test_userRepo_UpdateLastLoginDate(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	err := userRepo.UpdateLastLoginDate(context.TODO(), "1")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_userRepo_UpdateNoticeStatus(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	err := userRepo.UpdateNoticeStatus(context.TODO(), "1", 1)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
 
 func Test_userRepo_UpdatePass(t *testing.T) {
 	userRepo := user.NewUserRepo(testDataSource)
 	err := userRepo.UpdatePass(context.TODO(), "1", "admin")
-	assert.NoError(t, err)
+	require.NoError(t, err)
 }
diff --git a/internal/service/content/question_hottest_service.go b/internal/service/content/question_hottest_service.go
index 085b3670..b73e7a30 100644
--- a/internal/service/content/question_hottest_service.go
+++ b/internal/service/content/question_hottest_service.go
@@ -30,7 +30,6 @@ import (
 )
 
 func (q *QuestionService) RefreshHottestCron(ctx context.Context) {
-
 	var (
 		page     = 1
 		pageSize = 100
diff --git a/internal/service/siteinfo_common/siteinfo_service_test.go b/internal/service/siteinfo_common/siteinfo_service_test.go
index 3a567dcb..a87d427f 100644
--- a/internal/service/siteinfo_common/siteinfo_service_test.go
+++ b/internal/service/siteinfo_common/siteinfo_service_test.go
@@ -27,6 +27,7 @@ import (
 	"github.com/apache/answer/internal/entity"
 	"github.com/apache/answer/internal/service/mock"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 	"go.uber.org/mock/gomock"
 )
 
@@ -46,6 +47,6 @@ func TestSiteInfoCommonService_GetSiteGeneral(t *testing.T) {
 	mockInit(ctl)
 	siteInfoCommonService := NewSiteInfoCommonService(mockSiteInfoRepo)
 	resp, err := siteInfoCommonService.GetSiteGeneral(context.TODO())
-	assert.NoError(t, err)
-	assert.Equal(t, resp.Name, "name")
+	require.NoError(t, err)
+	assert.Equal(t, "name", resp.Name)
 }
diff --git a/pkg/htmltext/htmltext_test.go b/pkg/htmltext/htmltext_test.go
index 63866eb2..39de9e96 100644
--- a/pkg/htmltext/htmltext_test.go
+++ b/pkg/htmltext/htmltext_test.go
@@ -186,11 +186,11 @@ func TestCutLongTitle(t *testing.T) {
 
 	// Exactly max bytes, no cutting needed
 	exact150 := strings.Repeat("a", 150)
-	assert.Equal(t, 150, len(cutLongTitle(exact150)))
+	assert.Len(t, cutLongTitle(exact150), 150)
 
 	// Just over max bytes, should be cut
 	exact151 := strings.Repeat("a", 151)
-	assert.Equal(t, 150, len(cutLongTitle(exact151)))
+	assert.Len(t, cutLongTitle(exact151), 150)
 
 	// Multi-byte rune at boundary gets removed properly
 	asciiPart := strings.Repeat("a", 149) // 149 bytes
diff --git a/plugin/plugin_test/plugin_main_test.go b/plugin/plugin_test/plugin_main_test.go
index fd9015c8..7ba6f8ae 100644
--- a/plugin/plugin_test/plugin_main_test.go
+++ b/plugin/plugin_test/plugin_main_test.go
@@ -81,19 +81,16 @@ func TestMain(t *testing.M) {
 		_ = os.RemoveAll(dbSetting.Connection)
 	}
 
-	defer func() {
-		if tearDown != nil {
-			tearDown()
-		}
-	}()
 	if err := initTestDataSource(dbSetting); err != nil {
 		panic(err)
 	}
 	log.Info("init test database successfully")
 
-	if ret := t.Run(); ret != 0 {
-		os.Exit(ret)
+	ret := t.Run()
+	if tearDown != nil {
+		tearDown()
 	}
+	os.Exit(ret)
 }
 
 type TestDBSetting struct {
@@ -155,7 +152,7 @@ func initDatabaseImage(dbSetting TestDBSetting) (connection string, cleanup func
 		return "", nil, fmt.Errorf("could not connect to docker: %s", err)
 	}
 
-	//resource, err := pool.Run(dbSetting.ImageName, dbSetting.ImageVersion, dbSetting.ENV)
+	// resource, err := pool.Run(dbSetting.ImageName, dbSetting.ImageVersion, dbSetting.ENV)
 	resource, err := pool.RunWithOptions(&dockertest.RunOptions{
 		Repository: dbSetting.ImageName,
 		Tag:        dbSetting.ImageVersion,