Repository: pingcap/dumpling
Pull request #212 (2020-12-03 10:08:29)

*: integrate golangci-lint for dumpling
<!--
Thank you for contributing to Dumpling! Please read the [CONTRIBUTING](https://github.com/pingcap/dumpling/blob/master/CONTRIBUTING.md) document **BEFORE** filing this PR.

If you want to open the **Challenge Program** pull request, please use the following template:
https://raw.githubusercontent.com/pingcap/.github/master/.github/PULL_REQUEST_TEMPLATE/challenge-program.md

You can use it with query parameters: https://github.com/pingcap/dumpling/compare/master...${you branch}?template=challenge-program.md<!--
Thank you for contributing to Dumpling! Please read the [CONTRIBUTING](https://github.com/pingcap/dumpling/blob/master/CONTRIBUTING.md) document **BEFORE** filing this PR.

If you want to open the **Challenge Program** pull request, please use the following template:
https://raw.githubusercontent.com/pingcap/.github/master/.github/PULL_REQUEST_TEMPLATE/challenge-program.md

You can use it with query parameters: https://github.com/pingcap/dumpling/compare/master...${you branch}?template=challenge-program.md
-->

### What problem does this PR solve? <!--add issue link with summary if exists-->
Dumpling didn't have linter before. The code has some problems not detected before.

### What is changed and how it works?
Integrate `golangci-lint` in dumpling and and `make check` in CI.

### Check List <!--REMOVE the items that are not applicable-->

Tests <!-- At least one of them must be included. -->

 - Unit test
 - Integration test
 
### Release note

<!-- bugfixes or new feature need a release note, must in the form of a list, such as

- support -T/--tables-list argument

or if no need to be included in the release note, just add the following line

- No release note
-->
- No release note


lichunzhu: @kennytm all comments have been addressed. PTAL again.

Patch:
diff --git a/.travis.yml b/.travis.yml
index 7915ac3..2703022 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,7 @@ install:
   - sh install.sh
 
 script:
+  - make check
   - make test WITH_RACE=1
   - make integration_test
 
diff --git a/Makefile b/Makefile
index 38a312e..1492703 100644
--- a/Makefile
+++ b/Makefile
@@ -1,40 +1,118 @@
-LDFLAGS += -X "github.com/pingcap/dumpling/v4/cli.ReleaseVersion=$(shell git describe --tags --dirty="-dev")"
+PACKAGES := go list ./... | sed '/github.com\/pingcap\/dumpling\/bin/d'
+PACKAGE_DIRECTORIES := $(PACKAGES) | sed 's/github.com\/pingcap\/dumpling\/*//'
+DUMPLING_PKG := github.com/pingcap/dumpling
+CHECKER := awk '{ print } END { if (NR > 0) { exit 1 } }'
+
+LDFLAGS += -X "github.com/pingcap/dumpling/v4/cli.ReleaseVersion=$(shell git describe --tags --dirty)"
 LDFLAGS += -X "github.com/pingcap/dumpling/v4/cli.BuildTimestamp=$(shell date -u '+%Y-%m-%d %I:%M:%S')"
 LDFLAGS += -X "github.com/pingcap/dumpling/v4/cli.GitHash=$(shell git rev-parse HEAD)"
 LDFLAGS += -X "github.com/pingcap/dumpling/v4/cli.GitBranch=$(shell git rev-parse --abbrev-ref HEAD)"
 LDFLAGS += -X "github.com/pingcap/dumpling/v4/cli.GoVersion=$(shell go version)"
 
-FAILPOINT_ENABLE  := $$(find $$PWD/ -type d | grep -vE "(\.git|tools)" | xargs bin/failpoint-ctl enable)
-FAILPOINT_DISABLE := $$(find $$PWD/ -type d | grep -vE "(\.git|tools)" | xargs bin/failpoint-ctl disable)
+GOBUILD := CGO_ENABLED=0 GO111MODULE=on go build -trimpath -ldflags '$(LDFLAGS)'
+GOTEST  := CGO_ENABLED=1 GO111MODULE=on go test -ldflags '$(LDFLAGS)'
 
-GO = go
-GOLDFLAGS = -ldflags '$(LDFLAGS)'
 ifeq ("$(WITH_RACE)", "1")
-	GOLDFLAGS += -race
+	RACEFLAG = -race
 endif
 
-.PHONY: build test
+all: build check test
 
 build: bin/dumpling
 
 bin/%: cmd/%/main.go $(wildcard v4/**/*.go)
-	$(GO) build $(GOLDFLAGS) -tags codes -o $@ $<
+	$(GOBUILD) $(RACEFLAG) -tags codes -o $@ $<
 
 test: failpoint-enable
-	$(GO) list ./... | xargs $(GO) test $(GOLDFLAGS) -coverprofile=coverage.txt -covermode=atomic  ||{ $(FAILPOINT_DISABLE); exit 1; }
+	$(GOTEST) $(RACEFLAG) -tags leak ./... || ( make failpoint-disable && exit 1 )
 	@make failpoint-disable
 
 integration_test: failpoint-enable bin/dumpling
 	@make failpoint-disable
-	./tests/run.sh ||{ $(FAILPOINT_DISABLE); exit 1; }
+	./tests/run.sh
+
+tools:
+	@echo "install tools..."
+	@cd tools && make
+
+failpoint-enable: tools
+	tools/bin/failpoint-ctl enable
+
+failpoint-disable: tools
+	tools/bin/failpoint-ctl disable
+
+check:
+	@# Tidy first to avoid go.mod being affected by static and lint
+	@make tidy
+	@# Build tools for static and lint
+	@make tools static lint
+
+static: export GO111MODULE=on
+static: tools
+	@ # Not running vet and fmt through metalinter becauase it ends up looking at vendor
+	tools/bin/gofumports -w -d -format-only -local $(DUMPLING_PKG) $$($(PACKAGE_DIRECTORIES)) 2>&1 | $(CHECKER)
+	tools/bin/govet --shadow $$($(PACKAGE_DIRECTORIES)) 2>&1 | $(CHECKER)
+
+	@# why some lints are disabled?
+	@#   gochecknoglobals - disabled because we do use quite a lot of globals
+	@#          goimports - executed above already, gofumports
+	@#              gofmt - ditto
+	@#                gci - ditto
+	@#                wsl - too pedantic about the formatting
+	@#             funlen - PENDING REFACTORING
+	@#           gocognit - PENDING REFACTORING
+	@#              godox - TODO
+	@#              gomnd - too many magic numbers, and too pedantic (even 2*x got flagged...)
+	@#        testpackage - several test packages still rely on private functions
+	@#             nestif - PENDING REFACTORING
+	@#           goerr113 - it mistaken pingcap/errors with standard errors
+	@#                lll - pingcap/errors may need to write a long line
+	@#       paralleltest - no need to run test parallel
+	@#           nlreturn - no need to ensure a new line before continue or return
+	@#   exhaustivestruct - Protobuf structs have hidden fields, like "XXX_NoUnkeyedLiteral"
+	@#         exhaustive - no need to check exhaustiveness of enum switch statements
+	@#              gosec - too many false positive
+	@#          errorlint - can't detect errors.Cause
+	@#      sqlclosecheck - the rows in dumpling is created in one function but closed in other functions
+	CGO_ENABLED=0 tools/bin/golangci-lint run --enable-all --deadline 120s \
+		--disable gochecknoglobals \
+		--disable goimports \
+		--disable gofmt \
+		--disable gci \
+		--disable wsl \
+		--disable funlen \
+		--disable gocognit \
+		--disable godox \
+		--disable gomnd \
+		--disable testpackage \
+		--disable nestif \
+		--disable goerr113 \
+		--disable lll \
+		--disable paralleltest \
+		--disable nlreturn \
+		--disable exhaustivestruct \
+		--disable exhaustive \
+		--disable godot \
+		--disable gosec \
+		--disable errorlint \
+		--disable sqlclosecheck \
+		$$($(PACKAGE_DIRECTORIES))
+	# pingcap/errors APIs are mixed with multiple patterns 'pkg/errors',
+	# 'juju/errors' and 'pingcap/parser'. To avoid confusion and mistake,
+	# we only allow a subset of APIs, that's "Normalize|Annotate|Trace|Cause".
+	@# TODO: delete Errorf and New after we support standard code.
+	@# TODO: allow more APIs when we need to support "workaound".
+	grep -Rn --exclude="*_test.go" -E "(\t| )errors\.[A-Z]" cmd v4 | \
+		grep -vE "Normalize|Annotate|Trace|Cause|Errorf|New" 2>&1 | $(CHECKER)
 
-bin/failpoint-ctl: go.mod
-	$(GO) build -o $@ github.com/pingcap/failpoint/failpoint-ctl
+lint: tools
+	@echo "linting"
+	CGO_ENABLED=0 tools/bin/revive -formatter friendly -config revive.toml $$($(PACKAGES))
 
-failpoint-enable: bin/failpoint-ctl
-# Converting gofail failpoints...
-	@$(FAILPOINT_ENABLE)
+tidy:
+	@echo "go mod tidy"
+	GO111MODULE=on go mod tidy
+	cd tools && GO111MODULE=on go mod tidy
+	git diff --exit-code go.mod go.sum tools/go.mod tools/go.sum
 
-failpoint-disable: bin/failpoint-ctl
-# Restoring gofail failpoints...
-	@$(FAILPOINT_DISABLE)
+.PHONY: build test integration_test tools failpoint-enable failpoint-disable check static lint tidy
diff --git a/cmd/dumpling/main.go b/cmd/dumpling/main.go
index 7f26edc..b5dcd50 100644
--- a/cmd/dumpling/main.go
+++ b/cmd/dumpling/main.go
@@ -68,13 +68,12 @@ func main() {
 		fmt.Printf("\ncreate dumper failed: %s\n", err.Error())
 		os.Exit(1)
 	}
-	defer dumper.Close()
 	err = dumper.Dump()
+	dumper.Close()
 	if err != nil {
 		log.Error("dump failed error stack info", zap.Error(err))
 		fmt.Printf("\ndump failed: %s\n", err.Error())
 		os.Exit(1)
-	} else {
-		log.Info("dump data successfully, dumpling will exit now")
 	}
+	log.Info("dump data successfully, dumpling will exit now")
 }
diff --git a/revive.toml b/revive.toml
new file mode 100644
index 0000000..356c300
--- /dev/null
+++ b/revive.toml
@@ -0,0 +1,52 @@
+ignoreGeneratedHeader = false
+severity = "error"
+confidence = 0.8
+errorCode = 1
+warningCode = 0
+
+[rule.blank-imports]
+[rule.context-as-argument]
+[rule.dot-imports]
+[rule.error-return]
+[rule.error-strings]
+[rule.error-naming]
+[rule.exported]
+[rule.if-return]
+[rule.var-naming]
+[rule.package-comments]
+[rule.range]
+[rule.receiver-naming]
+[rule.indent-error-flow]
+[rule.empty-block]
+[rule.superfluous-else]
+[rule.modifies-parameter]
+
+# Add these once issues are fixed
+[rule.confusing-naming]
+  severity = "warning"
+[rule.confusing-results]
+  severity = "warning"
+[rule.flag-parameter]
+  severity = "warning"
+
+# Currently this makes too much noise, but should add it in
+# and perhaps ignore it in a few files
+#[rule.unused-parameter]
+#  severity = "warning"
+#[rule.deep-exit]
+#  severity = "warning"
+
+
+# Already checked by megacheck
+# [rule.unreachable-code]
+
+# Adding these will slow down the linter
+# They are already provided by megacheck
+# [rule.unexported-return]
+# [rule.time-naming]
+# [rule.errorf]
+
+# Adding these will slow down the linter
+# Not sure if they are already provided by megacheck
+# [rule.var-declaration]
+# [rule.context-keys-type]
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644
index 0000000..e660fd9
--- /dev/null
+++ b/tools/.gitignore
@@ -0,0 +1,1 @@
+bin/
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000..5a8f387
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,17 @@
+all: bin/gofumports bin/govet bin/revive bin/golangci-lint bin/failpoint-ctl
+
+bin/gofumports:
+	go build -o $@ mvdan.cc/gofumpt/gofumports
+
+bin/govet:
+	go build -o $@ github.com/dnephin/govet
+
+bin/revive:
+	go build -o $@ github.com/mgechev/revive
+
+bin/golangci-lint:
+	go build -o $@ github.com/golangci/golangci-lint/cmd/golangci-lint
+
+bin/failpoint-ctl:
+	go build -o $@ github.com/pingcap/failpoint/failpoint-ctl
+
diff --git a/tools/go.mod b/tools/go.mod
new file mode 100644
index 0000000..c3f4efd
--- /dev/null
+++ b/tools/go.mod
@@ -0,0 +1,11 @@
+module github.com/pingcap/dumpling/_tools
+
+go 1.13
+
+require (
+	github.com/dnephin/govet v0.0.0-20171012192244-4a96d43e39d3
+	github.com/golangci/golangci-lint v1.33.0
+	github.com/mgechev/revive v1.0.2
+	github.com/pingcap/failpoint v0.0.0-20200702092429-9f69995143ce
+	mvdan.cc/gofumpt v0.0.0-20201123090407-3077abae40c0
+)
diff --git a/tools/go.sum b/tools/go.sum
new file mode 100644
index 0000000..3f32c80
--- /dev/null
+++ b/tools/go.sum
@@ -0,0 +1,649 @@
+4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a h1:wFEQiK85fRsEVF0CRrPAos5LoAryUsIX1kPW/WrIqFw=
+4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5 h1:XTrzB+F8+SpRmbhAH8HLxhiiG6nYNwaBZjrFps1oWEk=
+github.com/Djarvur/go-err113 v0.0.0-20200511133814-5174e21577d5/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
+github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
+github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us=
+github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
+github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
+github.com/bombsimon/wsl/v3 v3.1.0 h1:E5SRssoBgtVFPcYWUOFJEcgaySgdtTNYzsSKDOY7ss8=
+github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
+github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/daixiang0/gci v0.2.4 h1:BUCKk5nlK2m+kRIsoj+wb/5hazHvHeZieBKWd9Afa8Q=
+github.com/daixiang0/gci v0.2.4/go.mod h1:+AV8KmHTGxxwp/pY84TLQfFKp2vuKXXJVzF3kD/hfR4=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/denis-tingajkin/go-header v0.3.1 h1:ymEpSiFjeItCy1FOP+x0M2KdCELdEAHUsNa8F+hHc6w=
+github.com/denis-tingajkin/go-header v0.3.1/go.mod h1:sq/2IxMhaZX+RRcgHfCRx/m0M5na0fBt4/CRe7Lrji0=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/dnephin/govet v0.0.0-20171012192244-4a96d43e39d3 h1:LrNBULdC8dhFb7VeeIfuLAVq2IOFtVD9zIYh838jWfM=
+github.com/dnephin/govet v0.0.0-20171012192244-4a96d43e39d3/go.mod h1:pPTX0MEEoAnfbrAGFj4nSVNhl6YbugRj6eardUZdtGo=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
+github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
+github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
+github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
+github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-critic/go-critic v0.5.2 h1:3RJdgf6u4NZUumoP8nzbqiiNT8e1tC2Oc7jlgqre/IA=
+github.com/go-critic/go-critic v0.5.2/go.mod h1:cc0+HvdE3lFpqLecgqMaJcvWWH77sLdBp+wLGPM1Yyo=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
+github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
+github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g=
+github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
+github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8=
+github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ=
+github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ=
+github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
+github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k=
+github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
+github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
+github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg=
+github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
+github.com/go-toolsmith/pkgload v1.0.0 h1:4DFWWMXVfbcN5So1sBNW9+yeiMqLFGl1wFLTL5R0Tgg=
+github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
+github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4=
+github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
+github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
+github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk=
+github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
+github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo=
+github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
+github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
+github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
+github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0=
+github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
+github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM=
+github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
+github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w=
+github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
+github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw=
+github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
+github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d h1:pXTK/gkVNs7Zyy7WKgLXmpQ5bHTrq5GDsp8R9Qs67g0=
+github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
+github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks=
+github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
+github.com/golangci/golangci-lint v1.33.0 h1:/o4OtOR3Idim4FHKBJXcy+6ZjNDm82gwK/v6+gWyH9U=
+github.com/golangci/golangci-lint v1.33.0/go.mod h1:zMnMLSCaDlrXExYsuq2LOweE9CHVqYk5jexk23UsjYM=
+github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI=
+github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
+github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA=
+github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
+github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA=
+github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
+github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk=
+github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
+github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us=
+github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
+github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg=
+github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
+github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys=
+github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/gookit/color v1.3.1/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
+github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
+github.com/gostaticanalysis/analysisutil v0.1.0 h1:E4c8Y1EQURbBEAHoXc/jBTK7Np14ArT8NPUiSFOl9yc=
+github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw=
+github.com/gostaticanalysis/comment v1.3.0 h1:wTVgynbFu8/nz6SGgywA0TcyIoAVsYc7ai/Zp5xNGlw=
+github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
+github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
+github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3 h1:7nkB9fLPMwtn/R6qfPcHileL/x9ydlhw8XyDrLI1ZXg=
+github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
+github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a h1:GmsqmapfzSJkm28dhRoHz2tLRbJmqhU86IPgBtN3mmk=
+github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s=
+github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3 h1:jNYPNLe3d8smommaoQlK7LOA5ESyUJJ+Wf79ZtA7Vp4=
+github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
+github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
+github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kunwardeep/paralleltest v1.0.2 h1:/jJRv0TiqPoEy/Y8dQxCFJhD56uS/pnvtatgTZBHokU=
+github.com/kunwardeep/paralleltest v1.0.2/go.mod h1:ZPqNm1fVHPllh5LPVujzbVz1JN2GhLxSfY+oqUsvG30=
+github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M=
+github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg=
+github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
+github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/maratori/testpackage v1.0.1 h1:QtJ5ZjqapShm0w5DosRjg0PRlSdAdlx+W6cCKoALdbQ=
+github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU=
+github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE=
+github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
+github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
+github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
+github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mbilski/exhaustivestruct v1.1.0 h1:4ykwscnAFeHJruT+EY3M3vdeP8uXMh0VV2E61iR7XD8=
+github.com/mbilski/exhaustivestruct v1.1.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc=
+github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 h1:QASJXOGm2RZ5Ardbc86qNFvby9AqkLDibfChMtAg5QM=
+github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg=
+github.com/mgechev/revive v1.0.2 h1:v0NxxQ7fSFz/u1NQydPo6EGdq7va0J1BtsZmae6kzUg=
+github.com/mgechev/revive v1.0.2/go.mod h1:rb0dQy1LVAxW9SWy5R3LPUjevzUbUS316U5MFySA2lo=
+github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
+github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4=
+github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k=
+github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nakabonne/nestif v0.3.0 h1:+yOViDGhg8ygGrmII72nV9B/zGxY188TYpfolntsaPw=
+github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c=
+github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
+github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nishanths/exhaustive v0.1.0 h1:kVlMw8h2LHPMGUVqUj6230oQjjTMFjwcZrnkhXzFfl8=
+github.com/nishanths/exhaustive v0.1.0/go.mod h1:S1j9110vxV1ECdCudXRkeMnFQ/DQk9ajLT0Uf2MYZQQ=
+github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
+github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
+github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
+github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA=
+github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw=
+github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 h1:USx2/E1bX46VG32FIw034Au6seQ2fY9NEILmNh/UlQg=
+github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8/go.mod h1:B1+S9LNcuMyLH/4HMTViQOJevkGiik3wW2AN9zb2fNQ=
+github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
+github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pingcap/failpoint v0.0.0-20200702092429-9f69995143ce h1:Y1kCxlCtlPTMtVcOkjUcuQKh+YrluSo7+7YMCQSzy30=
+github.com/pingcap/failpoint v0.0.0-20200702092429-9f69995143ce/go.mod h1:w4PEZ5y16LeofeeGwdgZB4ddv9bLyDuIX+ljstgKZyk=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/polyfloyd/go-errorlint v0.0.0-20201006195004-351e25ade6e3 h1:Amgs0nbayPhBNGh1qPqqr2e7B2qNAcBgRjnBH/lmn8k=
+github.com/polyfloyd/go-errorlint v0.0.0-20201006195004-351e25ade6e3/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
+github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
+github.com/quasilyte/go-ruleguard v0.2.0 h1:UOVMyH2EKkxIfzrULvA9n/tO+HtEhqD9mrLSWMr5FwU=
+github.com/quasilyte/go-ruleguard v0.2.0/go.mod h1:2RT/tf0Ce0UDj5y243iWKosQogJd8+1G3Rs2fxmlYnw=
+github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY=
+github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.6.2 h1:aIihoIOHCiLZHxyoNQ+ABL4NKhFTgKLBdMLyEAh98m0=
+github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/ryancurrah/gomodguard v1.1.0 h1:DWbye9KyMgytn8uYpuHkwf0RHqAYO6Ay/D0TbCpPtVU=
+github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUccKSJBU0UMXJFVM=
+github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw=
+github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/securego/gosec/v2 v2.5.0 h1:kjfXLeKdk98gBe2+eYRFMpC4+mxmQQtbidpiiOQ69Qc=
+github.com/securego/gosec/v2 v2.5.0/go.mod h1:L/CDXVntIff5ypVHIkqPXbtRpJiNCh6c6Amn68jXDjo=
+github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44 h1:tB9NOR21++IjLyVx3/PCPhWMwqGNCMQEH96A6dMZ/gc=
+github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
+github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU=
+github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs=
+github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
+github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
+github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
+github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY=
+github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI=
+github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ=
+github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
+github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
+github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
+github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
+github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
+github.com/ssgreg/nlreturn/v2 v2.1.0 h1:6/s4Rc49L6Uo6RLjhWZGBpWWjfzk2yrf1nIW8m4wgVA=
+github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
+github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2 h1:Xr9gkxfOP0KQWXKNqmwe8vEeSUiUj4Rlee9CMVX2ZUQ=
+github.com/tdakkota/asciicheck v0.0.0-20200416190851-d7f85be797a2/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM=
+github.com/tetafro/godot v1.3.0 h1:rKXb6aAz2AnwS98jYlU3snCFFXnIInQdaGiftNwpj+k=
+github.com/tetafro/godot v1.3.0/go.mod h1:/7NLHhv08H1+8DNj0MElpAACw1ajsCuf3TKNQxA5S+0=
+github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q=
+github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/tomarrell/wrapcheck v0.0.0-20200807122107-df9e8bcb914d h1:3EZyvNUMsGD1QA8cu0STNn1L7I77rvhf2IhOcHYQhSw=
+github.com/tomarrell/wrapcheck v0.0.0-20200807122107-df9e8bcb914d/go.mod h1:yiFB6fFoV7saXirUGfuK+cPtUh4NX/Hf5y2WC2lehu0=
+github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa h1:RC4maTWLKKwb7p1cnoygsbKIgNlJqSYBeAFON3Ar8As=
+github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
+github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA=
+github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
+github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg=
+github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
+github.com/uudashr/gocognit v1.0.1 h1:MoG2fZ0b/Eo7NXoIwCVFLG5JED3qgQz5/NEE+rOsjPs=
+github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
+github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM=
+golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
+golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
+golang.org/x/tools v0.0.0-20201007032633-0806396f153e/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
+golang.org/x/tools v0.0.0-20201011145850-ed2f50202694/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
+golang.org/x/tools v0.0.0-20201013201025-64a9e34f3752/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
+golang.org/x/tools v0.0.0-20201121010211-780cb80bd7fb h1:z5+u0pkAUPUWd3taoTialQ2JAMo4Wo1Z3L25U4ZV9r0=
+golang.org/x/tools v0.0.0-20201121010211-780cb80bd7fb/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
+gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.6 h1:W18jzjh8mfPez+AwGLxmOImucz/IFjpNlrKVnaj2YVc=
+honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY=
+k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
+mvdan.cc/gofumpt v0.0.0-20200802201014-ab5a8192947d/go.mod h1:bzrjFmaD6+xqohD3KYP0H2FEuxknnBmyyOxdhLdaIws=
+mvdan.cc/gofumpt v0.0.0-20201123090407-3077abae40c0 h1:kQ90sSvDP83HYKOsmrpDtcKkbWPjWYL2LmSCz1oE6vE=
+mvdan.cc/gofumpt v0.0.0-20201123090407-3077abae40c0/go.mod h1:E4LOcu9JQEtnYXtB1Y51drqh2Qr2Ngk9J3YrRCwcbd0=
+mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=
+mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
+mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
+mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
+mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7 h1:kAREL6MPwpsk1/PQPFD3Eg7WAQR5mPTWZJaBiG5LDbY=
+mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/tools/go_mod_guard.go b/tools/go_mod_guard.go
new file mode 100644
index 0000000..1d5a43f
--- /dev/null
+++ b/tools/go_mod_guard.go
@@ -0,0 +1,20 @@
+package tools
+
+// This file ensures `go mod tidy` will not delete entries to all tools.
+
+import (
+	// golangci-lint is a package-based linter
+	_ "github.com/golangci/golangci-lint/pkg/commands"
+
+	// revive is a file-based linter
+	_ "github.com/mgechev/revive/lint"
+
+	// govet checks for code correctness
+	_ "github.com/dnephin/govet"
+
+	// failpoint enables manual 'failure' of some execution points.
+	_ "github.com/pingcap/failpoint"
+
+	// A stricter gofmt
+	_ "mvdan.cc/gofumpt/gofumports"
+)
diff --git a/v4/export/block_allow_list.go b/v4/export/block_allow_list.go
index 1821016..dbc3318 100644
--- a/v4/export/block_allow_list.go
+++ b/v4/export/block_allow_list.go
@@ -3,8 +3,9 @@
 package export
 
 import (
-	"github.com/pingcap/dumpling/v4/log"
 	"go.uber.org/zap"
+
+	"github.com/pingcap/dumpling/v4/log"
 )
 
 func filterTables(conf *Config) {
diff --git a/v4/export/config.go b/v4/export/config.go
index d77d932..e7af50c 100644
--- a/v4/export/config.go
+++ b/v4/export/config.go
@@ -54,7 +54,7 @@ const (
 	flagNoSchemas                = "no-schemas"
 	flagNoData                   = "no-data"
 	flagCsvNullValue             = "csv-null-value"
-	flagSql                      = "sql"
+	flagSQL                      = "sql"
 	flagFilter                   = "filter"
 	flagCaseSensitive            = "case-sensitive"
 	flagDumpEmptyDatabase        = "dump-empty-database"
@@ -71,67 +71,68 @@ const (
 	flagTransactionalConsistency = "transactional-consistency"
 	flagCompress                 = "compress"
 
+	// FlagHelp represents the help flag
 	FlagHelp = "help"
 )
 
+// Config is the dump config for dumpling
 type Config struct {
 	storage.BackendOptions
 
-	Databases               []string
-	Host                    string
-	User                    string
-	Port                    int
-	Password                string `json:"-"`
-	AllowCleartextPasswords bool
-	Security                struct {
+	AllowCleartextPasswords  bool
+	SortByPk                 bool
+	NoViews                  bool
+	NoHeader                 bool
+	NoSchemas                bool
+	NoData                   bool
+	CompleteInsert           bool
+	TransactionalConsistency bool
+	EscapeBackslash          bool
+	DumpEmptyDatabase        bool
+	PosAfterConnect          bool
+	CompressType             storage.CompressType
+
+	Host     string
+	Port     int
+	Threads  int
+	User     string
+	Password string `json:"-"`
+	Security struct {
 		CAPath   string
 		CertPath string
 		KeyPath  string
 	}
 
-	Threads int
-
-	LogLevel  string
-	LogFile   string
-	LogFormat string
-	Logger    *zap.Logger `json:"-"`
-
-	FileSize      uint64
-	StatementSize uint64
+	LogLevel      string
+	LogFile       string
+	LogFormat     string
 	OutputDirPath string
-	ServerInfo    ServerInfo
-	SortByPk      bool
-	Tables        DatabaseTables
 	StatusAddr    string
 	Snapshot      string
 	Consistency   string
-	NoViews       bool
-	NoHeader      bool
-	NoSchemas     bool
-	NoData        bool
 	CsvNullValue  string
-	Sql           string
+	SQL           string
 	CsvSeparator  string
 	CsvDelimiter  string
-	ReadTimeout   time.Duration
-	CompressType  storage.CompressType
-
-	TableFilter              filter.Filter `json:"-"`
-	Rows                     uint64
-	Where                    string
-	FileType                 string
-	CompleteInsert           bool
-	TransactionalConsistency bool
-	EscapeBackslash          bool
-	DumpEmptyDatabase        bool
-	OutputFileTemplate       *template.Template `json:"-"`
-	TiDBMemQuotaQuery        uint64
-	SessionParams            map[string]interface{}
-
-	PosAfterConnect bool
-	Labels          prometheus.Labels `json:"-"`
+	Databases     []string
+
+	TableFilter        filter.Filter `json:"-"`
+	Where              string
+	FileType           string
+	ServerInfo         ServerInfo
+	Logger             *zap.Logger        `json:"-"`
+	OutputFileTemplate *template.Template `json:"-"`
+	Rows               uint64
+	ReadTimeout        time.Duration
+	TiDBMemQuotaQuery  uint64
+	FileSize           uint64
+	StatementSize      uint64
+	SessionParams      map[string]interface{}
+	Labels             prometheus.Labels `json:"-"`
+	Tables             DatabaseTables
 }
 
+// DefaultConfig returns the default export Config for dumpling
 func DefaultConfig() *Config {
 	allFilter, _ := filter.Parse([]string{"*.*"})
 	return &Config{
@@ -154,12 +155,12 @@ func DefaultConfig() *Config {
 		NoViews:            true,
 		Rows:               UnspecifiedSize,
 		Where:              "",
-		FileType:           "sql",
+		FileType:           FileFormatSQLTextString,
 		NoHeader:           false,
 		NoSchemas:          false,
 		NoData:             false,
 		CsvNullValue:       "\\N",
-		Sql:                "",
+		SQL:                "",
 		TableFilter:        allFilter,
 		DumpEmptyDatabase:  true,
 		SessionParams:      make(map[string]interface{}),
@@ -168,8 +169,9 @@ func DefaultConfig() *Config {
 	}
 }
 
-func (config *Config) String() string {
-	cfg, err := json.Marshal(config)
+// String returns dumpling's config in json format
+func (conf *Config) String() string {
+	cfg, err := json.Marshal(conf)
 	if err != nil {
 		log.Error("marshal config to json", zap.Error(err))
 	}
@@ -195,6 +197,7 @@ func timestampDirName() string {
 	return fmt.Sprintf("./export-%s", time.Now().Format(time.RFC3339))
 }
 
+// DefineFlags defines flags of dumpling's configuration
 func (conf *Config) DefineFlags(flags *pflag.FlagSet) {
 	storage.DefineFlags(flags)
 	flags.StringSliceP(flagDatabase, "B", nil, "Databases to dump")
@@ -218,12 +221,12 @@ func (conf *Config) DefineFlags(flags *pflag.FlagSet) {
 	flags.Uint64P(flagRows, "r", UnspecifiedSize, "Split table into chunks of this many rows, default unlimited")
 	flags.String(flagWhere, "", "Dump only selected records")
 	flags.Bool(flagEscapeBackslash, true, "use backslash to escape special characters")
-	flags.String(flagFiletype, "sql", "The type of export file (sql/csv)")
+	flags.String(flagFiletype, FileFormatSQLTextString, "The type of export file (sql/csv)")
 	flags.Bool(flagNoHeader, false, "whether not to dump CSV table header")
 	flags.BoolP(flagNoSchemas, "m", false, "Do not dump table schemas with the data")
 	flags.BoolP(flagNoData, "d", false, "Do not dump table data")
 	flags.String(flagCsvNullValue, "\\N", "The null value used when export to csv")
-	flags.StringP(flagSql, "S", "", "Dump data with given sql. This argument doesn't support concurrent dump")
+	flags.StringP(flagSQL, "S", "", "Dump data with given sql. This argument doesn't support concurrent dump")
 	flags.StringSliceP(flagFilter, "f", []string{"*.*", DefaultTableFilter}, "filter to select which tables to dump")
 	flags.Bool(flagCaseSensitive, false, "whether the filter should be case-sensitive")
 	flags.Bool(flagDumpEmptyDatabase, true, "whether to dump empty database")
@@ -238,12 +241,13 @@ func (conf *Config) DefineFlags(flags *pflag.FlagSet) {
 	flags.StringToString(flagParams, nil, `Extra session variables used while dumping, accepted format: --params "character_set_client=latin1,character_set_connection=latin1"`)
 	flags.Bool(FlagHelp, false, "Print help message and quit")
 	flags.Duration(flagReadTimeout, 15*time.Minute, "I/O read timeout for db connection.")
-	flags.MarkHidden(flagReadTimeout)
+	_ = flags.MarkHidden(flagReadTimeout)
 	flags.Bool(flagTransactionalConsistency, true, "Only support transactional consistency")
 	flags.StringP(flagCompress, "c", "", "Compress output file type, support 'gzip', 'no-compression' now")
 }
 
-// GetDSN generates DSN from Config
+// ParseFromFlags parses dumpling's export.Config from flags
+// nolint: gocyclo
 func (conf *Config) ParseFromFlags(flags *pflag.FlagSet) error {
 	var err error
 	conf.Databases, err = flags.GetStringSlice(flagDatabase)
@@ -342,7 +346,7 @@ func (conf *Config) ParseFromFlags(flags *pflag.FlagSet) error {
 	if err != nil {
 		return errors.Trace(err)
 	}
-	conf.Sql, err = flags.GetString(flagSql)
+	conf.SQL, err = flags.GetString(flagSQL)
 	if err != nil {
 		return errors.Trace(err)
 	}
@@ -434,7 +438,7 @@ func (conf *Config) ParseFromFlags(flags *pflag.FlagSet) error {
 		return errors.Trace(err)
 	}
 
-	if outputFilenameFormat == "" && conf.Sql != "" {
+	if outputFilenameFormat == "" && conf.SQL != "" {
 		outputFilenameFormat = DefaultAnonymousOutputFileTemplateText
 	}
 	tmpl, err := ParseOutputFileTemplate(outputFilenameFormat)
@@ -464,6 +468,7 @@ func (conf *Config) ParseFromFlags(flags *pflag.FlagSet) error {
 	return nil
 }
 
+// ParseFileSize parses file size from tables-list and filter arguments
 func ParseFileSize(fileSizeStr string) (uint64, error) {
 	if len(fileSizeStr) == 0 {
 		return UnspecifiedSize, nil
@@ -476,6 +481,7 @@ func ParseFileSize(fileSizeStr string) (uint64, error) {
 	return 0, errors.Errorf("failed to parse filesize (-F '%s')", fileSizeStr)
 }
 
+// ParseTableFilter parses table filter from tables-list and filter arguments
 func ParseTableFilter(tablesList, filters []string) (filter.Filter, error) {
 	if len(tablesList) == 0 {
 		return filter.Parse(filters)
@@ -498,6 +504,7 @@ func ParseTableFilter(tablesList, filters []string) (filter.Filter, error) {
 	return filter.NewTablesFilter(tableNames...), nil
 }
 
+// ParseCompressType parses compressType string to storage.CompressType
 func ParseCompressType(compressType string) (storage.CompressType, error) {
 	switch compressType {
 	case "", "no-compression":
@@ -509,16 +516,16 @@ func ParseCompressType(compressType string) (storage.CompressType, error) {
 	}
 }
 
-func (config *Config) createExternalStorage(ctx context.Context) (storage.ExternalStorage, error) {
-	b, err := storage.ParseBackend(config.OutputDirPath, &config.BackendOptions)
+func (conf *Config) createExternalStorage(ctx context.Context) (storage.ExternalStorage, error) {
+	b, err := storage.ParseBackend(conf.OutputDirPath, &conf.BackendOptions)
 	if err != nil {
-		return nil, err
+		return nil, errors.Trace(err)
 	}
 	httpClient := http.DefaultClient
 	httpClient.Timeout = 30 * time.Second
 	maxIdleConnsPerHost := http.DefaultMaxIdleConnsPerHost
-	if config.Threads > maxIdleConnsPerHost {
-		maxIdleConnsPerHost = config.Threads
+	if conf.Threads > maxIdleConnsPerHost {
+		maxIdleConnsPerHost = conf.Threads
 	}
 	transport := http.DefaultTransport.(*http.Transport).Clone()
 	transport.MaxIdleConnsPerHost = maxIdleConnsPerHost
@@ -530,11 +537,16 @@ func (config *Config) createExternalStorage(ctx context.Context) (storage.Extern
 }
 
 const (
-	UnspecifiedSize          = 0
+	// UnspecifiedSize means the filesize/statement-size is unspecified
+	UnspecifiedSize = 0
+	// DefaultTiDBMemQuotaQuery is the default TiDBMemQuotaQuery size for TiDB
 	DefaultTiDBMemQuotaQuery = 32 << 30
-	DefaultStatementSize     = 1000000
-	TiDBMemQuotaQueryName    = "tidb_mem_quota_query"
-	DefaultTableFilter       = "!/^(mysql|sys|INFORMATION_SCHEMA|PERFORMANCE_SCHEMA|METRICS_SCHEMA|INSPECTION_SCHEMA)$/.*"
+	// DefaultStatementSize is the default statement size
+	DefaultStatementSize = 1000000
+	// TiDBMemQuotaQueryName is the session variable TiDBMemQuotaQuery's name in TiDB
+	TiDBMemQuotaQueryName = "tidb_mem_quota_query"
+	// DefaultTableFilter is the default exclude table filter. It will exclude all system databases
+	DefaultTableFilter = "!/^(mysql|sys|INFORMATION_SCHEMA|PERFORMANCE_SCHEMA|METRICS_SCHEMA|INSPECTION_SCHEMA)$/.*"
 
 	defaultDumpThreads         = 128
 	defaultDumpGCSafePointTTL  = 5 * 60
@@ -547,30 +559,36 @@ var (
 	tableSampleVersion = semver.New("5.0.0")
 )
 
+// ServerInfo is the combination of ServerType and ServerInfo
 type ServerInfo struct {
 	ServerType    ServerType
 	ServerVersion *semver.Version
 }
 
+// ServerInfoUnknown is the unknown database type to dumpling
 var ServerInfoUnknown = ServerInfo{
 	ServerType:    ServerTypeUnknown,
 	ServerVersion: nil,
 }
 
-var versionRegex = regexp.MustCompile(`^\d+\.\d+\.\d+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?`)
-var tidbVersionRegex = regexp.MustCompile(`-[v]?\d+\.\d+\.\d+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?`)
+var (
+	versionRegex     = regexp.MustCompile(`^\d+\.\d+\.\d+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?`)
+	tidbVersionRegex = regexp.MustCompile(`-[v]?\d+\.\d+\.\d+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?`)
+)
 
+// ParseServerInfo parses exported server type and version info from version string
 func ParseServerInfo(src string) ServerInfo {
 	log.Debug("parse server info", zap.String("server info string", src))
 	lowerCase := strings.ToLower(src)
 	serverInfo := ServerInfo{}
-	if strings.Contains(lowerCase, "tidb") {
+	switch {
+	case strings.Contains(lowerCase, "tidb"):
 		serverInfo.ServerType = ServerTypeTiDB
-	} else if strings.Contains(lowerCase, "mariadb") {
+	case strings.Contains(lowerCase, "mariadb"):
 		serverInfo.ServerType = ServerTypeMariaDB
-	} else if versionRegex.MatchString(lowerCase) {
+	case versionRegex.MatchString(lowerCase):
 		serverInfo.ServerType = ServerTypeMySQL
-	} else {
+	default:
 		serverInfo.ServerType = ServerTypeUnknown
 	}
 
@@ -598,8 +616,10 @@ func ParseServerInfo(src string) ServerInfo {
 	return serverInfo
 }
 
+// ServerType represents the type of database to export
 type ServerType int8
 
+// String implements Stringer.String
 func (s ServerType) String() string {
 	if s >= ServerTypeAll {
 		return ""
@@ -608,22 +628,24 @@ func (s ServerType) String() string {
 }
 
 const (
+	// ServerTypeUnknown represents unknown server type
 	ServerTypeUnknown = iota
+	// ServerTypeMySQL represents MySQL server type
 	ServerTypeMySQL
+	// ServerTypeMariaDB represents MariaDB server type
 	ServerTypeMariaDB
+	// ServerTypeTiDB represents TiDB server type
 	ServerTypeTiDB
 
+	// ServerTypeAll represents All server types
 	ServerTypeAll
 )
 
-var serverTypeString []string
-
-func init() {
-	serverTypeString = make([]string, ServerTypeAll)
-	serverTypeString[ServerTypeUnknown] = "Unknown"
-	serverTypeString[ServerTypeMySQL] = "MySQL"
-	serverTypeString[ServerTypeMariaDB] = "MariaDB"
-	serverTypeString[ServerTypeTiDB] = "TiDB"
+var serverTypeString = []string{
+	ServerTypeUnknown: "Unknown",
+	ServerTypeMySQL:   "MySQL",
+	ServerTypeMariaDB: "MariaDB",
+	ServerTypeTiDB:    "TiDB",
 }
 
 func adjustConfig(conf *Config, fns ...func(*Config) error) error {
@@ -646,7 +668,7 @@ func initLogger(conf *Config) error {
 			Format: conf.LogFormat,
 		})
 		if err != nil {
-			return err
+			return errors.Trace(err)
 		}
 	}
 	return nil
@@ -656,18 +678,18 @@ func registerTLSConfig(conf *Config) error {
 	if len(conf.Security.CAPath) > 0 {
 		tlsConfig, err := utils.ToTLSConfig(conf.Security.CAPath, conf.Security.CertPath, conf.Security.KeyPath)
 		if err != nil {
-			return err
+			return errors.Trace(err)
 		}
 		err = mysql.RegisterTLSConfig("dumpling-tls-target", tlsConfig)
 		if err != nil {
-			return err
+			return errors.Trace(err)
 		}
 	}
 	return nil
 }
 
 func validateSpecifiedSQL(conf *Config) error {
-	if conf.Sql != "" && conf.Where != "" {
+	if conf.SQL != "" && conf.Where != "" {
 		return errors.New("can't specify both --sql and --where at the same time. Please try to combine them into --sql")
 	}
 	return nil
@@ -676,7 +698,7 @@ func validateSpecifiedSQL(conf *Config) error {
 func validateFileFormat(conf *Config) error {
 	conf.FileType = strings.ToLower(conf.FileType)
 	switch conf.FileType {
-	case "sql", "csv":
+	case FileFormatSQLTextString, FileFormatCSVString:
 		return nil
 	}
 	return errors.Errorf("unknown config.FileType '%s'", conf.FileType)
diff --git a/v4/export/connectionsPool.go b/v4/export/connectionsPool.go
deleted file mode 100644
index 7a65284..0000000
--- a/v4/export/connectionsPool.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0.
-
-package export
-
-import (
-	"context"
-	"database/sql"
-)
-
-type connectionsPool struct {
-	conns        chan *sql.Conn
-	createdConns []*sql.Conn
-}
-
-func newConnectionsPool(ctx context.Context, n int, pool *sql.DB) (*connectionsPool, error) {
-	connectPool := &connectionsPool{
-		conns:        make(chan *sql.Conn, n),
-		createdConns: make([]*sql.Conn, 0, n+1),
-	}
-	for i := 0; i < n+1; i++ {
-		conn, err := createConnWithConsistency(ctx, pool)
-		if err != nil {
-			connectPool.Close()
-			return connectPool, err
-		}
-		if i != n {
-			connectPool.releaseConn(conn)
-		}
-		connectPool.createdConns = append(connectPool.createdConns, conn)
-	}
-	return connectPool, nil
-}
-
-func (r *connectionsPool) getConn() *sql.Conn {
-	return <-r.conns
-}
-
-func (r *connectionsPool) extraConn() *sql.Conn {
-	return r.createdConns[len(r.createdConns)-1]
-}
-
-func (r *connectionsPool) Close() error {
-	var err error
-	for _, conn := range r.createdConns {
-		err2 := conn.Close()
-		if err2 != nil {
-			err = err2
-		}
-	}
-	return err
-}
-
-func (r *connectionsPool) releaseConn(conn *sql.Conn) {
-	select {
-	case r.conns <- conn:
-	default:
-		panic("put a redundant conn")
-	}
-}
diff --git a/v4/export/consistency.go b/v4/export/consistency.go
index 9cd37b0..d3504bc 100644
--- a/v4/export/consistency.go
+++ b/v4/export/consistency.go
@@ -17,10 +17,11 @@ const (
 	consistencyTypeNone     = "none"
 )
 
+// NewConsistencyController returns a new consistency controller
 func NewConsistencyController(ctx context.Context, conf *Config, session *sql.DB) (ConsistencyController, error) {
 	conn, err := session.Conn(ctx)
 	if err != nil {
-		return nil, err
+		return nil, errors.Trace(err)
 	}
 	switch conf.Consistency {
 	case consistencyTypeFlush:
@@ -45,31 +46,38 @@ func NewConsistencyController(ctx context.Context, conf *Config, session *sql.DB
 	}
 }
 
+// ConsistencyController is the interface that controls the consistency of exporting progress
 type ConsistencyController interface {
 	Setup(context.Context) error
 	TearDown(context.Context) error
 	PingContext(context.Context) error
 }
 
+// ConsistencyNone dumps without adding locks, which cannot guarantee consistency
 type ConsistencyNone struct{}
 
+// Setup implements ConsistencyController.Setup
 func (c *ConsistencyNone) Setup(_ context.Context) error {
 	return nil
 }
 
+// TearDown implements ConsistencyController.TearDown
 func (c *ConsistencyNone) TearDown(_ context.Context) error {
 	return nil
 }
 
+// PingContext implements ConsistencyController.PingContext
 func (c *ConsistencyNone) PingContext(_ context.Context) error {
 	return nil
 }
 
+// ConsistencyFlushTableWithReadLock uses FlushTableWithReadLock before the dump
 type ConsistencyFlushTableWithReadLock struct {
 	serverType ServerType
 	conn       *sql.Conn
 }
 
+// Setup implements ConsistencyController.Setup
 func (c *ConsistencyFlushTableWithReadLock) Setup(ctx context.Context) error {
 	if c.serverType == ServerTypeTiDB {
 		return errors.New("'flush table with read lock' cannot be used to ensure the consistency in TiDB")
@@ -77,6 +85,7 @@ func (c *ConsistencyFlushTableWithReadLock) Setup(ctx context.Context) error {
 	return FlushTableWithReadLock(ctx, c.conn)
 }
 
+// TearDown implements ConsistencyController.TearDown
 func (c *ConsistencyFlushTableWithReadLock) TearDown(ctx context.Context) error {
 	if c.conn == nil {
 		return nil
@@ -88,18 +97,21 @@ func (c *ConsistencyFlushTableWithReadLock) TearDown(ctx context.Context) error
 	return UnlockTables(ctx, c.conn)
 }
 
+// PingContext implements ConsistencyController.PingContext
 func (c *ConsistencyFlushTableWithReadLock) PingContext(ctx context.Context) error {
 	if c.conn == nil {
-		return errors.New("consistency connection has already been closed!")
+		return errors.New("consistency connection has already been closed")
 	}
 	return c.conn.PingContext(ctx)
 }
 
+// ConsistencyLockDumpingTables execute lock tables read on all tables before dump
 type ConsistencyLockDumpingTables struct {
 	conn      *sql.Conn
 	allTables DatabaseTables
 }
 
+// Setup implements ConsistencyController.Setup
 func (c *ConsistencyLockDumpingTables) Setup(ctx context.Context) error {
 	for dbName, tables := range c.allTables {
 		for _, table := range tables {
@@ -112,6 +124,7 @@ func (c *ConsistencyLockDumpingTables) Setup(ctx context.Context) error {
 	return nil
 }
 
+// TearDown implements ConsistencyController.TearDown
 func (c *ConsistencyLockDumpingTables) TearDown(ctx context.Context) error {
 	if c.conn == nil {
 		return nil
@@ -123,9 +136,10 @@ func (c *ConsistencyLockDumpingTables) TearDown(ctx context.Context) error {
 	return UnlockTables(ctx, c.conn)
 }
 
+// PingContext implements ConsistencyController.PingContext
 func (c *ConsistencyLockDumpingTables) PingContext(ctx context.Context) error {
 	if c.conn == nil {
-		return errors.New("consistency connection has already been closed!")
+		return errors.New("consistency connection has already been closed")
 	}
 	return c.conn.PingContext(ctx)
 }
diff --git a/v4/export/dump.go b/v4/export/dump.go
index fb8c0eb..8ce03e7 100755
--- a/v4/export/dump.go
+++ b/v4/export/dump.go
@@ -13,6 +13,7 @@ import (
 
 	"github.com/pingcap/dumpling/v4/log"
 
+	// import mysql driver
 	_ "github.com/go-sql-driver/mysql"
 	"github.com/pingcap/br/pkg/storage"
 	"github.com/pingcap/br/pkg/summary"
@@ -23,6 +24,7 @@ import (
 	"golang.org/x/sync/errgroup"
 )
 
+// Dumper is the dump progress structure
 type Dumper struct {
 	ctx       context.Context
 	conf      *Config
@@ -34,6 +36,7 @@ type Dumper struct {
 	tidbPDClientForGC pd.Client
 }
 
+// NewDumper returns a new Dumper
 func NewDumper(ctx context.Context, conf *Config) (*Dumper, error) {
 	ctx, cancelFn := context.WithCancel(ctx)
 	d := &Dumper{
@@ -51,7 +54,7 @@ func NewDumper(ctx context.Context, conf *Config) (*Dumper, error) {
 	}
 	err = runSteps(d,
 		createExternalStore,
-		startHttpService,
+		startHTTPService,
 		openSQLDB,
 		detectServerInfo,
 		resolveAutoConsistency,
@@ -64,11 +67,19 @@ func NewDumper(ctx context.Context, conf *Config) (*Dumper, error) {
 	return d, err
 }
 
-func (d *Dumper) Dump() (err error) {
+// Dump dumps table from database
+// nolint: gocyclo
+func (d *Dumper) Dump() (dumpErr error) {
+	initColTypeRowReceiverMap()
+	var (
+		conn    *sql.Conn
+		err     error
+		conCtrl ConsistencyController
+	)
 	ctx, conf, pool := d.ctx, d.conf, d.dbHandle
 	m := newGlobalMetadata(d.extStore, conf.Snapshot)
 	defer func() {
-		if err == nil {
+		if dumpErr == nil {
 			_ = m.writeGlobalMetaData(ctx)
 		}
 	}()
@@ -76,7 +87,7 @@ func (d *Dumper) Dump() (err error) {
 	// for consistency lock, we should lock tables at first to get the tables we want to lock & dump
 	// for consistency lock, record meta pos before lock tables because other tables may still be modified while locking tables
 	if conf.Consistency == consistencyTypeLock {
-		conn, err := createConnWithConsistency(ctx, pool)
+		conn, err = createConnWithConsistency(ctx, pool)
 		if err != nil {
 			return errors.Trace(err)
 		}
@@ -92,20 +103,25 @@ func (d *Dumper) Dump() (err error) {
 		conn.Close()
 	}
 
-	conCtrl, err := NewConsistencyController(ctx, conf, pool)
+	conCtrl, err = NewConsistencyController(ctx, conf, pool)
 	if err != nil {
 		return err
 	}
 	if err = conCtrl.Setup(ctx); err != nil {
-		return err
+		return errors.Trace(err)
 	}
 	// To avoid lock is not released
-	defer conCtrl.TearDown(ctx)
+	defer func() {
+		err = conCtrl.TearDown(ctx)
+		if err != nil {
+			log.Error("fail to tear down consistency controller", zap.Error(err))
+		}
+	}()
 
 	// for other consistencies, we should get table list after consistency is set up and GlobalMetaData is cached
 	// for other consistencies, record snapshot after whole tables are locked. The recorded meta info is exactly the locked snapshot.
 	if conf.Consistency != consistencyTypeLock {
-		conn, err := pool.Conn(ctx)
+		conn, err = pool.Conn(ctx)
 		if err != nil {
 			return errors.Trace(err)
 		}
@@ -139,22 +155,22 @@ func (d *Dumper) Dump() (err error) {
 	failpoint.Inject("ConsistencyCheck", nil)
 	rebuildConn := func(conn *sql.Conn) (*sql.Conn, error) {
 		// make sure that the lock connection is still alive
-		err := conCtrl.PingContext(ctx)
-		if err != nil {
-			return conn, err
+		err1 := conCtrl.PingContext(ctx)
+		if err1 != nil {
+			return conn, errors.Trace(err1)
 		}
 		// give up the last broken connection
 		conn.Close()
-		newConn, err := createConnWithConsistency(ctx, pool)
-		if err != nil {
-			return conn, err
+		newConn, err1 := createConnWithConsistency(ctx, pool)
+		if err1 != nil {
+			return conn, errors.Trace(err1)
 		}
 		conn = newConn
 		// renew the master status after connection. dm can't close safe-mode until dm reaches current pos
 		if conf.PosAfterConnect {
-			err = m.recordGlobalMetaData(conn, conf.ServerInfo.ServerType, true)
-			if err != nil {
-				return conn, err
+			err1 = m.recordGlobalMetaData(conn, conf.ServerInfo.ServerType, true)
+			if err1 != nil {
+				return conn, errors.Trace(err1)
 			}
 		}
 		return conn, nil
@@ -173,7 +189,7 @@ func (d *Dumper) Dump() (err error) {
 			log.Info("All the dumping transactions have started. Start to unlock tables")
 		}
 		if err = conCtrl.TearDown(ctx); err != nil {
-			return err
+			return errors.Trace(err)
 		}
 	}
 
@@ -182,19 +198,19 @@ func (d *Dumper) Dump() (err error) {
 	defer summary.Summary(summary.BackupUnit)
 
 	tableDataStartTime := time.Now()
-	if conf.Sql == "" {
+	if conf.SQL == "" {
 		if err = d.dumpDatabases(metaConn, taskChan); err != nil {
 			return err
 		}
 	} else {
-		if err = d.dumpSql(metaConn, taskChan); err != nil {
+		if err = d.dumpSQL(metaConn, taskChan); err != nil {
 			return err
 		}
 	}
 	close(taskChan)
 	if err := wg.Wait(); err != nil {
 		summary.CollectFailureUnit("dump table data", err)
-		return err
+		return errors.Trace(err)
 	}
 	summary.CollectSuccessUnit("dump cost", countTotalTask(writers), time.Since(tableDataStartTime))
 
@@ -212,18 +228,18 @@ func (d *Dumper) startWriters(ctx context.Context, wg *errgroup.Group, taskChan
 		if err != nil {
 			return nil, func() {}, err
 		}
-		writer := NewWriter(int64(i), ctx, conf, conn, d.extStore)
+		writer := NewWriter(ctx, int64(i), conf, conn, d.extStore)
 		writer.rebuildConnFn = rebuildConnFn
-		writer.finishTableCallBack = func(task Task) {
+		writer.setFinishTableCallBack(func(task Task) {
 			if td, ok := task.(*TaskTableData); ok {
 				log.Debug("finished dumping table data",
 					zap.String("database", td.Meta.DatabaseName()),
 					zap.String("table", td.Meta.TableName()))
 			}
-		}
-		writer.finishTaskCallBack = func(task Task) {
+		})
+		writer.setFinishTaskCallBack(func(task Task) {
 			taskChannelCapacity.With(conf.Labels).Inc()
-		}
+		})
 		wg.Go(func() error {
 			return writer.run(taskChan)
 		})
@@ -269,6 +285,7 @@ func (d *Dumper) dumpDatabases(metaConn *sql.Conn, taskChan chan<- Task) error {
 			}
 		}
 	}
+
 	return nil
 }
 
@@ -292,6 +309,7 @@ func (d *Dumper) sequentialDumpTable(conn *sql.Conn, meta TableMeta, taskChan ch
 	}
 	task := NewTaskTableData(meta, tableIR, 0, 1)
 	d.sendTaskToChan(task, taskChan)
+
 	return nil
 }
 
@@ -402,7 +420,7 @@ func (d *Dumper) selectMinAndMaxIntValue(conn *sql.Conn, db, tbl, field string)
 	err := row.Scan(&smin, &smax)
 	if err != nil {
 		log.Error("split chunks - get max min failed", zap.String("query", query), zap.Error(err))
-		return zero, zero, err
+		return zero, zero, errors.Trace(err)
 	}
 	if !smax.Valid || !smin.Valid {
 		// found no data
@@ -551,9 +569,9 @@ func dumpTableMeta(conf *Config, conn *sql.Conn, db string, table *TableInfo) (T
 	}
 	if table.Type == TableTypeView {
 		viewName := table.Name
-		createTableSQL, createViewSQL, err := ShowCreateView(conn, db, viewName)
-		if err != nil {
-			return meta, err
+		createTableSQL, createViewSQL, err1 := ShowCreateView(conn, db, viewName)
+		if err1 != nil {
+			return meta, err1
 		}
 		meta.showCreateTable = createTableSQL
 		meta.showCreateView = createViewSQL
@@ -567,9 +585,9 @@ func dumpTableMeta(conf *Config, conn *sql.Conn, db string, table *TableInfo) (T
 	return meta, nil
 }
 
-func (d *Dumper) dumpSql(metaConn *sql.Conn, taskChan chan<- Task) error {
+func (d *Dumper) dumpSQL(metaConn *sql.Conn, taskChan chan<- Task) error {
 	conf := d.conf
-	meta, tableIR, err := SelectFromSql(conf, metaConn)
+	meta, tableIR, err := SelectFromSQL(conf, metaConn)
 	if err != nil {
 		return err
 	}
@@ -590,6 +608,7 @@ func canRebuildConn(consistency string, trxConsistencyOnly bool) bool {
 	}
 }
 
+// Close closes a Dumper and stop dumping immediately
 func (d *Dumper) Close() error {
 	d.cancelCtx()
 	return d.dbHandle.Close()
@@ -610,18 +629,18 @@ func createExternalStore(d *Dumper) error {
 	ctx, conf := d.ctx, d.conf
 	b, err := storage.ParseBackend(conf.OutputDirPath, &conf.BackendOptions)
 	if err != nil {
-		return err
+		return errors.Trace(err)
 	}
 	extStore, err := storage.Create(ctx, b, false)
 	if err != nil {
-		return err
+		return errors.Trace(err)
 	}
 	d.extStore = extStore
 	return nil
 }
 
-// startHttpService is an initialization step of Dumper.
-func startHttpService(d *Dumper) error {
+// startHTTPService is an initialization step of Dumper.
+func startHTTPService(d *Dumper) error {
 	conf := d.conf
 	if conf.StatusAddr != "" {
 		go func() {
@@ -794,14 +813,9 @@ func setSessionParam(d *Dumper) error {
 			}
 		}
 	}
-	if newPool, err := resetDBWithSessionParams(pool, conf.GetDSN(""), conf.SessionParams); err != nil {
+	var err error
+	if d.dbHandle, err = resetDBWithSessionParams(pool, conf.GetDSN(""), conf.SessionParams); err != nil {
 		return errors.Trace(err)
-	} else {
-		d.dbHandle = newPool
 	}
 	return nil
 }
-
-func shouldRedirectLog(conf *Config) bool {
-	return conf.Logger != nil || conf.LogFile != ""
-}
diff --git a/v4/export/http_handler.go b/v4/export/http_handler.go
index 15a93c7..98f79b4 100644
--- a/v4/export/http_handler.go
+++ b/v4/export/http_handler.go
@@ -17,9 +17,7 @@ import (
 	"go.uber.org/zap"
 )
 
-var (
-	cmuxReadTimeout = 10 * time.Second
-)
+var cmuxReadTimeout = 10 * time.Second
 
 func startHTTPServer(lis net.Listener) {
 	router := http.NewServeMux()
@@ -35,6 +33,7 @@ func startHTTPServer(lis net.Listener) {
 		Handler: router,
 	}
 	err := httpServer.Serve(lis)
+	err = errors.Cause(err)
 	if err != nil && !isErrNetClosing(err) && err != http.ErrServerClosed {
 		log.Error("http server return with error", zap.Error(err))
 	}
@@ -60,9 +59,7 @@ func startDumplingService(addr string) error {
 	return err
 }
 
-var (
-	useOfClosedErrMsg = "use of closed network connection"
-)
+var useOfClosedErrMsg = "use of closed network connection"
 
 // isErrNetClosing checks whether is an ErrNetClosing error
 func isErrNetClosing(err error) bool {
diff --git a/v4/export/ir.go b/v4/export/ir.go
index 0901e3d..8fbb967 100644
--- a/v4/export/ir.go
+++ b/v4/export/ir.go
@@ -41,16 +41,19 @@ type SQLRowIter interface {
 	Close() error
 }
 
+// RowReceiverStringer is a combined interface of RowReceiver and Stringer
 type RowReceiverStringer interface {
 	RowReceiver
 	Stringer
 }
 
+// Stringer is an interface which represents sql types that support writing to buffer in sql/csv type
 type Stringer interface {
 	WriteToBuffer(*bytes.Buffer, bool)
 	WriteToBufferInCsv(*bytes.Buffer, bool, *csvOption)
 }
 
+// RowReceiver is an interface which represents sql types that support bind address for *sql.Rows
 type RowReceiver interface {
 	BindAddress([]interface{})
 }
@@ -70,6 +73,7 @@ type StringIter interface {
 	HasNext() bool
 }
 
+// MetaIR is the interface that wraps database/table/view's metadata
 type MetaIR interface {
 	SpecialComments() StringIter
 	TargetName() string
diff --git a/v4/export/ir_impl.go b/v4/export/ir_impl.go
index 5a9e0dc..9580fe3 100644
--- a/v4/export/ir_impl.go
+++ b/v4/export/ir_impl.go
@@ -7,6 +7,8 @@ import (
 	"database/sql"
 	"fmt"
 	"strings"
+
+	"github.com/pingcap/errors"
 )
 
 // rowIter implements the SQLRowIter interface.
@@ -64,7 +66,7 @@ func (m *stringIter) Next() string {
 		return ""
 	}
 	ret := m.ss[m.idx]
-	m.idx += 1
+	m.idx++
 	return ret
 }
 
@@ -89,7 +91,10 @@ func newTableData(query string, colLen int) *tableData {
 func (td *tableData) Start(ctx context.Context, conn *sql.Conn) error {
 	rows, err := conn.QueryContext(ctx, td.query)
 	if err != nil {
-		return err
+		return errors.Trace(err)
+	}
+	if err = rows.Err(); err != nil {
+		return errors.Trace(err)
 	}
 	td.SQLRowIter = nil
 	td.rows = rows
diff --git a/v4/export/metadata.go b/v4/export/metadata.go
index e3a9f90..da0cbeb 100644
--- a/v4/export/metadata.go
+++ b/v4/export/metadata.go
@@ -6,14 +6,15 @@ import (
 	"bytes"
 	"context"
 	"database/sql"
-	"errors"
 	"fmt"
 	"strings"
 	"time"
 
 	"github.com/pingcap/br/pkg/storage"
-	"github.com/pingcap/dumpling/v4/log"
+	"github.com/pingcap/errors"
 	"go.uber.org/zap"
+
+	"github.com/pingcap/dumpling/v4/log"
 )
 
 type globalMetadata struct {
@@ -31,8 +32,6 @@ const (
 	fileFieldIndex    = 0
 	posFieldIndex     = 1
 	gtidSetFieldIndex = 4
-
-	mariadbShowMasterStatusFieldNum = 4
 )
 
 func newGlobalMetadata(s storage.ExternalStorage, snapshot string) *globalMetadata {
@@ -56,7 +55,7 @@ func (m *globalMetadata) recordFinishTime(t time.Time) {
 	m.buffer.WriteString("Finished dump at: " + t.Format(metadataTimeLayout) + "\n")
 }
 
-func (m *globalMetadata) recordGlobalMetaData(db *sql.Conn, serverType ServerType, afterConn bool) error {
+func (m *globalMetadata) recordGlobalMetaData(db *sql.Conn, serverType ServerType, afterConn bool) error { // revive:disable-line:flag-parameter
 	if afterConn {
 		m.afterConnBuffer.Reset()
 		return recordGlobalMetaData(db, &m.afterConnBuffer, serverType, afterConn, m.snapshot)
@@ -64,7 +63,7 @@ func (m *globalMetadata) recordGlobalMetaData(db *sql.Conn, serverType ServerTyp
 	return recordGlobalMetaData(db, &m.buffer, serverType, afterConn, m.snapshot)
 }
 
-func recordGlobalMetaData(db *sql.Conn, buffer *bytes.Buffer, serverType ServerType, afterConn bool, snapshot string) error {
+func recordGlobalMetaData(db *sql.Conn, buffer *bytes.Buffer, serverType ServerType, afterConn bool, snapshot string) error { // revive:disable-line:flag-parameter
 	writeMasterStatusHeader := func() {
 		buffer.WriteString("SHOW MASTER STATUS:")
 		if afterConn {
@@ -143,7 +142,7 @@ func recordGlobalMetaData(db *sql.Conn, buffer *bytes.Buffer, serverType ServerT
 			fmt.Fprintf(buffer, "\tLog: %s\n\tPos: %s\n\tGTID:%s\n", logFile, pos, gtidSet)
 		}
 	default:
-		return errors.New("unsupported serverType" + serverType.String() + "for recordGlobalMetaData")
+		return errors.Errorf("unsupported serverType %s for recordGlobalMetaData", serverType.String())
 	}
 	buffer.WriteString("\n")
 	if serverType == ServerTypeTiDB {
@@ -173,7 +172,7 @@ func recordGlobalMetaData(db *sql.Conn, buffer *bytes.Buffer, serverType ServerT
 	return simpleQuery(db, query, func(rows *sql.Rows) error {
 		cols, err := rows.Columns()
 		if err != nil {
-			return err
+			return errors.Trace(err)
 		}
 		data := make([]sql.NullString, len(cols))
 		args := make([]interface{}, 0, len(cols))
@@ -181,7 +180,7 @@ func recordGlobalMetaData(db *sql.Conn, buffer *bytes.Buffer, serverType ServerT
 			args = append(args, &data[i])
 		}
 		if err := rows.Scan(args...); err != nil {
-			return err
+			return errors.Trace(err)
 		}
 		var connName, pos, logFile, host, gtidSet string
 		for i, col := range cols {
diff --git a/v4/export/metrics.go b/v4/export/metrics.go
index 5f88646..0a97c51 100644
--- a/v4/export/metrics.go
+++ b/v4/export/metrics.go
@@ -63,6 +63,7 @@ func RegisterMetrics(registry *prometheus.Registry) {
 	registry.MustRegister(taskChannelCapacity)
 }
 
+// RemoveLabelValuesWithTaskInMetrics removes metrics of specified labels.
 func RemoveLabelValuesWithTaskInMetrics(labels prometheus.Labels) {
 	finishedSizeCounter.Delete(labels)
 	finishedRowsCounter.Delete(labels)
diff --git a/v4/export/prepare.go b/v4/export/prepare.go
index 517c3f2..00bbbf0 100644
--- a/v4/export/prepare.go
+++ b/v4/export/prepare.go
@@ -9,8 +9,9 @@ import (
 	"strings"
 	"text/template"
 
-	"github.com/pingcap/dumpling/v4/log"
 	"github.com/pingcap/errors"
+
+	"github.com/pingcap/dumpling/v4/log"
 )
 
 const (
@@ -52,21 +53,26 @@ const (
 		{{- end -}}
 	`
 
+	// DefaultAnonymousOutputFileTemplateText is the default anonymous output file templateText for dumpling's table data file name
 	DefaultAnonymousOutputFileTemplateText = "result.{{.Index}}"
 )
 
-var filenameEscapeRegexp = regexp.MustCompile(`[\x00-\x1f%"*./:<>?\\|]|-(?i:schema)`)
-var DefaultOutputFileTemplate = template.Must(template.New("data").
-	Option("missingkey=error").
-	Funcs(template.FuncMap{
-		"fn": func(input string) string {
-			return filenameEscapeRegexp.ReplaceAllStringFunc(input, func(match string) string {
-				return fmt.Sprintf("%%%02X%s", match[0], match[1:])
-			})
-		},
-	}).
-	Parse(defaultOutputFileTemplateBase))
+var (
+	filenameEscapeRegexp = regexp.MustCompile(`[\x00-\x1f%"*./:<>?\\|]|-(?i:schema)`)
+	// DefaultOutputFileTemplate is the default output file template for dumpling's table data file name
+	DefaultOutputFileTemplate = template.Must(template.New("data").
+					Option("missingkey=error").
+					Funcs(template.FuncMap{
+			"fn": func(input string) string {
+				return filenameEscapeRegexp.ReplaceAllStringFunc(input, func(match string) string {
+					return fmt.Sprintf("%%%02X%s", match[0], match[1:])
+				})
+			},
+		}).
+		Parse(defaultOutputFileTemplateBase))
+)
 
+// ParseOutputFileTemplate parses template from the specified text
 func ParseOutputFileTemplate(text string) (*template.Template, error) {
 	return template.Must(DefaultOutputFileTemplate.Clone()).Parse(text)
 }
@@ -75,22 +81,21 @@ func prepareDumpingDatabases(conf *Config, db *sql.Conn) ([]string, error) {
 	databases, err := ShowDatabases(db)
 	if len(conf.Databases) == 0 {
 		return databases, err
-	} else {
-		dbMap := make(map[string]interface{}, len(databases))
-		for _, database := range databases {
-			dbMap[database] = struct{}{}
-		}
-		var notExistsDatabases []string
-		for _, database := range conf.Databases {
-			if _, ok := dbMap[database]; !ok {
-				notExistsDatabases = append(notExistsDatabases, database)
-			}
-		}
-		if len(notExistsDatabases) > 0 {
-			return nil, errors.Errorf("Unknown databases [%s]", strings.Join(notExistsDatabases, ","))
+	}
+	dbMap := make(map[string]interface{}, len(databases))
+	for _, database := range databases {
+		dbMap[database] = struct{}{}
+	}
+	var notExistsDatabases []string
+	for _, database := range conf.Databases {
+		if _, ok := dbMap[database]; !ok {
+			notExistsDatabases = append(notExistsDatabases, database)
 		}
-		return conf.Databases, nil
 	}
+	if len(notExistsDatabases) > 0 {
+		return nil, errors.Errorf("Unknown databases [%s]", strings.Join(notExistsDatabases, ","))
+	}
+	return conf.Databases, nil
 }
 
 func listAllTables(db *sql.Conn, databaseNames []string) (DatabaseTables, error) {
@@ -105,33 +110,42 @@ func listAllViews(db *sql.Conn, databaseNames []string) (DatabaseTables, error)
 
 type databaseName = string
 
+// TableType represents the type of table
 type TableType int8
 
 const (
+	// TableTypeBase represents the basic table
 	TableTypeBase TableType = iota
+	// TableTypeView represents the view table
 	TableTypeView
 )
 
+// TableInfo is the table info for a table in database
 type TableInfo struct {
 	Name string
 	Type TableType
 }
 
+// Equals returns true the table info is the same with another one
 func (t *TableInfo) Equals(other *TableInfo) bool {
 	return t.Name == other.Name && t.Type == other.Type
 }
 
+// DatabaseTables is the type that represents tables in a database
 type DatabaseTables map[databaseName][]*TableInfo
 
+// NewDatabaseTables returns a new DatabaseTables
 func NewDatabaseTables() DatabaseTables {
 	return DatabaseTables{}
 }
 
+// AppendTable appends a TableInfo to DatabaseTables
 func (d DatabaseTables) AppendTable(dbName string, table *TableInfo) DatabaseTables {
 	d[dbName] = append(d[dbName], table)
 	return d
 }
 
+// AppendTables appends several basic tables to DatabaseTables
 func (d DatabaseTables) AppendTables(dbName string, tableNames ...string) DatabaseTables {
 	for _, t := range tableNames {
 		d[dbName] = append(d[dbName], &TableInfo{t, TableTypeBase})
@@ -139,6 +153,7 @@ func (d DatabaseTables) AppendTables(dbName string, tableNames ...string) Databa
 	return d
 }
 
+// AppendViews appends several views to DatabaseTables
 func (d DatabaseTables) AppendViews(dbName string, viewNames ...string) DatabaseTables {
 	for _, v := range viewNames {
 		d[dbName] = append(d[dbName], &TableInfo{v, TableTypeView})
@@ -146,12 +161,14 @@ func (d DatabaseTables) AppendViews(dbName string, viewNames ...string) Database
 	return d
 }
 
+// Merge merges another DatabaseTables
 func (d DatabaseTables) Merge(other DatabaseTables) {
 	for name, infos := range other {
 		d[name] = append(d[name], infos...)
 	}
 }
 
+// Literal returns a user-friendly output for DatabaseTables
 func (d DatabaseTables) Literal() string {
 	var b strings.Builder
 	b.WriteString("tables list\n")
diff --git a/v4/export/retry.go b/v4/export/retry.go
index f1683d4..f4a75ff 100644
--- a/v4/export/retry.go
+++ b/v4/export/retry.go
@@ -16,8 +16,8 @@ const (
 	dumpChunkMaxWaitInterval = 200 * time.Millisecond
 )
 
-func newDumpChunkBackoffer(canRetry bool) *dumpChunkBackoffer {
-	if !canRetry {
+func newDumpChunkBackoffer(shouldRetry bool) *dumpChunkBackoffer { // revive:disable-line:flag-parameter
+	if !shouldRetry {
 		return &dumpChunkBackoffer{
 			attempt: 1,
 		}
diff --git a/v4/export/sql.go b/v4/export/sql.go
index 5f0b7e7..ca5a235 100644
--- a/v4/export/sql.go
+++ b/v4/export/sql.go
@@ -6,6 +6,7 @@ import (
 	"context"
 	"database/sql"
 	"fmt"
+	"io"
 	"net/url"
 	"strconv"
 	"strings"
@@ -16,6 +17,7 @@ import (
 	"github.com/pingcap/dumpling/v4/log"
 )
 
+// ShowDatabases shows the databases of a database server.
 func ShowDatabases(db *sql.Conn) ([]string, error) {
 	var res oneStrColumnTable
 	if err := simpleQuery(db, "SHOW DATABASES", res.handleOneRow); err != nil {
@@ -33,6 +35,8 @@ func ShowTables(db *sql.Conn) ([]string, error) {
 	return res.data, nil
 }
 
+// ShowCreateDatabase constructs the create database SQL for a specified database
+// returns (createDatabaseSQL, error)
 func ShowCreateDatabase(db *sql.Conn, database string) (string, error) {
 	var oneRow [2]string
 	handleOneRow := func(rows *sql.Rows) error {
@@ -46,6 +50,8 @@ func ShowCreateDatabase(db *sql.Conn, database string) (string, error) {
 	return oneRow[1], nil
 }
 
+// ShowCreateTable constructs the create table SQL for a specified table
+// returns (createTableSQL, error)
 func ShowCreateTable(db *sql.Conn, database, table string) (string, error) {
 	var oneRow [2]string
 	handleOneRow := func(rows *sql.Rows) error {
@@ -59,13 +65,15 @@ func ShowCreateTable(db *sql.Conn, database, table string) (string, error) {
 	return oneRow[1], nil
 }
 
-func ShowCreateView(db *sql.Conn, database, view string) (string, string, error) {
+// ShowCreateView constructs the create view SQL for a specified view
+// returns (createFakeTableSQL, createViewSQL, error)
+func ShowCreateView(db *sql.Conn, database, view string) (createFakeTableSQL string, createRealViewSQL string, err error) {
 	var fieldNames []string
 	handleFieldRow := func(rows *sql.Rows) error {
 		var oneRow [6]sql.NullString
-		err := rows.Scan(&oneRow[0], &oneRow[1], &oneRow[2], &oneRow[3], &oneRow[4], &oneRow[5])
-		if err != nil {
-			return err
+		scanErr := rows.Scan(&oneRow[0], &oneRow[1], &oneRow[2], &oneRow[3], &oneRow[4], &oneRow[5])
+		if scanErr != nil {
+			return errors.Trace(scanErr)
 		}
 		if oneRow[0].Valid {
 			fieldNames = append(fieldNames, fmt.Sprintf("`%s` int", escapeString(oneRow[0].String)))
@@ -80,7 +88,7 @@ func ShowCreateView(db *sql.Conn, database, view string) (string, string, error)
 
 	// Build createTableSQL
 	query := fmt.Sprintf("SHOW FIELDS FROM `%s`.`%s`", escapeString(database), escapeString(view))
-	err := simpleQuery(db, query, handleFieldRow)
+	err = simpleQuery(db, query, handleFieldRow)
 	if err != nil {
 		return "", "", errors.Annotatef(err, "sql: %s", query)
 	}
@@ -111,6 +119,7 @@ func ShowCreateView(db *sql.Conn, database, view string) (string, string, error)
 	return createTableSQL.String(), createViewSQL.String(), nil
 }
 
+// SetCharset builds the set charset SQLs
 func SetCharset(w *strings.Builder, characterSet, collationConnection string) {
 	w.WriteString("SET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;\n")
 	w.WriteString("SET @PREV_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;\n")
@@ -121,12 +130,14 @@ func SetCharset(w *strings.Builder, characterSet, collationConnection string) {
 	fmt.Fprintf(w, "SET collation_connection = %s;\n", collationConnection)
 }
 
-func RestoreCharset(w *strings.Builder) {
-	w.WriteString("SET character_set_client = @PREV_CHARACTER_SET_CLIENT;\n")
-	w.WriteString("SET character_set_results = @PREV_CHARACTER_SET_RESULTS;\n")
-	w.WriteString("SET collation_connection = @PREV_COLLATION_CONNECTION;\n")
+// RestoreCharset builds the restore charset SQLs
+func RestoreCharset(w io.StringWriter) {
+	_, _ = w.WriteString("SET character_set_client = @PREV_CHARACTER_SET_CLIENT;\n")
+	_, _ = w.WriteString("SET character_set_results = @PREV_CHARACTER_SET_RESULTS;\n")
+	_, _ = w.WriteString("SET collation_connection = @PREV_COLLATION_CONNECTION;\n")
 }
 
+// ListAllDatabasesTables lists all the databases and tables from the database
 func ListAllDatabasesTables(db *sql.Conn, databaseNames []string, tableType TableType) (DatabaseTables, error) {
 	var tableTypeStr string
 	switch tableType {
@@ -161,6 +172,7 @@ func ListAllDatabasesTables(db *sql.Conn, databaseNames []string, tableType Tabl
 	return dbTables, nil
 }
 
+// SelectVersion gets the version information from the database server
 func SelectVersion(db *sql.DB) (string, error) {
 	var versionInfo string
 	const query = "SELECT version()"
@@ -172,6 +184,7 @@ func SelectVersion(db *sql.DB) (string, error) {
 	return versionInfo, nil
 }
 
+// SelectAllFromTable dumps data serialized from a specified table
 func SelectAllFromTable(conf *Config, db *sql.Conn, database, table string) (TableDataIR, error) {
 	selectedField, selectLen, err := buildSelectField(db, database, table, conf.CompleteInsert)
 	if err != nil {
@@ -190,20 +203,21 @@ func SelectAllFromTable(conf *Config, db *sql.Conn, database, table string) (Tab
 	}, nil
 }
 
-func SelectFromSql(conf *Config, conn *sql.Conn) (TableMeta, TableDataIR, error) {
-	log.Info("dump data from sql", zap.String("sql", conf.Sql))
-	rows, err := conn.QueryContext(context.Background(), conf.Sql)
+// SelectFromSQL dumps data serialized from a specified SQL
+func SelectFromSQL(conf *Config, conn *sql.Conn) (TableMeta, TableDataIR, error) {
+	log.Info("dump data from sql", zap.String("sql", conf.SQL))
+	rows, err := conn.QueryContext(context.Background(), conf.SQL)
 	if err != nil {
-		return nil, nil, errors.Annotatef(err, "sql: %s", conf.Sql)
+		return nil, nil, errors.Annotatef(err, "sql: %s", conf.SQL)
 	}
 	defer rows.Close()
 	colTypes, err := rows.ColumnTypes()
 	if err != nil {
-		return nil, nil, errors.Annotatef(err, "sql: %s", conf.Sql)
+		return nil, nil, errors.Annotatef(err, "sql: %s", conf.SQL)
 	}
 	cols, err := rows.Columns()
 	if err != nil {
-		return nil, nil, errors.Annotatef(err, "sql: %s", conf.Sql)
+		return nil, nil, errors.Annotatef(err, "sql: %s", conf.SQL)
 	}
 	for i := range cols {
 		cols[i] = wrapBackTicks(cols[i])
@@ -216,11 +230,12 @@ func SelectFromSql(conf *Config, conn *sql.Conn) (TableMeta, TableDataIR, error)
 		},
 	}
 	data := &tableData{
-		query:  conf.Sql,
+		query:  conf.SQL,
 		colLen: len(cols),
 	}
+	rows.Close()
 
-	return meta, data, nil
+	return meta, data, rows.Err()
 }
 
 func buildSelectQuery(database, table string, fields string, where string, orderByClause string) string {
@@ -271,6 +286,7 @@ func buildOrderByClause(conf *Config, db *sql.Conn, database, table string) (str
 	return buildOrderByClauseString(cols), nil
 }
 
+// SelectTiDBRowID checks whether this table has _tidb_rowid column
 func SelectTiDBRowID(db *sql.Conn, database, table string) (bool, error) {
 	const errBadFieldCode = 1054
 	tiDBRowIDQuery := fmt.Sprintf("SELECT _tidb_rowid from `%s`.`%s` LIMIT 0", escapeString(database), escapeString(table))
@@ -285,6 +301,7 @@ func SelectTiDBRowID(db *sql.Conn, database, table string) (bool, error) {
 	return true, nil
 }
 
+// GetColumnTypes gets *sql.ColumnTypes from a specified table
 func GetColumnTypes(db *sql.Conn, fields, database, table string) ([]*sql.ColumnType, error) {
 	query := fmt.Sprintf("SELECT %s FROM `%s`.`%s` LIMIT 1", fields, escapeString(database), escapeString(table))
 	rows, err := db.QueryContext(context.Background(), query)
@@ -292,9 +309,13 @@ func GetColumnTypes(db *sql.Conn, fields, database, table string) ([]*sql.Column
 		return nil, errors.Annotatef(err, "sql: %s", query)
 	}
 	defer rows.Close()
+	if err = rows.Err(); err != nil {
+		return nil, errors.Annotatef(err, "sql: %s", query)
+	}
 	return rows.ColumnTypes()
 }
 
+// GetPrimaryKeyAndColumnTypes gets all primary columns and their types in ordinal order
 func GetPrimaryKeyAndColumnTypes(conn *sql.Conn, database, table string) ([]string, []string, error) {
 	query :=
 		`SELECT c.COLUMN_NAME, DATA_TYPE FROM
@@ -321,6 +342,7 @@ ORDER BY k.ORDINAL_POSITION;`
 	return colNames, colTypes, nil
 }
 
+// GetPrimaryKeyColumns gets all primary columns in ordinal order
 func GetPrimaryKeyColumns(db *sql.Conn, database, table string) ([]string, error) {
 	priKeyColsQuery := "SELECT column_name FROM information_schema.KEY_COLUMN_USAGE " +
 		"WHERE table_schema = ? AND table_name = ? AND CONSTRAINT_NAME = 'PRIMARY' order by ORDINAL_POSITION;"
@@ -344,10 +366,12 @@ func GetPrimaryKeyColumns(db *sql.Conn, database, table string) ([]string, error
 	return cols, nil
 }
 
+// GetPrimaryKeyName try to get a numeric primary index
 func GetPrimaryKeyName(db *sql.Conn, database, table string) (string, error) {
 	return getNumericIndex(db, database, table, "PRI")
 }
 
+// GetUniqueIndexName try to get a numeric unique index
 func GetUniqueIndexName(db *sql.Conn, database, table string) (string, error) {
 	return getNumericIndex(db, database, table, "UNI")
 }
@@ -358,7 +382,7 @@ func getNumericIndex(db *sql.Conn, database, table, indexType string) (string, e
 	var colName string
 	row := db.QueryRowContext(context.Background(), keyQuery, database, table, indexType)
 	err := row.Scan(&colName)
-	if err == sql.ErrNoRows {
+	if errors.Cause(err) == sql.ErrNoRows {
 		return "", nil
 	} else if err != nil {
 		return "", errors.Annotatef(err, "sql: %s, indexType: %s", keyQuery, indexType)
@@ -366,35 +390,34 @@ func getNumericIndex(db *sql.Conn, database, table, indexType string) (string, e
 	return colName, nil
 }
 
+// FlushTableWithReadLock flush tables with read lock
 func FlushTableWithReadLock(ctx context.Context, db *sql.Conn) error {
 	const ftwrlQuery = "FLUSH TABLES WITH READ LOCK"
 	_, err := db.ExecContext(ctx, ftwrlQuery)
 	return errors.Annotatef(err, "sql: %s", ftwrlQuery)
 }
 
+// LockTables locks table with read lock
 func LockTables(ctx context.Context, db *sql.Conn, database, table string) error {
 	lockTableQuery := fmt.Sprintf("LOCK TABLES `%s`.`%s` READ", escapeString(database), escapeString(table))
 	_, err := db.ExecContext(ctx, lockTableQuery)
 	return errors.Annotatef(err, "sql: %s", lockTableQuery)
 }
 
+// UnlockTables unlocks all tables' lock
 func UnlockTables(ctx context.Context, db *sql.Conn) error {
 	const unlockTableQuery = "UNLOCK TABLES"
 	_, err := db.ExecContext(ctx, unlockTableQuery)
 	return errors.Annotatef(err, "sql: %s", unlockTableQuery)
 }
 
-func UseDatabase(db *sql.DB, databaseName string) error {
-	_, err := db.Exec(fmt.Sprintf("USE `%s`", escapeString(databaseName)))
-	return errors.Trace(err)
-}
-
+// ShowMasterStatus get SHOW MASTER STATUS result from database
 func ShowMasterStatus(db *sql.Conn) ([]string, error) {
 	var oneRow []string
 	handleOneRow := func(rows *sql.Rows) error {
 		cols, err := rows.Columns()
 		if err != nil {
-			return err
+			return errors.Trace(err)
 		}
 		fieldNum := len(cols)
 		oneRow = make([]string, fieldNum)
@@ -412,12 +435,13 @@ func ShowMasterStatus(db *sql.Conn) ([]string, error) {
 	return oneRow, nil
 }
 
+// GetSpecifiedColumnValue get columns' values whose name is equal to columnName
 func GetSpecifiedColumnValue(rows *sql.Rows, columnName string) ([]string, error) {
 	var strs []string
 	columns, _ := rows.Columns()
 	addr := make([]interface{}, len(columns))
 	oneRow := make([]sql.NullString, len(columns))
-	var fieldIndex = -1
+	fieldIndex := -1
 	for i, col := range columns {
 		if strings.ToUpper(col) == columnName {
 			fieldIndex = i
@@ -432,11 +456,14 @@ func GetSpecifiedColumnValue(rows *sql.Rows, columnName string) ([]string, error
 		if err != nil {
 			return strs, errors.Trace(err)
 		}
-		strs = append(strs, oneRow[fieldIndex].String)
+		if oneRow[fieldIndex].Valid {
+			strs = append(strs, oneRow[fieldIndex].String)
+		}
 	}
 	return strs, nil
 }
 
+// GetPdAddrs gets PD address from TiDB
 func GetPdAddrs(db *sql.DB) ([]string, error) {
 	query := "SELECT * FROM information_schema.cluster_info where type = 'pd';"
 	rows, err := db.Query(query)
@@ -449,6 +476,7 @@ func GetPdAddrs(db *sql.DB) ([]string, error) {
 	return GetSpecifiedColumnValue(rows, "STATUS_ADDRESS")
 }
 
+// GetTiDBDDLIDs gets DDL IDs from TiDB
 func GetTiDBDDLIDs(db *sql.DB) ([]string, error) {
 	query := "SELECT * FROM information_schema.tidb_servers_info;"
 	rows, err := db.Query(query)
@@ -461,6 +489,7 @@ func GetTiDBDDLIDs(db *sql.DB) ([]string, error) {
 	return GetSpecifiedColumnValue(rows, "DDL_ID")
 }
 
+// CheckTiDBWithTiKV use sql to check whether current TiDB has TiKV
 func CheckTiDBWithTiKV(db *sql.DB) (bool, error) {
 	var count int
 	query := "SELECT COUNT(1) as c FROM MYSQL.TiDB WHERE VARIABLE_NAME='tikv_gc_safe_point'"
@@ -542,7 +571,7 @@ func createConnWithConsistency(ctx context.Context, db *sql.DB) (*sql.Conn, erro
 
 // buildSelectField returns the selecting fields' string(joined by comma(`,`)),
 // and the number of writable fields.
-func buildSelectField(db *sql.Conn, dbName, tableName string, completeInsert bool) (string, int, error) {
+func buildSelectField(db *sql.Conn, dbName, tableName string, completeInsert bool) (string, int, error) { // revive:disable-line:flag-parameter
 	query := `SELECT COLUMN_NAME,EXTRA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=? AND TABLE_NAME=? ORDER BY ORDINAL_POSITION;`
 	rows, err := db.QueryContext(context.Background(), query, dbName, tableName)
 	if err != nil {
@@ -566,6 +595,9 @@ func buildSelectField(db *sql.Conn, dbName, tableName string, completeInsert boo
 		}
 		availableFields = append(availableFields, wrapBackTicks(escapeString(fieldName)))
 	}
+	if err = rows.Err(); err != nil {
+		return "", 0, errors.Annotatef(err, "sql: %s", query)
+	}
 	if completeInsert || hasGenerateColumn {
 		return strings.Join(availableFields, ","), len(availableFields), nil
 	}
@@ -703,18 +735,29 @@ func estimateCount(dbName, tableName string, db *sql.Conn, field string, conf *C
 }
 
 func detectEstimateRows(db *sql.Conn, query string, fieldNames []string) uint64 {
-	row, err := db.QueryContext(context.Background(), query)
+	rows, err := db.QueryContext(context.Background(), query)
 	if err != nil {
 		log.Warn("can't execute query from db",
 			zap.String("query", query), zap.Error(err))
 		return 0
 	}
-	defer row.Close()
-	row.Next()
-	columns, _ := row.Columns()
+	defer rows.Close()
+	rows.Next()
+	columns, err := rows.Columns()
+	if err != nil {
+		log.Warn("can't get columns from db",
+			zap.String("query", query), zap.Error(err))
+		return 0
+	}
+	err = rows.Err()
+	if err != nil {
+		log.Warn("rows meet some error during the query",
+			zap.String("query", query), zap.Error(err))
+		return 0
+	}
 	addr := make([]interface{}, len(columns))
 	oneRow := make([]sql.NullString, len(columns))
-	var fieldIndex = -1
+	fieldIndex := -1
 	for i := range oneRow {
 		addr[i] = &oneRow[i]
 	}
@@ -727,7 +770,7 @@ found:
 			}
 		}
 	}
-	err = row.Scan(addr...)
+	err = rows.Scan(addr...)
 	if err != nil || fieldIndex < 0 {
 		log.Warn("can't get estimate count from db",
 			zap.String("query", query), zap.Error(err))
diff --git a/v4/export/sql_type.go b/v4/export/sql_type.go
index 619eb79..d061b34 100644
--- a/v4/export/sql_type.go
+++ b/v4/export/sql_type.go
@@ -10,11 +10,13 @@ import (
 
 var colTypeRowReceiverMap = map[string]func() RowReceiverStringer{}
 
-var nullValue = "NULL"
-var quotationMark = []byte{'\''}
-var doubleQuotationMark = []byte{'"'}
+var (
+	nullValue           = "NULL"
+	quotationMark       = []byte{'\''}
+	doubleQuotationMark = []byte{'"'}
+)
 
-func init() {
+func initColTypeRowReceiverMap() {
 	for _, s := range dataTypeString {
 		colTypeRowReceiverMap[s] = SQLTypeStringMaker
 	}
@@ -47,7 +49,7 @@ var dataTypeBin = []string{
 	"BIT",
 }
 
-func getEscapeQuotation(escapeBackSlash bool, escapeQuotation []byte) []byte {
+func getEscapeQuotation(escapeBackSlash bool, escapeQuotation []byte) []byte { // revive:disable-line:flag-parameter
 	if escapeBackSlash {
 		return nil
 	}
@@ -71,22 +73,16 @@ func escape(s []byte, bf *bytes.Buffer, escapeQuotation []byte) {
 		switch s[i] {
 		case 0: /* Must be escaped for 'mysql' */
 			escape = '0'
-			break
 		case '\n': /* Must be escaped for logs */
 			escape = 'n'
-			break
 		case '\r':
 			escape = 'r'
-			break
 		case '\\':
 			escape = '\\'
-			break
 		case '\'':
 			escape = '\''
-			break
 		case '"': /* Better safe than sorry */
 			escape = '"'
-			break
 		case '\032': /* This gives problems on Win32 */
 			escape = 'Z'
 		}
@@ -105,18 +101,22 @@ func escape(s []byte, bf *bytes.Buffer, escapeQuotation []byte) {
 	}
 }
 
+// SQLTypeStringMaker returns a SQLTypeString
 func SQLTypeStringMaker() RowReceiverStringer {
 	return &SQLTypeString{}
 }
 
+// SQLTypeBytesMaker returns a SQLTypeBytes
 func SQLTypeBytesMaker() RowReceiverStringer {
 	return &SQLTypeBytes{}
 }
 
+// SQLTypeNumberMaker returns a SQLTypeNumber
 func SQLTypeNumberMaker() RowReceiverStringer {
 	return &SQLTypeNumber{}
 }
 
+// MakeRowReceiver constructs RowReceiverArr from column types
 func MakeRowReceiver(colTypes []string) RowReceiverStringer {
 	rowReceiverArr := make([]RowReceiverStringer, len(colTypes))
 	for i, colTp := range colTypes {
@@ -132,11 +132,13 @@ func MakeRowReceiver(colTypes []string) RowReceiverStringer {
 	}
 }
 
+// RowReceiverArr is the combined RowReceiver array
 type RowReceiverArr struct {
 	bound     bool
 	receivers []RowReceiverStringer
 }
 
+// BindAddress implements RowReceiver.BindAddress
 func (r RowReceiverArr) BindAddress(args []interface{}) {
 	if r.bound {
 		return
@@ -147,6 +149,7 @@ func (r RowReceiverArr) BindAddress(args []interface{}) {
 	}
 }
 
+// WriteToBuffer implements Stringer.WriteToBuffer
 func (r RowReceiverArr) WriteToBuffer(bf *bytes.Buffer, escapeBackslash bool) {
 	bf.WriteByte('(')
 	for i, receiver := range r.receivers {
@@ -158,6 +161,7 @@ func (r RowReceiverArr) WriteToBuffer(bf *bytes.Buffer, escapeBackslash bool) {
 	bf.WriteByte(')')
 }
 
+// WriteToBufferInCsv implements Stringer.WriteToBufferInCsv
 func (r RowReceiverArr) WriteToBufferInCsv(bf *bytes.Buffer, escapeBackslash bool, opt *csvOption) {
 	for i, receiver := range r.receivers {
 		receiver.WriteToBufferInCsv(bf, escapeBackslash, opt)
@@ -167,10 +171,12 @@ func (r RowReceiverArr) WriteToBufferInCsv(bf *bytes.Buffer, escapeBackslash boo
 	}
 }
 
+// SQLTypeNumber implements RowReceiverStringer which represents numeric type columns in database
 type SQLTypeNumber struct {
 	SQLTypeString
 }
 
+// WriteToBuffer implements Stringer.WriteToBuffer
 func (s SQLTypeNumber) WriteToBuffer(bf *bytes.Buffer, _ bool) {
 	if s.RawBytes != nil {
 		bf.Write(s.RawBytes)
@@ -179,6 +185,7 @@ func (s SQLTypeNumber) WriteToBuffer(bf *bytes.Buffer, _ bool) {
 	}
 }
 
+// WriteToBufferInCsv implements Stringer.WriteToBufferInCsv
 func (s SQLTypeNumber) WriteToBufferInCsv(bf *bytes.Buffer, _ bool, opt *csvOption) {
 	if s.RawBytes != nil {
 		bf.Write(s.RawBytes)
@@ -187,14 +194,17 @@ func (s SQLTypeNumber) WriteToBufferInCsv(bf *bytes.Buffer, _ bool, opt *csvOpti
 	}
 }
 
+// SQLTypeString implements RowReceiverStringer which represents string type columns in database
 type SQLTypeString struct {
 	sql.RawBytes
 }
 
+// BindAddress implements RowReceiver.BindAddress
 func (s *SQLTypeString) BindAddress(arg []interface{}) {
 	arg[0] = &s.RawBytes
 }
 
+// WriteToBuffer implements Stringer.WriteToBuffer
 func (s *SQLTypeString) WriteToBuffer(bf *bytes.Buffer, escapeBackslash bool) {
 	if s.RawBytes != nil {
 		bf.Write(quotationMark)
@@ -205,6 +215,7 @@ func (s *SQLTypeString) WriteToBuffer(bf *bytes.Buffer, escapeBackslash bool) {
 	}
 }
 
+// WriteToBufferInCsv implements Stringer.WriteToBufferInCsv
 func (s *SQLTypeString) WriteToBufferInCsv(bf *bytes.Buffer, escapeBackslash bool, opt *csvOption) {
 	if s.RawBytes != nil {
 		bf.Write(opt.delimiter)
@@ -215,14 +226,17 @@ func (s *SQLTypeString) WriteToBufferInCsv(bf *bytes.Buffer, escapeBackslash boo
 	}
 }
 
+// SQLTypeBytes implements RowReceiverStringer which represents bytes type columns in database
 type SQLTypeBytes struct {
 	sql.RawBytes
 }
 
+// BindAddress implements RowReceiver.BindAddress
 func (s *SQLTypeBytes) BindAddress(arg []interface{}) {
 	arg[0] = &s.RawBytes
 }
 
+// WriteToBuffer implements Stringer.WriteToBuffer
 func (s *SQLTypeBytes) WriteToBuffer(bf *bytes.Buffer, _ bool) {
 	if s.RawBytes != nil {
 		fmt.Fprintf(bf, "x'%x'", s.RawBytes)
@@ -231,6 +245,7 @@ func (s *SQLTypeBytes) WriteToBuffer(bf *bytes.Buffer, _ bool) {
 	}
 }
 
+// WriteToBufferInCsv implements Stringer.WriteToBufferInCsv
 func (s *SQLTypeBytes) WriteToBufferInCsv(bf *bytes.Buffer, escapeBackslash bool, opt *csvOption) {
 	if s.RawBytes != nil {
 		bf.Write(opt.delimiter)
diff --git a/v4/export/task.go b/v4/export/task.go
index 6c11bca..8cfec59 100644
--- a/v4/export/task.go
+++ b/v4/export/task.go
@@ -1,17 +1,23 @@
+// Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0.
+
 package export
 
 import "fmt"
 
+// Task is a file dump task for dumpling, it could either be dumping database/table/view metadata, table data
 type Task interface {
+	// Brief is the brief for a dumping task
 	Brief() string
 }
 
+// TaskDatabaseMeta is a dumping database metadata task
 type TaskDatabaseMeta struct {
 	Task
 	DatabaseName      string
 	CreateDatabaseSQL string
 }
 
+// TaskTableMeta is a dumping table metadata task
 type TaskTableMeta struct {
 	Task
 	DatabaseName   string
@@ -19,6 +25,7 @@ type TaskTableMeta struct {
 	CreateTableSQL string
 }
 
+// TaskViewMeta is a dumping view metadata task
 type TaskViewMeta struct {
 	Task
 	DatabaseName   string
@@ -27,6 +34,7 @@ type TaskViewMeta struct {
 	CreateViewSQL  string
 }
 
+// TaskTableData is a dumping table data task
 type TaskTableData struct {
 	Task
 	Meta        TableMeta
@@ -35,6 +43,7 @@ type TaskTableData struct {
 	TotalChunks int
 }
 
+// NewTaskDatabaseMeta returns a new dumping database metadata task
 func NewTaskDatabaseMeta(dbName, createSQL string) *TaskDatabaseMeta {
 	return &TaskDatabaseMeta{
 		DatabaseName:      dbName,
@@ -42,6 +51,7 @@ func NewTaskDatabaseMeta(dbName, createSQL string) *TaskDatabaseMeta {
 	}
 }
 
+// NewTaskTableMeta returns a new dumping table metadata task
 func NewTaskTableMeta(dbName, tblName, createSQL string) *TaskTableMeta {
 	return &TaskTableMeta{
 		DatabaseName:   dbName,
@@ -50,6 +60,7 @@ func NewTaskTableMeta(dbName, tblName, createSQL string) *TaskTableMeta {
 	}
 }
 
+// NewTaskViewMeta returns a new dumping view metadata task
 func NewTaskViewMeta(dbName, tblName, createTableSQL, createViewSQL string) *TaskViewMeta {
 	return &TaskViewMeta{
 		DatabaseName:   dbName,
@@ -59,6 +70,7 @@ func NewTaskViewMeta(dbName, tblName, createTableSQL, createViewSQL string) *Tas
 	}
 }
 
+// NewTaskTableData returns a new dumping table data task
 func NewTaskTableData(meta TableMeta, data TableDataIR, currentChunk, totalChunks int) *TaskTableData {
 	return &TaskTableData{
 		Meta:        meta,
@@ -68,18 +80,22 @@ func NewTaskTableData(meta TableMeta, data TableDataIR, currentChunk, totalChunk
 	}
 }
 
+// Brief implements task.Brief
 func (t *TaskDatabaseMeta) Brief() string {
 	return fmt.Sprintf("meta of dababase '%s'", t.DatabaseName)
 }
 
+// Brief implements task.Brief
 func (t *TaskTableMeta) Brief() string {
 	return fmt.Sprintf("meta of table '%s'.'%s'", t.DatabaseName, t.TableName)
 }
 
+// Brief implements task.Brief
 func (t *TaskViewMeta) Brief() string {
 	return fmt.Sprintf("meta of view '%s'.'%s'", t.DatabaseName, t.ViewName)
 }
 
+// Brief implements task.Brief
 func (t *TaskTableData) Brief() string {
 	db, tbl := t.Meta.DatabaseName(), t.Meta.TableName()
 	idx, total := t.ChunkIndex, t.TotalChunks
diff --git a/v4/export/util.go b/v4/export/util.go
index ba1435b..7157a0d 100644
--- a/v4/export/util.go
+++ b/v4/export/util.go
@@ -9,23 +9,24 @@ import (
 	"strings"
 	"time"
 
+	"github.com/pingcap/errors"
 	"go.etcd.io/etcd/clientv3"
 )
 
 const tidbServerInformationPath = "/tidb/server/info"
 
-func GetPdDDLIDs(pCtx context.Context, cli *clientv3.Client) ([]string, error) {
+func getPdDDLIDs(pCtx context.Context, cli *clientv3.Client) ([]string, error) {
 	ctx, cancel := context.WithTimeout(pCtx, 10*time.Second)
 	defer cancel()
 
-	var pdDDLIds []string
 	resp, err := cli.Get(ctx, tidbServerInformationPath, clientv3.WithPrefix())
 	if err != nil {
-		return pdDDLIds, err
+		return nil, errors.Trace(err)
 	}
-	for _, kv := range resp.Kvs {
+	pdDDLIds := make([]string, len(resp.Kvs))
+	for i, kv := range resp.Kvs {
 		items := strings.Split(string(kv.Key), "/")
-		pdDDLIds = append(pdDDLIds, items[len(items)-1])
+		pdDDLIds[i] = items[len(items)-1]
 	}
 	return pdDDLIds, nil
 }
@@ -36,13 +37,13 @@ func checkSameCluster(ctx context.Context, db *sql.DB, pdAddrs []string) (bool,
 		DialTimeout: defaultEtcdDialTimeOut,
 	})
 	if err != nil {
-		return false, err
+		return false, errors.Trace(err)
 	}
 	tidbDDLIDs, err := GetTiDBDDLIDs(db)
 	if err != nil {
 		return false, err
 	}
-	pdDDLIDs, err := GetPdDDLIDs(ctx, cli)
+	pdDDLIDs, err := getPdDDLIDs(ctx, cli)
 	if err != nil {
 		return false, err
 	}
diff --git a/v4/export/writer.go b/v4/export/writer.go
index c891397..0d4e81b 100644
--- a/v4/export/writer.go
+++ b/v4/export/writer.go
@@ -12,11 +12,14 @@ import (
 
 	"github.com/pingcap/br/pkg/storage"
 	"github.com/pingcap/br/pkg/utils"
+	"github.com/pingcap/errors"
 	"go.uber.org/zap"
 
 	"github.com/pingcap/dumpling/v4/log"
 )
 
+// Writer is the abstraction that keep pulling data from database and write to files.
+// Every writer owns a snapshot connection, and will try to get a task from task stream chan and work on it.
 type Writer struct {
 	id         int64
 	ctx        context.Context
@@ -32,7 +35,8 @@ type Writer struct {
 	finishTableCallBack func(Task)
 }
 
-func NewWriter(id int64, ctx context.Context, config *Config, conn *sql.Conn, externalStore storage.ExternalStorage) *Writer {
+// NewWriter returns a new Writer with given configurations
+func NewWriter(ctx context.Context, id int64, config *Config, conn *sql.Conn, externalStore storage.ExternalStorage) *Writer {
 	sw := &Writer{
 		id:                  id,
 		ctx:                 ctx,
@@ -43,9 +47,9 @@ func NewWriter(id int64, ctx context.Context, config *Config, conn *sql.Conn, ex
 		finishTableCallBack: func(Task) {},
 	}
 	switch strings.ToLower(config.FileType) {
-	case "sql":
+	case FileFormatSQLTextString:
 		sw.fileFmt = FileFormatSQLText
-	case "csv":
+	case FileFormatCSVString:
 		sw.fileFmt = FileFormatCSV
 	}
 	return sw
@@ -56,7 +60,7 @@ func (w *Writer) setFinishTaskCallBack(fn func(Task)) {
 }
 
 func (w *Writer) setFinishTableCallBack(fn func(Task)) {
-	w.finishTaskCallBack = fn
+	w.finishTableCallBack = fn
 }
 
 func countTotalTask(writers []*Writer) int {
@@ -111,6 +115,7 @@ func (w *Writer) handleTask(task Task) error {
 	}
 }
 
+// WriteDatabaseMeta writes database meta to a file
 func (w *Writer) WriteDatabaseMeta(db, createSQL string) error {
 	ctx, conf := w.ctx, w.conf
 	fileName, err := (&outputFileNamer{DB: db}).render(conf.OutputFileTemplate, outputFileTemplateSchema)
@@ -120,6 +125,7 @@ func (w *Writer) WriteDatabaseMeta(db, createSQL string) error {
 	return writeMetaToFile(ctx, db, createSQL, w.extStorage, fileName+".sql", conf.CompressType)
 }
 
+// WriteTableMeta writes table meta to a file
 func (w *Writer) WriteTableMeta(db, table, createSQL string) error {
 	ctx, conf := w.ctx, w.conf
 	fileName, err := (&outputFileNamer{DB: db, Table: table}).render(conf.OutputFileTemplate, outputFileTemplateTable)
@@ -129,6 +135,7 @@ func (w *Writer) WriteTableMeta(db, table, createSQL string) error {
 	return writeMetaToFile(ctx, db, createSQL, w.extStorage, fileName+".sql", conf.CompressType)
 }
 
+// WriteViewMeta writes view meta to a file
 func (w *Writer) WriteViewMeta(db, view, createTableSQL, createViewSQL string) error {
 	ctx, conf := w.ctx, w.conf
 	fileNameTable, err := (&outputFileNamer{DB: db, Table: view}).render(conf.OutputFileTemplate, outputFileTemplateTable)
@@ -146,6 +153,7 @@ func (w *Writer) WriteViewMeta(db, view, createTableSQL, createViewSQL string) e
 	return writeMetaToFile(ctx, db, createViewSQL, w.extStorage, fileNameView+".sql", conf.CompressType)
 }
 
+// WriteTableData writes table data to a file with retry
 func (w *Writer) WriteTableData(meta TableMeta, ir TableDataIR, currentChunk int) error {
 	ctx, conf, conn := w.ctx, w.conf, w.conn
 	retryTime := 0
@@ -157,9 +165,10 @@ func (w *Writer) WriteTableData(meta TableMeta, ir TableDataIR, currentChunk int
 				errorCount.With(conf.Labels).Inc()
 			}
 		}()
-		retryTime += 1
+		retryTime++
 		log.Debug("trying to dump table chunk", zap.Int("retryTime", retryTime), zap.String("db", meta.DatabaseName()),
 			zap.String("table", meta.TableName()), zap.Int("chunkIndex", currentChunk), zap.NamedError("lastError", lastErr))
+		// don't rebuild connection when dump for the first time
 		if retryTime > 1 {
 			conn, err = w.rebuildConnFn(conn)
 			if err != nil {
@@ -171,11 +180,11 @@ func (w *Writer) WriteTableData(meta TableMeta, ir TableDataIR, currentChunk int
 			return
 		}
 		defer ir.Close()
-		return w.writeTableData(ctx, meta, ir, currentChunk)
+		return w.tryToWriteTableData(ctx, meta, ir, currentChunk)
 	}, newDumpChunkBackoffer(canRebuildConn(conf.Consistency, conf.TransactionalConsistency)))
 }
 
-func (w *Writer) writeTableData(ctx context.Context, meta TableMeta, ir TableDataIR, curChkIdx int) error {
+func (w *Writer) tryToWriteTableData(ctx context.Context, meta TableMeta, ir TableDataIR, curChkIdx int) error {
 	conf, format := w.conf, w.fileFmt
 	namer := newOutputFileNamer(meta, curChkIdx, conf.Rows != UnspecifiedSize, conf.FileSize != UnspecifiedSize)
 	fileName, err := namer.NextName(conf.OutputFileTemplate, w.fileFmt.Extension())
@@ -209,7 +218,7 @@ func (w *Writer) writeTableData(ctx context.Context, meta TableMeta, ir TableDat
 func writeMetaToFile(ctx context.Context, target, metaSQL string, s storage.ExternalStorage, path string, compressType storage.CompressType) error {
 	fileWriter, tearDown, err := buildFileWriter(ctx, s, path, compressType)
 	if err != nil {
-		return err
+		return errors.Trace(err)
 	}
 	defer tearDown(ctx)
 
@@ -243,11 +252,12 @@ func newOutputFileNamer(meta TableMeta, chunkIdx int, rows, fileSize bool) *outp
 	}
 	o.ChunkIndex = chunkIdx
 	o.FileIndex = 0
-	if rows && fileSize {
+	switch {
+	case rows && fileSize:
 		o.format = "%09d%04d"
-	} else if fileSize {
+	case fileSize:
 		o.format = "%09[2]d"
-	} else {
+	default:
 		o.format = "%09[1]d"
 	}
 	return o
@@ -256,7 +266,7 @@ func newOutputFileNamer(meta TableMeta, chunkIdx int, rows, fileSize bool) *outp
 func (namer *outputFileNamer) render(tmpl *template.Template, subName string) (string, error) {
 	var bf bytes.Buffer
 	if err := tmpl.ExecuteTemplate(&bf, subName, namer); err != nil {
-		return "", err
+		return "", errors.Trace(err)
 	}
 	return bf.String(), nil
 }
diff --git a/v4/export/writer_util.go b/v4/export/writer_util.go
old mode 100644
new mode 100755
index cb14417..3ef9660
--- a/v4/export/writer_util.go
+++ b/v4/export/writer_util.go
@@ -117,6 +117,7 @@ func (b *writerPipe) ShouldSwitchStatement() bool {
 		(b.statementSizeLimit != UnspecifiedSize && b.currentStatementSize >= b.statementSizeLimit)
 }
 
+// WriteMeta writes MetaIR to a storage.Writer
 func WriteMeta(ctx context.Context, meta MetaIR, w storage.Writer) error {
 	log.Debug("start dumping meta data", zap.String("target", meta.TargetName()))
 
@@ -135,6 +136,7 @@ func WriteMeta(ctx context.Context, meta MetaIR, w storage.Writer) error {
 	return nil
 }
 
+// WriteInsert writes TableDataIR to a storage.Writer in sql type
 func WriteInsert(pCtx context.Context, cfg *Config, meta TableMeta, tblIR TableDataIR, w storage.Writer) error {
 	fileRowIter := tblIR.Rows()
 	if !fileRowIter.HasNext() {
@@ -194,18 +196,17 @@ func WriteInsert(pCtx context.Context, cfg *Config, meta TableMeta, tblIR TableD
 		wp.AddFileSize(insertStatementPrefixLen)
 
 		for fileRowIter.HasNext() {
-
 			lastBfSize := bf.Len()
 			if selectedField != "" {
 				if err = fileRowIter.Decode(row); err != nil {
 					log.Error("scanning from sql.Row failed", zap.Error(err))
-					return err
+					return errors.Trace(err)
 				}
 				row.WriteToBuffer(bf, escapeBackSlash)
 			} else {
 				bf.WriteString("()")
 			}
-			counter += 1
+			counter++
 			wp.AddFileSize(uint64(bf.Len()-lastBfSize) + 2) // 2 is for ",\n" and ";\n"
 			failpoint.Inject("ChaosBrokenMySQLConn", func(_ failpoint.Value) {
 				failpoint.Return(errors.New("connection is closed"))
@@ -222,7 +223,7 @@ func WriteInsert(pCtx context.Context, cfg *Config, meta TableMeta, tblIR TableD
 				select {
 				case <-pCtx.Done():
 					return pCtx.Err()
-				case err := <-wp.errCh:
+				case err = <-wp.errCh:
 					return err
 				case wp.input <- bf:
 					bf = pool.Get().(*bytes.Buffer)
@@ -254,11 +255,12 @@ func WriteInsert(pCtx context.Context, cfg *Config, meta TableMeta, tblIR TableD
 	summary.CollectSuccessUnit("total rows", 1, counter)
 	finishedRowsCounter.With(cfg.Labels).Add(float64(counter - lastCounter))
 	if err = fileRowIter.Error(); err != nil {
-		return err
+		return errors.Trace(err)
 	}
 	return wp.Error()
 }
 
+// WriteInsertInCsv writes TableDataIR to a storage.Writer in csv type
 func WriteInsertInCsv(pCtx context.Context, cfg *Config, meta TableMeta, tblIR TableDataIR, w storage.Writer) error {
 	fileRowIter := tblIR.Rows()
 	if !fileRowIter.HasNext() {
@@ -316,11 +318,11 @@ func WriteInsertInCsv(pCtx context.Context, cfg *Config, meta TableMeta, tblIR T
 		if selectedFields != "" {
 			if err = fileRowIter.Decode(row); err != nil {
 				log.Error("scanning from sql.Row failed", zap.Error(err))
-				return err
+				return errors.Trace(err)
 			}
 			row.WriteToBufferInCsv(bf, escapeBackSlash, opt)
 		}
-		counter += 1
+		counter++
 		wp.currentFileSize += uint64(bf.Len()-lastBfSize) + 1 // 1 is for "\n"
 
 		bf.WriteByte('\n')
@@ -328,7 +330,7 @@ func WriteInsertInCsv(pCtx context.Context, cfg *Config, meta TableMeta, tblIR T
 			select {
 			case <-pCtx.Done():
 				return pCtx.Err()
-			case err := <-wp.errCh:
+			case err = <-wp.errCh:
 				return err
 			case wp.input <- bf:
 				bf = pool.Get().(*bytes.Buffer)
@@ -358,7 +360,7 @@ func WriteInsertInCsv(pCtx context.Context, cfg *Config, meta TableMeta, tblIR T
 	summary.CollectSuccessUnit("total rows", 1, counter)
 	finishedRowsCounter.With(cfg.Labels).Add(float64(counter - lastCounter))
 	if err = fileRowIter.Error(); err != nil {
-		return err
+		return errors.Trace(err)
 	}
 	return wp.Error()
 }
@@ -375,7 +377,7 @@ func write(ctx context.Context, writer storage.Writer, str string) error {
 			zap.String("string", str[:outputLength]),
 			zap.Error(err))
 	}
-	return err
+	return errors.Trace(err)
 }
 
 func writeBytes(ctx context.Context, writer storage.Writer, p []byte) error {
@@ -391,7 +393,7 @@ func writeBytes(ctx context.Context, writer storage.Writer, p []byte) error {
 			zap.String("writer", fmt.Sprintf("%#v", writer)),
 			zap.Error(err))
 	}
-	return err
+	return errors.Trace(err)
 }
 
 func buildFileWriter(ctx context.Context, s storage.ExternalStorage, fileName string, compressType storage.CompressType) (storage.Writer, func(ctx context.Context), error) {
@@ -402,7 +404,7 @@ func buildFileWriter(ctx context.Context, s storage.ExternalStorage, fileName st
 		log.Error("open file failed",
 			zap.String("path", fullPath),
 			zap.Error(err))
-		return nil, nil, err
+		return nil, nil, errors.Trace(err)
 	}
 	writer := storage.NewUploaderWriter(uploader, hardcodedS3ChunkSize, compressType)
 	log.Debug("opened file", zap.String("path", fullPath))
@@ -411,6 +413,7 @@ func buildFileWriter(ctx context.Context, s storage.ExternalStorage, fileName st
 		if err == nil {
 			return
 		}
+		err = errors.Trace(err)
 		log.Error("close file failed",
 			zap.String("path", fullPath),
 			zap.Error(err))
@@ -452,6 +455,8 @@ func buildInterceptFileWriter(s storage.ExternalStorage, fileName string, compre
 	return fileWriter, tearDownRoutine
 }
 
+// LazyStringWriter is an interceptor of io.StringWriter,
+// will lazily create file the first time StringWriter need to write something.
 type LazyStringWriter struct {
 	initRoutine func() error
 	sync.Once
@@ -459,6 +464,7 @@ type LazyStringWriter struct {
 	err error
 }
 
+// WriteString implements io.StringWriter. It check whether writer has written something and init a file at first time
 func (l *LazyStringWriter) WriteString(str string) (int, error) {
 	l.Do(func() { l.err = l.initRoutine() })
 	if l.err != nil {
@@ -487,12 +493,13 @@ func newWriterError(err error) error {
 type InterceptFileWriter struct {
 	storage.Writer
 	sync.Once
+	SomethingIsWritten bool
+
 	initRoutine func(context.Context) error
 	err         error
-
-	SomethingIsWritten bool
 }
 
+// Write implements storage.Writer.Write. It check whether writer has written something and init a file at first time
 func (w *InterceptFileWriter) Write(ctx context.Context, p []byte) (int, error) {
 	w.Do(func() { w.err = w.initRoutine(ctx) })
 	if len(p) > 0 {
@@ -505,6 +512,7 @@ func (w *InterceptFileWriter) Write(ctx context.Context, p []byte) (int, error)
 	return n, newWriterError(err)
 }
 
+// Close closes the InterceptFileWriter
 func (w *InterceptFileWriter) Close(ctx context.Context) error {
 	return w.Writer.Close(ctx)
 }
@@ -535,18 +543,28 @@ func compressFileSuffix(compressType storage.CompressType) string {
 type FileFormat int32
 
 const (
+	// FileFormatUnknown indicates the given file type is unknown
 	FileFormatUnknown FileFormat = iota
+	// FileFormatSQLText indicates the given file type is sql type
 	FileFormatSQLText
+	// FileFormatCSV indicates the given file type is csv type
 	FileFormatCSV
 )
 
+const (
+	// FileFormatSQLTextString indicates the string/suffix of sql type file
+	FileFormatSQLTextString = "sql"
+	// FileFormatCSVString indicates the string/suffix of csv type file
+	FileFormatCSVString = "csv"
+)
+
 // String implement Stringer.String method.
 func (f FileFormat) String() string {
 	switch f {
 	case FileFormatSQLText:
-		return "SQL"
+		return strings.ToUpper(FileFormatSQLTextString)
 	case FileFormatCSV:
-		return "CSV"
+		return strings.ToUpper(FileFormatCSVString)
 	default:
 		return "unknown"
 	}
@@ -558,14 +576,15 @@ func (f FileFormat) String() string {
 func (f FileFormat) Extension() string {
 	switch f {
 	case FileFormatSQLText:
-		return "sql"
+		return FileFormatSQLTextString
 	case FileFormatCSV:
-		return "csv"
+		return FileFormatCSVString
 	default:
 		return "unknown_format"
 	}
 }
 
+// WriteInsert writes TableDataIR to a storage.Writer in sql/csv type
 func (f FileFormat) WriteInsert(pCtx context.Context, cfg *Config, meta TableMeta, tblIR TableDataIR, w storage.Writer) error {
 	switch f {
 	case FileFormatSQLText:
diff --git a/v4/log/log.go b/v4/log/log.go
index fc522bc..f134bcb 100644
--- a/v4/log/log.go
+++ b/v4/log/log.go
@@ -14,6 +14,7 @@ var (
 	appLevel  = zap.NewAtomicLevel()
 )
 
+// Logger wraps the zap logger.
 type Logger struct {
 	*zap.Logger
 }
@@ -40,6 +41,7 @@ type Config struct {
 	Format string `toml:"format" json:"format"`
 }
 
+// InitAppLogger inits the wrapped logger from config.
 func InitAppLogger(cfg *Config) error {
 	logger, props, err := pclog.InitLogger(&pclog.Config{
 		Level: cfg.Level,
@@ -60,34 +62,42 @@ func InitAppLogger(cfg *Config) error {
 	return nil
 }
 
+// SetAppLogger sets the wrapped logger from config.
 func SetAppLogger(logger *zap.Logger) {
 	appLogger = Logger{logger}
 }
 
+// ChangeAppLogLevel changes the wrapped logger's log level.
 func ChangeAppLogLevel(level zapcore.Level) {
 	appLevel.SetLevel(level)
 }
 
+// Info wraps *zap.Logger's Info function.
 func Info(msg string, fields ...zap.Field) {
 	appLogger.Info(msg, fields...)
 }
 
+// Warn wraps *zap.Logger's Warn function.
 func Warn(msg string, fields ...zap.Field) {
 	appLogger.Warn(msg, fields...)
 }
 
+// Error wraps *zap.Logger's Error function.
 func Error(msg string, fields ...zap.Field) {
 	appLogger.Error(msg, fields...)
 }
 
+// Debug wraps *zap.Logger's Debug function.
 func Debug(msg string, fields ...zap.Field) {
 	appLogger.Debug(msg, fields...)
 }
 
+// Fatal wraps *zap.Logger's Fatal function.
 func Fatal(msg string, fields ...zap.Field) {
 	appLogger.Fatal(msg, fields...)
 }
 
+// Panic wraps *zap.Logger's Panic function.
 func Panic(msg string, fields ...zap.Field) {
 	appLogger.Panic(msg, fields...)
 }


Test patch:
diff --git a/v4/export/ir_impl_test.go b/v4/export/ir_impl_test.go
index fb2e2cf..8241078 100644
--- a/v4/export/ir_impl_test.go
+++ b/v4/export/ir_impl_test.go
@@ -74,6 +74,7 @@ func (s *testIRImplSuite) TestChunkRowIter(c *C) {
 	mock.ExpectQuery("SELECT a, b FROM t").WillReturnRows(expectedRows)
 	rows, err := db.Query("SELECT a, b FROM t")
 	c.Assert(err, IsNil)
+	defer rows.Close()
 
 	var (
 		testFileSize      uint64 = 200
diff --git a/v4/export/metadata_test.go b/v4/export/metadata_test.go
index ed1e0c9..8583a3f 100644
--- a/v4/export/metadata_test.go
+++ b/v4/export/metadata_test.go
@@ -14,6 +14,12 @@ import (
 
 var _ = Suite(&testMetaDataSuite{})
 
+const (
+	logFile = "ON.000001"
+	pos     = "7502"
+	gtidSet = "6ce40be3-e359-11e9-87e0-36933cb0ca5a:1-29"
+)
+
 type testMetaDataSuite struct{}
 
 func (s *testMetaDataSuite) TestMysqlMetaData(c *C) {
@@ -23,9 +29,6 @@ func (s *testMetaDataSuite) TestMysqlMetaData(c *C) {
 	conn, err := db.Conn(context.Background())
 	c.Assert(err, IsNil)
 
-	logFile := "ON.000001"
-	pos := "7502"
-	gtidSet := "6ce40be3-e359-11e9-87e0-36933cb0ca5a:1-29"
 	rows := sqlmock.NewRows([]string{"File", "Position", "Binlog_Do_DB", "Binlog_Ignore_DB", "Executed_Gtid_Set"}).
 		AddRow(logFile, pos, "", "", gtidSet)
 	mock.ExpectQuery("SHOW MASTER STATUS").WillReturnRows(rows)
@@ -57,9 +60,6 @@ func (s *testMetaDataSuite) TestMetaDataAfterConn(c *C) {
 	conn, err := db.Conn(context.Background())
 	c.Assert(err, IsNil)
 
-	logFile := "ON.000001"
-	pos := "7502"
-	gtidSet := "6ce40be3-e359-11e9-87e0-36933cb0ca5a:1-29"
 	rows := sqlmock.NewRows([]string{"File", "Position", "Binlog_Do_DB", "Binlog_Ignore_DB", "Executed_Gtid_Set"}).
 		AddRow(logFile, pos, "", "", gtidSet)
 	pos2 := "7510"
@@ -94,9 +94,6 @@ func (s *testMetaDataSuite) TestMysqlWithFollowersMetaData(c *C) {
 	conn, err := db.Conn(context.Background())
 	c.Assert(err, IsNil)
 
-	logFile := "ON.000001"
-	pos := "7502"
-	gtidSet := "6ce40be3-e359-11e9-87e0-36933cb0ca5a:1-29"
 	rows := sqlmock.NewRows([]string{"File", "Position", "Binlog_Do_DB", "Binlog_Ignore_DB", "Executed_Gtid_Set"}).
 		AddRow(logFile, pos, "", "", gtidSet)
 	followerRows := sqlmock.NewRows([]string{"exec_master_log_pos", "relay_master_log_file", "master_host", "Executed_Gtid_Set", "Seconds_Behind_Master"}).
@@ -127,9 +124,6 @@ func (s *testMetaDataSuite) TestMysqlWithNullFollowersMetaData(c *C) {
 	conn, err := db.Conn(context.Background())
 	c.Assert(err, IsNil)
 
-	logFile := "ON.000001"
-	pos := "7502"
-	gtidSet := "6ce40be3-e359-11e9-87e0-36933cb0ca5a:1-29"
 	rows := sqlmock.NewRows([]string{"File", "Position", "Binlog_Do_DB", "Binlog_Ignore_DB", "Executed_Gtid_Set"}).
 		AddRow(logFile, pos, "", "", gtidSet)
 	mock.ExpectQuery("SHOW MASTER STATUS").WillReturnRows(rows)
@@ -176,9 +170,6 @@ func (s *testMetaDataSuite) TestMariaDBWithFollowersMetaData(c *C) {
 	conn, err := db.Conn(context.Background())
 	c.Assert(err, IsNil)
 
-	logFile := "ON.000001"
-	pos := "7502"
-	gtidSet := "6ce40be3-e359-11e9-87e0-36933cb0ca5a:1-29"
 	rows := sqlmock.NewRows([]string{"File", "Position", "Binlog_Do_DB", "Binlog_Ignore_DB", "Executed_Gtid_Set"}).
 		AddRow(logFile, pos, "", "", gtidSet)
 	followerRows := sqlmock.NewRows([]string{"exec_master_log_pos", "relay_master_log_file", "master_host", "Executed_Gtid_Set", "connection_name", "Seconds_Behind_Master"}).
diff --git a/v4/export/prepare_test.go b/v4/export/prepare_test.go
index 1b96c19..9c73a4e 100644
--- a/v4/export/prepare_test.go
+++ b/v4/export/prepare_test.go
@@ -70,7 +70,7 @@ func (s *testPrepareSuite) TestListAllTables(c *C) {
 		AppendTables("db2", "t3", "t4", "t5").
 		AppendViews("db3", "t6", "t7", "t8")
 
-	var dbNames []databaseName
+	dbNames := make([]databaseName, 0, len(data))
 	rows := sqlmock.NewRows([]string{"table_schema", "table_name"})
 	for dbName, tableInfos := range data {
 		dbNames = append(dbNames, dbName)
@@ -115,14 +115,14 @@ func (s *testPrepareSuite) TestListAllTables(c *C) {
 func (s *testPrepareSuite) TestConfigValidation(c *C) {
 	conf := DefaultConfig()
 	conf.Where = "id < 5"
-	conf.Sql = "select * from t where id > 3"
+	conf.SQL = "select * from t where id > 3"
 	c.Assert(validateSpecifiedSQL(conf), ErrorMatches, "can't specify both --sql and --where at the same time. Please try to combine them into --sql")
 	conf.Where = ""
 	c.Assert(validateSpecifiedSQL(conf), IsNil)
 
-	conf.FileType = "sql"
+	conf.FileType = FileFormatSQLTextString
 	c.Assert(validateFileFormat(conf), IsNil)
-	conf.FileType = "csv"
+	conf.FileType = FileFormatCSVString
 	c.Assert(validateFileFormat(conf), IsNil)
 	conf.FileType = "rand_str"
 	c.Assert(validateFileFormat(conf), ErrorMatches, "unknown config.FileType 'rand_str'")
diff --git a/v4/export/sql_test.go b/v4/export/sql_test.go
index 2b7f2dd..7512cc1 100644
--- a/v4/export/sql_test.go
+++ b/v4/export/sql_test.go
@@ -156,7 +156,7 @@ func (s *testSQLSuite) TestBuildSelectAllQuery(c *C) {
 
 	// Test when config.SortByPk is disabled.
 	mockConf.SortByPk = false
-	for tp := ServerTypeUnknown; tp < ServerTypeAll; tp += 1 {
+	for tp := ServerTypeUnknown; tp < ServerTypeAll; tp++ {
 		mockConf.ServerInfo.ServerType = ServerType(tp)
 		cmt := Commentf("current server type: ", tp)
 
@@ -247,7 +247,7 @@ func (s *testSQLSuite) TestBuildOrderByClause(c *C) {
 
 	// Test when config.SortByPk is disabled.
 	mockConf.SortByPk = false
-	for tp := ServerTypeUnknown; tp < ServerTypeAll; tp += 1 {
+	for tp := ServerTypeUnknown; tp < ServerTypeAll; tp++ {
 		mockConf.ServerInfo.ServerType = ServerType(tp)
 		cmt := Commentf("current server type: ", tp)
 
diff --git a/v4/export/sql_type_test.go b/v4/export/sql_type_test.go
index f407122..59c3ad9 100644
--- a/v4/export/sql_type_test.go
+++ b/v4/export/sql_type_test.go
@@ -8,11 +8,11 @@ import (
 	. "github.com/pingcap/check"
 )
 
-var _ = Suite(&testSqlByteSuite{})
+var _ = Suite(&testSQLByteSuite{})
 
-type testSqlByteSuite struct{}
+type testSQLByteSuite struct{}
 
-func (s *testSqlByteSuite) TestEscape(c *C) {
+func (s *testSQLByteSuite) TestEscape(c *C) {
 	var bf bytes.Buffer
 	str := []byte(`MWQeWw""'\rNmtGxzGp`)
 	expectStrBackslash := `MWQeWw\"\"\'\\rNmtGxzGp`
diff --git a/v4/export/test_util.go b/v4/export/test_util.go
index bf9bc39..0a22022 100644
--- a/v4/export/test_util.go
+++ b/v4/export/test_util.go
@@ -29,25 +29,6 @@ func (m *mockPoisonWriter) Close(ctx context.Context) error {
 	return nil
 }
 
-type mockSQLRowIterator struct {
-	idx  int
-	data [][]sql.NullString
-}
-
-func (m *mockSQLRowIterator) Next(sp RowReceiver) error {
-	args := make([]interface{}, len(m.data[m.idx]))
-	sp.BindAddress(args)
-	for i := range args {
-		*(args[i]).(*sql.NullString) = m.data[m.idx][i]
-	}
-	m.idx += 1
-	return nil
-}
-
-func (m *mockSQLRowIterator) HasNext() bool {
-	return m.idx < len(m.data)
-}
-
 type mockMetaIR struct {
 	tarName string
 	meta    string
diff --git a/v4/export/writer_test.go b/v4/export/writer_test.go
index cda5fad..14e1e7a 100644
--- a/v4/export/writer_test.go
+++ b/v4/export/writer_test.go
@@ -4,7 +4,6 @@ package export
 
 import (
 	"context"
-	"database/sql"
 	"database/sql/driver"
 	"io/ioutil"
 	"os"
@@ -17,24 +16,7 @@ import (
 
 var _ = Suite(&testWriterSuite{})
 
-type testWriterSuite struct {
-	pool *connectionsPool
-}
-
-func (s *testWriterSuite) SetUpSuite(c *C) {
-	s.pool = newMockConnectPool(c)
-}
-
-func newMockConnectPool(c *C) *connectionsPool {
-	db, _, err := sqlmock.New()
-	c.Assert(err, IsNil)
-	conn, err := db.Conn(context.Background())
-	c.Assert(err, IsNil)
-	connectPool := &connectionsPool{conns: make(chan *sql.Conn, 1)}
-	connectPool.releaseConn(conn)
-	connectPool.createdConns = []*sql.Conn{conn}
-	return connectPool
-}
+type testWriterSuite struct{}
 
 func (s *testWriterSuite) newWriter(conf *Config, c *C) *Writer {
 	b, err := storage.ParseBackend(conf.OutputDirPath, &conf.BackendOptions)
@@ -45,7 +27,7 @@ func (s *testWriterSuite) newWriter(conf *Config, c *C) *Writer {
 	c.Assert(err, IsNil)
 	conn, err := db.Conn(context.Background())
 	c.Assert(err, IsNil)
-	return NewWriter(0, context.Background(), conf, conn, extStore)
+	return NewWriter(context.Background(), 0, conf, conn, extStore)
 }
 
 func (s *testWriterSuite) TestWriteDatabaseMeta(c *C) {
@@ -190,7 +172,7 @@ func (s *testWriterSuite) TestWriteTableDataWithFileSize(c *C) {
 	}
 
 	for p, expected := range cases {
-		p := path.Join(dir, p)
+		p = path.Join(dir, p)
 		_, err := os.Stat(p)
 		c.Assert(err, IsNil)
 		bytes, err := ioutil.ReadFile(p)
@@ -241,7 +223,7 @@ func (s *testWriterSuite) TestWriteTableDataWithFileSizeAndRows(c *C) {
 	}
 
 	for p, expected := range cases {
-		p := path.Join(dir, p)
+		p = path.Join(dir, p)
 		_, err = os.Stat(p)
 		c.Assert(err, IsNil)
 		bytes, err := ioutil.ReadFile(p)
@@ -291,11 +273,11 @@ func (s *testWriterSuite) TestWriteTableDataWithStatementSize(c *C) {
 	}
 
 	for p, expected := range cases {
-		p := path.Join(config.OutputDirPath, p)
+		p = path.Join(config.OutputDirPath, p)
 		_, err = os.Stat(p)
 		c.Assert(err, IsNil)
-		bytes, err := ioutil.ReadFile(p)
-		c.Assert(err, IsNil)
+		bytes, err1 := ioutil.ReadFile(p)
+		c.Assert(err1, IsNil)
 		c.Assert(string(bytes), Equals, expected)
 	}
 
@@ -331,7 +313,7 @@ func (s *testWriterSuite) TestWriteTableDataWithStatementSize(c *C) {
 	c.Assert(writer.WriteTableData(tableIR, tableIR, 0), IsNil)
 	c.Assert(err, IsNil)
 	for p, expected := range cases {
-		p := path.Join(config.OutputDirPath, p)
+		p = path.Join(config.OutputDirPath, p)
 		_, err = os.Stat(p)
 		c.Assert(err, IsNil)
 		bytes, err := ioutil.ReadFile(p)
diff --git a/v4/export/writer_util_test.go b/v4/export/writer_util_test.go
index a3e0b1e..4374e76 100644
--- a/v4/export/writer_util_test.go
+++ b/v4/export/writer_util_test.go
@@ -4,18 +4,18 @@ package export
 
 import (
 	"context"
-	"errors"
+	"database/sql/driver"
 	"fmt"
 	"strings"
 	"testing"
 
-	"database/sql/driver"
-
 	"github.com/pingcap/br/pkg/storage"
 	. "github.com/pingcap/check"
+	"github.com/pingcap/errors"
 )
 
 func TestT(t *testing.T) {
+	initColTypeRowReceiverMap()
 	TestingT(t)
 }
 
@@ -119,7 +119,7 @@ func (s *testUtilSuite) TestWriteInsertInCsv(c *C) {
 
 	// test nullValue
 	opt := &csvOption{separator: []byte(","), delimiter: doubleQuotationMark, nullValue: "\\N"}
-	conf := configForWriteCSV(true, opt, UnspecifiedSize)
+	conf := configForWriteCSV(true, opt)
 	err := WriteInsertInCsv(context.Background(), conf, tableIR, tableIR, bf)
 	c.Assert(err, IsNil)
 	expected := "1,\"male\",\"bob@mail.com\",\"020-1234\",\\N\n" +
@@ -132,7 +132,7 @@ func (s *testUtilSuite) TestWriteInsertInCsv(c *C) {
 	bf.Reset()
 	opt.delimiter = quotationMark
 	tableIR = newMockTableIR("test", "employee", data, nil, colTypes)
-	conf = configForWriteCSV(true, opt, UnspecifiedSize)
+	conf = configForWriteCSV(true, opt)
 	err = WriteInsertInCsv(context.Background(), conf, tableIR, tableIR, bf)
 	c.Assert(err, IsNil)
 	expected = "1,'male','bob@mail.com','020-1234',\\N\n" +
@@ -145,7 +145,7 @@ func (s *testUtilSuite) TestWriteInsertInCsv(c *C) {
 	bf.Reset()
 	opt.separator = []byte(";")
 	tableIR = newMockTableIR("test", "employee", data, nil, colTypes)
-	conf = configForWriteCSV(true, opt, UnspecifiedSize)
+	conf = configForWriteCSV(true, opt)
 	err = WriteInsertInCsv(context.Background(), conf, tableIR, tableIR, bf)
 	c.Assert(err, IsNil)
 	expected = "1;'male';'bob@mail.com';'020-1234';\\N\n" +
@@ -160,7 +160,7 @@ func (s *testUtilSuite) TestWriteInsertInCsv(c *C) {
 	opt.delimiter = []byte("ma")
 	tableIR = newMockTableIR("test", "employee", data, nil, colTypes)
 	tableIR.colNames = []string{"id", "gender", "email", "phone_number", "status"}
-	conf = configForWriteCSV(false, opt, UnspecifiedSize)
+	conf = configForWriteCSV(false, opt)
 	err = WriteInsertInCsv(context.Background(), conf, tableIR, tableIR, bf)
 	c.Assert(err, IsNil)
 	expected = "maidma&;,?magenderma&;,?maemamailma&;,?maphone_numberma&;,?mastatusma\n" +
@@ -217,12 +217,12 @@ func configForWriteSQL(fileSize, statementSize uint64) *Config {
 	return &Config{FileSize: fileSize, StatementSize: statementSize}
 }
 
-func configForWriteCSV(noHeader bool, opt *csvOption, fileSizeLimit uint64) *Config {
+func configForWriteCSV(noHeader bool, opt *csvOption) *Config {
 	return &Config{
 		NoHeader:     noHeader,
 		CsvNullValue: opt.nullValue,
 		CsvDelimiter: string(opt.delimiter),
 		CsvSeparator: string(opt.separator),
-		FileSize:     fileSizeLimit,
+		FileSize:     UnspecifiedSize,
 	}
 }