Skip to content

Commit 98df06d

Browse files
committed
✨ add .golangci.yml
1 parent f1f49ab commit 98df06d

File tree

12 files changed

+300
-48
lines changed

12 files changed

+300
-48
lines changed

.golangci.yml

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
run:
2+
# Concurrently run upto 4
3+
concurrency: 4
4+
# Issue exit code
5+
issues-exit-code: 1
6+
# Lint tests
7+
tests: true
8+
# Lint timeout
9+
timeout: 5m
10+
11+
linters-settings:
12+
errcheck:
13+
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`.
14+
# Such cases aren't reported by default.
15+
# Default: false
16+
check-blank: true
17+
# Report about not checking of errors in type assertions: `a := b.(MyStruct)`.
18+
# Such cases aren't reported by default.
19+
# Default: false
20+
check-type-assertions: true
21+
gocritic:
22+
enabled-tags:
23+
- diagnostic
24+
- experimental
25+
- opinionated
26+
- performance
27+
- style
28+
gocyclo:
29+
min-complexity: 15
30+
gofumpt:
31+
module-path: github.com/leetcode-golang-classroom/golang-rest-api-sample
32+
extra-rules: true
33+
# Import statements are formatted
34+
goimports:
35+
local-prefixes: github.com/leetcode-golang-classroom/golang-rest-api-sample
36+
gosimple:
37+
checks: ["all"]
38+
govet:
39+
enable-all: true
40+
disable:
41+
- fieldalignment
42+
ireturn:
43+
allow:
44+
- error
45+
lll:
46+
line-length: 160
47+
misspell:
48+
locale: US
49+
nolintlint:
50+
allow-unused: false
51+
require-explanation: true
52+
require-specific: true
53+
prealloc:
54+
simple: true
55+
range-loops: true
56+
for-loops: true
57+
promlinter:
58+
strict: true
59+
revive:
60+
rules:
61+
- name: blank-imports
62+
disabled: true
63+
- name: context-as-argument
64+
- name: context-keys-type
65+
- name: dot-imports
66+
- name: error-return
67+
- name: error-strings
68+
- name: error-naming
69+
- name: exported
70+
- name: if-return
71+
- name: increment-decrement
72+
- name: var-naming
73+
- name: var-declaration
74+
disabled: true
75+
- name: package-comments
76+
- name: range
77+
- name: receiver-naming
78+
- name: time-naming
79+
- name: unexported-return
80+
- name: indent-error-flow
81+
- name: errorf
82+
- name: empty-block
83+
- name: superfluous-else
84+
- name: unused-parameter
85+
- name: unreachable-code
86+
- name: redefines-builtin-id
87+
staticcheck:
88+
checks: ["all"]
89+
stylecheck:
90+
checks: ["all"]
91+
http-status-code-whitelist: []
92+
93+
linters:
94+
enable:
95+
- asasalint
96+
- asciicheck
97+
- bidichk
98+
- bodyclose
99+
- containedctx
100+
- contextcheck
101+
- dogsled
102+
- dupl
103+
- durationcheck
104+
- errname
105+
- errorlint
106+
- exhaustive
107+
- exportloopref
108+
- forbidigo
109+
- forcetypeassert
110+
- goconst
111+
- gocritic
112+
- gocyclo
113+
- godot
114+
- gofumpt
115+
- goimports
116+
- goprintffuncname
117+
- gosec
118+
- interfacebloat
119+
# - ireturn
120+
- lll
121+
- misspell
122+
- nakedret
123+
- nestif
124+
- nilerr
125+
- nilnil
126+
- noctx
127+
- nolintlint
128+
- prealloc
129+
- predeclared
130+
- promlinter
131+
- revive
132+
- rowserrcheck
133+
- sqlclosecheck
134+
- stylecheck
135+
- tenv
136+
- testpackage
137+
- thelper
138+
- tparallel
139+
- unconvert
140+
- unparam
141+
- usestdlibvars
142+
- wastedassign
143+
- whitespace
144+
- wrapcheck
145+
146+
issues:
147+
exclude-rules:
148+
- path: _test\.go
149+
linters:
150+
- bodyclose
151+
- forcetypeassert
152+
- goconst
153+
- ireturn
154+
- dupl
155+
- containedctx
156+
include:
157+
- EXC0012
158+
- EXC0014
159+
fix: true

cmd/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func main() {
1919
},
2020
))
2121
rootContext := context.WithValue(context.Background(), mlog.CtxKey{}, logger)
22-
app := application.New(config.AppConfig, rootContext)
22+
app := application.New(rootContext, config.AppConfig)
2323
ctx, cancel := signal.NotifyContext(rootContext, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
2424
defer cancel()
2525
err := app.Start(ctx)

interanl/application/app.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,35 @@ import (
77
"time"
88

99
"github.com/gin-gonic/gin"
10+
1011
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/config"
1112
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/logger"
1213
)
1314

14-
// define app dependency
15+
// App define app dependency.
1516
type App struct {
1617
Router *gin.Engine
17-
config *config.Config
18+
cfg *config.Config
1819
}
1920

20-
func New(config *config.Config, ctx context.Context) *App {
21+
// New - app constructor.
22+
func New(ctx context.Context, cfg *config.Config) *App {
2123
app := &App{
22-
config: config,
24+
cfg: cfg,
2325
}
2426
app.SetupRoutes(ctx)
2527
return app
2628
}
2729

30+
// Start - app 啟動.
2831
func (app *App) Start(ctx context.Context) error {
29-
logger := logger.FromContext(ctx)
32+
log := logger.FromContext(ctx)
3033
server := &http.Server{
31-
Addr: fmt.Sprintf(":%s", app.config.Port),
32-
Handler: app.Router,
34+
Addr: fmt.Sprintf(":%s", app.cfg.Port),
35+
Handler: app.Router,
36+
ReadHeaderTimeout: time.Minute,
3337
}
34-
logger.Info(fmt.Sprintf("Starting server on %s", app.config.Port))
38+
log.Info(fmt.Sprintf("Starting server on %s", app.cfg.Port))
3539
errCh := make(chan error, 1)
3640
go func() {
3741
err := server.ListenAndServe()
@@ -45,9 +49,13 @@ func (app *App) Start(ctx context.Context) error {
4549
case err := <-errCh:
4650
return err
4751
case <-ctx.Done():
48-
logger.Info("server cancel")
49-
timeout, cancel := context.WithTimeout(context.Background(), time.Second*10)
52+
log.Info("server cancel")
53+
timeout, cancel := context.WithTimeout(ctx, time.Second*10)
5054
defer cancel()
51-
return server.Shutdown(timeout)
55+
err := server.Shutdown(timeout)
56+
if err != nil {
57+
return fmt.Errorf("%w", err)
58+
}
59+
return nil
5260
}
5361
}

interanl/application/route.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import (
55
"net/http"
66

77
"github.com/gin-gonic/gin"
8+
sloggin "github.com/samber/slog-gin"
9+
810
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/logger"
911
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/services/news"
10-
sloggin "github.com/samber/slog-gin"
1112
)
1213

13-
// define route
14+
// SetupRoutes - define route.
1415
func (app *App) SetupRoutes(ctx context.Context) {
15-
gin.SetMode(app.config.GinMode)
16+
gin.SetMode(app.cfg.GinMode)
1617
router := gin.New()
1718
// recovery middleward
1819
router.Use(sloggin.New(logger.FromContext(ctx)))
@@ -24,8 +25,10 @@ func (app *App) SetupRoutes(ctx context.Context) {
2425
app.SetupNewsRoutes()
2526
}
2627

28+
// SetupNewsRoutes - setup new routes.
2729
func (app *App) SetupNewsRoutes() {
2830
newGroups := app.Router.Group("/news")
29-
handler := news.NewHandler()
31+
newsStore := news.NewNewsStore()
32+
handler := news.NewHandler(newsStore)
3033
handler.RegisterRoute(newGroups)
3134
}

interanl/config/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import (
66
"github.com/spf13/viper"
77
)
88

9+
// Config - App config.
910
type Config struct {
1011
Port string `mapstructure:"PORT"`
1112
GinMode string `mapstructure:"GIN_MODE"`
1213
}
1314

15+
// AppConfig - global config.
1416
var AppConfig *Config
1517

1618
func init() {

interanl/logger/log.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import (
66
"os"
77
)
88

9+
// CtxKey - struct.
910
type CtxKey struct{}
1011

12+
// CtxWithLogger - create ctx with logger.
1113
func CtxWithLogger(ctx context.Context, logger *slog.Logger) context.Context {
1214
if logger == nil {
1315
return ctx
@@ -18,6 +20,7 @@ func CtxWithLogger(ctx context.Context, logger *slog.Logger) context.Context {
1820
return context.WithValue(ctx, CtxKey{}, logger)
1921
}
2022

23+
// FromContext - get slog from ctx.
2124
func FromContext(ctx context.Context) *slog.Logger {
2225
if logger, ok := ctx.Value(CtxKey{}).(*slog.Logger); ok {
2326
return logger

interanl/logger/log_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ func Test_FromContext(t *testing.T) {
6969
}
7070
for _, tc := range testCases {
7171
t.Run(tc.name, func(t *testing.T) {
72-
logger := logger.FromContext(tc.ctx)
72+
log := logger.FromContext(tc.ctx)
7373

74-
if tc.expected && logger == nil {
75-
t.Errorf("expected: %v, got: %v", tc.expected, logger)
74+
if tc.expected && log == nil {
75+
t.Errorf("expected: %v, got: %v", tc.expected, log)
7676
}
7777
})
7878
}

interanl/services/news/model.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import (
77
"time"
88
)
99

10-
type NewsPostReqBody struct {
10+
// PostReqBody - PostReqBody struct.
11+
type PostReqBody struct {
1112
Author string `json:"author"`
1213
Title string `json:"title"`
1314
Summary string `json:"summary"`
@@ -17,7 +18,8 @@ type NewsPostReqBody struct {
1718
Tags []string `json:"tags"`
1819
}
1920

20-
func (n NewsPostReqBody) Validate() (errs error) {
21+
// Validate - validate request body.
22+
func (n *PostReqBody) Validate() (errs error) {
2123
if n.Author == "" {
2224
errs = errors.Join(errs, fmt.Errorf("author is empty: %s", n.Author))
2325
}

interanl/services/news/model_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,32 @@ import (
99
func TestNewsPostBody_Validate(t *testing.T) {
1010
testCases := []struct {
1111
name string
12-
req news.NewsPostReqBody
12+
req news.PostReqBody
1313
expectedErr bool
1414
}{
1515
{
1616
name: "author empty",
17-
req: news.NewsPostReqBody{},
17+
req: news.PostReqBody{},
1818
expectedErr: true,
1919
},
2020
{
2121
name: "title empty",
22-
req: news.NewsPostReqBody{
22+
req: news.PostReqBody{
2323
Author: "test-author",
2424
},
2525
expectedErr: true,
2626
},
2727
{
2828
name: "summary invalid",
29-
req: news.NewsPostReqBody{
29+
req: news.PostReqBody{
3030
Author: "test-author",
3131
Title: "test-title",
3232
},
3333
expectedErr: true,
3434
},
3535
{
3636
name: "time invalid",
37-
req: news.NewsPostReqBody{
37+
req: news.PostReqBody{
3838
Author: "test-author",
3939
Title: "test-title",
4040
Summary: "test-summary",
@@ -44,7 +44,7 @@ func TestNewsPostBody_Validate(t *testing.T) {
4444
},
4545
{
4646
name: "source invalid",
47-
req: news.NewsPostReqBody{
47+
req: news.PostReqBody{
4848
Author: "test-author",
4949
Title: "test-title",
5050
Summary: "test-summary",
@@ -54,7 +54,7 @@ func TestNewsPostBody_Validate(t *testing.T) {
5454
},
5555
{
5656
name: "tags is empty",
57-
req: news.NewsPostReqBody{
57+
req: news.PostReqBody{
5858
Author: "test-author",
5959
Title: "test-title",
6060
Summary: "test-summary",
@@ -65,7 +65,7 @@ func TestNewsPostBody_Validate(t *testing.T) {
6565
},
6666
{
6767
name: "validate",
68-
req: news.NewsPostReqBody{
68+
req: news.PostReqBody{
6969
Author: "test-author",
7070
Title: "test-title",
7171
Summary: "test-summary",

0 commit comments

Comments
 (0)