Repository: zeromicro/go-zero
Pull request #2368 (2022-09-07 09:21:36)

fix: issue #2359


Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 7912ec60..9d95ef51 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -14,7 +14,7 @@ jobs:
       - name: Set up Go 1.x
         uses: actions/setup-go@v2
         with:
-          go-version: ^1.15
+          go-version: ^1.16
         id: go
 
       - name: Check out code into the Go module directory
@@ -43,7 +43,7 @@ jobs:
       - name: Set up Go 1.x
         uses: actions/setup-go@v2
         with:
-          go-version: ^1.15
+          go-version: ^1.16
 
       - name: Checkout codebase
         uses: actions/checkout@v3
diff --git a/core/codec/rsa.go b/core/codec/rsa.go
index 4aa2bf83..5a54b838 100644
--- a/core/codec/rsa.go
+++ b/core/codec/rsa.go
@@ -7,7 +7,7 @@ import (
 	"encoding/base64"
 	"encoding/pem"
 	"errors"
-	"io/ioutil"
+	"os"
 )
 
 var (
@@ -48,7 +48,7 @@ type (
 
 // NewRsaDecrypter returns a RsaDecrypter with the given file.
 func NewRsaDecrypter(file string) (RsaDecrypter, error) {
-	content, err := ioutil.ReadFile(file)
+	content, err := os.ReadFile(file)
 	if err != nil {
 		return nil, err
 	}
diff --git a/core/conf/config.go b/core/conf/config.go
index aa5f4694..f9532e90 100644
--- a/core/conf/config.go
+++ b/core/conf/config.go
@@ -2,7 +2,6 @@ package conf
 
 import (
 	"fmt"
-	"io/ioutil"
 	"log"
 	"os"
 	"path"
@@ -20,7 +19,7 @@ var loaders = map[string]func([]byte, interface{}) error{
 
 // Load loads config into v from file, .json, .yaml and .yml are acceptable.
 func Load(file string, v interface{}, opts ...Option) error {
-	content, err := ioutil.ReadFile(file)
+	content, err := os.ReadFile(file)
 	if err != nil {
 		return err
 	}
diff --git a/core/discov/internal/accountmanager.go b/core/discov/internal/accountmanager.go
index 47b5e243..55bd9133 100644
--- a/core/discov/internal/accountmanager.go
+++ b/core/discov/internal/accountmanager.go
@@ -3,7 +3,7 @@ package internal
 import (
 	"crypto/tls"
 	"crypto/x509"
-	"io/ioutil"
+	"os"
 	"sync"
 )
 
@@ -37,7 +37,7 @@ func AddTLS(endpoints []string, certFile, certKeyFile, caFile string, insecureSk
 		return err
 	}
 
-	caData, err := ioutil.ReadFile(caFile)
+	caData, err := os.ReadFile(caFile)
 	if err != nil {
 		return err
 	}
diff --git a/core/fs/temps.go b/core/fs/temps.go
index 796875bc..30bee2a8 100644
--- a/core/fs/temps.go
+++ b/core/fs/temps.go
@@ -1,7 +1,6 @@
 package fs
 
 import (
-	"io/ioutil"
 	"os"
 
 	"github.com/zeromicro/go-zero/core/hash"
@@ -12,12 +11,12 @@ import (
 // The file is kept as open, the caller should close the file handle,
 // and remove the file by name.
 func TempFileWithText(text string) (*os.File, error) {
-	tmpfile, err := ioutil.TempFile(os.TempDir(), hash.Md5Hex([]byte(text)))
+	tmpfile, err := os.CreateTemp(os.TempDir(), hash.Md5Hex([]byte(text)))
 	if err != nil {
 		return nil, err
 	}
 
-	if err := ioutil.WriteFile(tmpfile.Name(), []byte(text), os.ModeTemporary); err != nil {
+	if err := os.WriteFile(tmpfile.Name(), []byte(text), os.ModeTemporary); err != nil {
 		return nil, err
 	}
 
diff --git a/core/iox/read.go b/core/iox/read.go
index 481173e5..530597fc 100644
--- a/core/iox/read.go
+++ b/core/iox/read.go
@@ -4,7 +4,6 @@ import (
 	"bufio"
 	"bytes"
 	"io"
-	"io/ioutil"
 	"os"
 	"strings"
 )
@@ -26,7 +25,7 @@ type (
 func DupReadCloser(reader io.ReadCloser) (io.ReadCloser, io.ReadCloser) {
 	var buf bytes.Buffer
 	tee := io.TeeReader(reader, &buf)
-	return ioutil.NopCloser(tee), ioutil.NopCloser(&buf)
+	return io.NopCloser(tee), io.NopCloser(&buf)
 }
 
 // KeepSpace customizes the reading functions to keep leading and tailing spaces.
@@ -54,7 +53,7 @@ func ReadBytes(reader io.Reader, buf []byte) error {
 
 // ReadText reads content from the given file with leading and tailing spaces trimmed.
 func ReadText(filename string) (string, error) {
-	content, err := ioutil.ReadFile(filename)
+	content, err := os.ReadFile(filename)
 	if err != nil {
 		return "", err
 	}
diff --git a/core/trace/agent.go b/core/trace/agent.go
index 9c19cc82..fdf4d87d 100644
--- a/core/trace/agent.go
+++ b/core/trace/agent.go
@@ -10,7 +10,6 @@ import (
 	"go.opentelemetry.io/otel"
 	"go.opentelemetry.io/otel/exporters/jaeger"
 	"go.opentelemetry.io/otel/exporters/zipkin"
-	"go.opentelemetry.io/otel/propagation"
 	"go.opentelemetry.io/otel/sdk/resource"
 	sdktrace "go.opentelemetry.io/otel/sdk/trace"
 	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
@@ -66,7 +65,7 @@ func startAgent(c Config) error {
 	opts := []sdktrace.TracerProviderOption{
 		// Set the sampling rate based on the parent span to 100%
 		sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(c.Sampler))),
-		// Record information about this application in an Resource.
+		// Record information about this application in a Resource.
 		sdktrace.WithResource(resource.NewSchemaless(semconv.ServiceNameKey.String(c.Name))),
 	}
 
@@ -83,8 +82,6 @@ func startAgent(c Config) error {
 
 	tp = sdktrace.NewTracerProvider(opts...)
 	otel.SetTracerProvider(tp)
-	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
-		propagation.TraceContext{}, propagation.Baggage{}))
 	otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
 		logx.Errorf("[otel] error: %v", err)
 	}))
diff --git a/core/trace/propagation.go b/core/trace/propagation.go
new file mode 100644
index 00000000..e0920039
--- /dev/null
+++ b/core/trace/propagation.go
@@ -0,0 +1,11 @@
+package trace
+
+import (
+	"go.opentelemetry.io/otel"
+	"go.opentelemetry.io/otel/propagation"
+)
+
+func init() {
+	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
+		propagation.TraceContext{}, propagation.Baggage{}))
+}
diff --git a/go.mod b/go.mod
index 0e1eee19..cc9a2ecf 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/zeromicro/go-zero
 go 1.16
 
 require (
-	github.com/ClickHouse/clickhouse-go/v2 v2.2.0
+	github.com/ClickHouse/clickhouse-go/v2 v2.0.14
 	github.com/DATA-DOG/go-sqlmock v1.5.0
 	github.com/alicebob/miniredis/v2 v2.23.0
 	github.com/fatih/color v1.13.0
@@ -16,7 +16,7 @@ require (
 	github.com/golang/protobuf v1.5.2
 	github.com/google/uuid v1.3.0
 	github.com/jhump/protoreflect v1.12.0
-	github.com/lib/pq v1.10.6
+	github.com/lib/pq v1.10.7
 	github.com/olekukonko/tablewriter v0.0.5
 	github.com/pelletier/go-toml/v2 v2.0.5
 	github.com/prometheus/client_golang v1.13.0
@@ -24,14 +24,14 @@ require (
 	github.com/stretchr/testify v1.8.0
 	go.etcd.io/etcd/api/v3 v3.5.4
 	go.etcd.io/etcd/client/v3 v3.5.4
-	go.mongodb.org/mongo-driver v1.10.1
+	go.mongodb.org/mongo-driver v1.10.2
 	go.opentelemetry.io/otel v1.9.0
 	go.opentelemetry.io/otel/exporters/jaeger v1.9.0
 	go.opentelemetry.io/otel/exporters/zipkin v1.9.0
 	go.opentelemetry.io/otel/sdk v1.9.0
 	go.opentelemetry.io/otel/trace v1.9.0
 	go.uber.org/automaxprocs v1.5.1
-	go.uber.org/goleak v1.1.12
+	go.uber.org/goleak v1.2.0
 	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
 	golang.org/x/time v0.0.0-20220411224347-583f2d630306
 	google.golang.org/grpc v1.49.0
diff --git a/go.sum b/go.sum
index 6dd18ba3..f0f4edd3 100644
--- a/go.sum
+++ b/go.sum
@@ -42,8 +42,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/ClickHouse/clickhouse-go v1.5.4 h1:cKjXeYLNWVJIx2J1K6H2CqyRmfwVJVY1OV1coaaFcI0=
 github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
-github.com/ClickHouse/clickhouse-go/v2 v2.2.0 h1:dj00TDKY+xwuTJdbpspCSmTLFyWzRJerTHwaBxut1C0=
-github.com/ClickHouse/clickhouse-go/v2 v2.2.0/go.mod h1:8f2XZUi7XoeU+uPIytSi1cvx8fmJxi7vIgqpvYTF1+o=
+github.com/ClickHouse/clickhouse-go/v2 v2.0.14 h1:7HW+MXPaQfVyCzPGEn/LciMc8K6cG58FZMUc7DXQmro=
+github.com/ClickHouse/clickhouse-go/v2 v2.0.14/go.mod h1:iq2DUGgpA4BBki2CVwrF8x43zqBjdgHtbexkFkh5a6M=
 github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
 github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@@ -147,7 +147,6 @@ github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
-github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
 github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
@@ -296,8 +295,8 @@ 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/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
-github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
+github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
@@ -353,8 +352,8 @@ github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
 github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
 github.com/openzipkin/zipkin-go v0.4.0 h1:CtfRrOVZtbDj8rt1WXjklw0kqqJQwICrCKmlfUuBUUw=
 github.com/openzipkin/zipkin-go v0.4.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ=
-github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU=
-github.com/paulmach/orb v0.7.1/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A=
+github.com/paulmach/orb v0.5.0 h1:sNhJV5ML+mv1F077ljOck/9inorF4ahDO8iNNpHbKHY=
+github.com/paulmach/orb v0.5.0/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A=
 github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
 github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
 github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
@@ -362,8 +361,8 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR
 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
 github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
-github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
-github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
+github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
+github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
 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=
@@ -433,7 +432,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
@@ -458,15 +456,14 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw=
 github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
-github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
 go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc=
 go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
 go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg=
 go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4=
 go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
-go.mongodb.org/mongo-driver v1.10.1 h1:NujsPveKwHaWuKUer/ceo9DzEe7HIj1SlJ6uvXZG0S4=
-go.mongodb.org/mongo-driver v1.10.1/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8=
+go.mongodb.org/mongo-driver v1.10.2 h1:4Wk3cnqOrQCn0P92L3/mmurMxzdvWWs5J9jinAVKD+k=
+go.mongodb.org/mongo-driver v1.10.2/go.mod h1:z4XpeoU6w+9Vht+jAFyLgVrD+jGSQQe0+CBWFHNiHt8=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -491,8 +488,8 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/automaxprocs v1.5.1 h1:e1YG66Lrk73dn4qhg8WFSvhF0JuFQF0ERIp4rpuV8Qk=
 go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU=
 go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
-go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
+go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
 go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
@@ -623,7 +620,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/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=
diff --git a/rest/handler/cryptionhandler.go b/rest/handler/cryptionhandler.go
index 7c5f6e63..9b91c840 100644
--- a/rest/handler/cryptionhandler.go
+++ b/rest/handler/cryptionhandler.go
@@ -6,7 +6,6 @@ import (
 	"encoding/base64"
 	"errors"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/http"
 
@@ -51,7 +50,7 @@ func decryptBody(key []byte, r *http.Request) error {
 		content = make([]byte, r.ContentLength)
 		_, err = io.ReadFull(r.Body, content)
 	} else {
-		content, err = ioutil.ReadAll(io.LimitReader(r.Body, maxBytes))
+		content, err = io.ReadAll(io.LimitReader(r.Body, maxBytes))
 	}
 	if err != nil {
 		return err
@@ -69,7 +68,7 @@ func decryptBody(key []byte, r *http.Request) error {
 
 	var buf bytes.Buffer
 	buf.Write(output)
-	r.Body = ioutil.NopCloser(&buf)
+	r.Body = io.NopCloser(&buf)
 
 	return nil
 }
diff --git a/rest/handler/loghandler.go b/rest/handler/loghandler.go
index 8d9ae44f..b236ecf5 100644
--- a/rest/handler/loghandler.go
+++ b/rest/handler/loghandler.go
@@ -7,7 +7,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/http"
 	"net/http/httputil"
@@ -180,7 +179,7 @@ func logBrief(r *http.Request, code int, timer *utils.ElapsedTimer, logs *intern
 	if !ok {
 		fullReq := dumpRequest(r)
 		limitReader := io.LimitReader(strings.NewReader(fullReq), limitBodyBytes)
-		body, err := ioutil.ReadAll(limitReader)
+		body, err := io.ReadAll(limitReader)
 		if err != nil {
 			buf.WriteString(fmt.Sprintf("\n%s", fullReq))
 		} else {
diff --git a/rest/httpc/requests.go b/rest/httpc/requests.go
index b9c2d3bb..a4ae197d 100644
--- a/rest/httpc/requests.go
+++ b/rest/httpc/requests.go
@@ -182,7 +182,6 @@ func request(r *http.Request, cli client) (*http.Response, error) {
 	}
 
 	r = r.WithContext(ctx)
-	span.SetAttributes(semconv.HTTPClientAttributesFromHTTPRequest(r)...)
 	propagator.Inject(ctx, propagation.HeaderCarrier(r.Header))
 
 	resp, err := cli.do(r)
diff --git a/tools/goctl/api/docgen/doc.go b/tools/goctl/api/docgen/doc.go
index ffa0e183..c4b0cbed 100644
--- a/tools/goctl/api/docgen/doc.go
+++ b/tools/goctl/api/docgen/doc.go
@@ -4,15 +4,15 @@ import (
 	"bytes"
 	_ "embed"
 	"fmt"
-	"go/format"
 	"html/template"
+	"io"
 	"strconv"
 	"strings"
 
 	"github.com/zeromicro/go-zero/core/stringx"
-	"github.com/zeromicro/go-zero/tools/goctl/api/gogen"
 	"github.com/zeromicro/go-zero/tools/goctl/api/spec"
-	"github.com/zeromicro/go-zero/tools/goctl/api/util"
+	apiutil "github.com/zeromicro/go-zero/tools/goctl/api/util"
+	"github.com/zeromicro/go-zero/tools/goctl/util"
 )
 
 //go:embed markdown.tpl
@@ -23,7 +23,7 @@ func genDoc(api *spec.ApiSpec, dir, filename string) error {
 		return nil
 	}
 
-	fp, _, err := util.MaybeCreateFile(dir, "", filename)
+	fp, _, err := apiutil.MaybeCreateFile(dir, "", filename)
 	if err != nil {
 		return err
 	}
@@ -36,12 +36,12 @@ func genDoc(api *spec.ApiSpec, dir, filename string) error {
 			routeComment = "N/A"
 		}
 
-		requestContent, err := buildDoc(route.RequestType, api)
+		requestContent, err := buildDoc(route.RequestType, api.Types)
 		if err != nil {
 			return err
 		}
 
-		responseContent, err := buildDoc(route.ResponseType, api)
+		responseContent, err := buildDoc(route.ResponseType, api.Types)
 		if err != nil {
 			return err
 		}
@@ -61,6 +61,7 @@ func genDoc(api *spec.ApiSpec, dir, filename string) error {
 		if err != nil {
 			return err
 		}
+
 		builder.Write(tmplBytes.Bytes())
 	}
 
@@ -68,7 +69,7 @@ func genDoc(api *spec.ApiSpec, dir, filename string) error {
 	return err
 }
 
-func buildDoc(route spec.Type, api *spec.ApiSpec) (string, error) {
+func buildDoc(route spec.Type, types []spec.Type) (string, error) {
 	if route == nil || len(route.Name()) == 0 {
 		return "", nil
 	}
@@ -78,15 +79,12 @@ func buildDoc(route spec.Type, api *spec.ApiSpec) (string, error) {
 	if definedType, ok := route.(spec.DefineStruct); ok {
 		associatedTypes(definedType, &tps)
 	}
-	value, err := gogen.BuildTypes(tps, api)
+	value, err := buildTypes(tps, types)
 	if err != nil {
 		return "", err
 	}
-	formatted, err := format.Source([]byte(value))
-	if err != nil {
-		return "", err
-	}
-	return fmt.Sprintf("\n\n```golang\n%s\n```\n", string(formatted)), nil
+
+	return fmt.Sprintf("\n\n```golang\n%s\n```\n", value), nil
 }
 
 func associatedTypes(tp spec.DefineStruct, tps *[]spec.Type) {
@@ -107,3 +105,82 @@ func associatedTypes(tp spec.DefineStruct, tps *[]spec.Type) {
 		}
 	}
 }
+
+// buildTypes gen types to string
+func buildTypes(types []spec.Type, all []spec.Type) (string, error) {
+	var builder strings.Builder
+	first := true
+	for _, tp := range types {
+		if first {
+			first = false
+		} else {
+			builder.WriteString("\n\n")
+		}
+		if err := writeType(&builder, tp, all); err != nil {
+			return "", apiutil.WrapErr(err, "Type "+tp.Name()+" generate error")
+		}
+	}
+
+	return builder.String(), nil
+}
+
+func writeType(writer io.Writer, tp spec.Type, all []spec.Type) error {
+	fmt.Fprintf(writer, "type %s struct {\n", util.Title(tp.Name()))
+	if err := writerMembers(writer, tp, all); err != nil {
+		return err
+	}
+	fmt.Fprintf(writer, "}")
+	return nil
+}
+
+func writerMembers(writer io.Writer, tp spec.Type, all []spec.Type) error {
+	structType, ok := tp.(spec.DefineStruct)
+	if !ok {
+		return fmt.Errorf("unspport struct type: %s", tp.Name())
+	}
+
+	getTargetType := func(tp string) spec.Type {
+		for _, v := range all {
+			if v.Name() == tp {
+				return v
+			}
+		}
+		return nil
+	}
+	for _, member := range structType.Members {
+		if member.IsInline {
+			inlineType := getTargetType(member.Type.Name())
+			if inlineType == nil {
+				if _, err := fmt.Fprintf(writer, "%s\n", strings.Title(member.Type.Name())); err != nil {
+					return err
+				}
+			} else {
+				if err := writerMembers(writer, inlineType, all); err != nil {
+					return err
+				}
+			}
+
+			continue
+		}
+
+		if err := writeProperty(writer, member.Name, member.Tag, member.GetComment(), member.Type, 1); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func writeProperty(writer io.Writer, name, tag, comment string, tp spec.Type, indent int) error {
+	apiutil.WriteIndent(writer, indent)
+	var err error
+	if len(comment) > 0 {
+		comment = strings.TrimPrefix(comment, "//")
+		comment = "//" + comment
+		_, err = fmt.Fprintf(writer, "%s %s %s %s\n", strings.Title(name), tp.Name(), tag, comment)
+	} else {
+		_, err = fmt.Fprintf(writer, "%s %s %s\n", strings.Title(name), tp.Name(), tag)
+	}
+
+	return err
+}
diff --git a/tools/goctl/api/format/format.go b/tools/goctl/api/format/format.go
index 97576db3..9ba127ff 100644
--- a/tools/goctl/api/format/format.go
+++ b/tools/goctl/api/format/format.go
@@ -7,7 +7,6 @@ import (
 	"go/format"
 	"go/scanner"
 	"io"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -76,7 +75,7 @@ func GoFormatApi(_ *cobra.Command, _ []string) error {
 // apiFormatReader
 // filename is needed when there are `import` literals.
 func apiFormatReader(reader io.Reader, filename string, skipCheckDeclare bool) error {
-	data, err := ioutil.ReadAll(reader)
+	data, err := io.ReadAll(reader)
 	if err != nil {
 		return err
 	}
@@ -91,7 +90,7 @@ func apiFormatReader(reader io.Reader, filename string, skipCheckDeclare bool) e
 
 // ApiFormatByPath format api from file path
 func ApiFormatByPath(apiFilePath string, skipCheckDeclare bool) error {
-	data, err := ioutil.ReadFile(apiFilePath)
+	data, err := os.ReadFile(apiFilePath)
 	if err != nil {
 		return err
 	}
@@ -111,7 +110,7 @@ func ApiFormatByPath(apiFilePath string, skipCheckDeclare bool) error {
 		return err
 	}
 
-	return ioutil.WriteFile(apiFilePath, []byte(result), os.ModePerm)
+	return os.WriteFile(apiFilePath, []byte(result), os.ModePerm)
 }
 
 func apiFormat(data string, skipCheckDeclare bool, filename ...string) (string, error) {
@@ -145,12 +144,12 @@ func apiFormat(data string, skipCheckDeclare bool, filename ...string) (string,
 		}
 
 		if tapCount == 0 {
-			format, err := formatGoTypeDef(line, s, &builder)
+			ft, err := formatGoTypeDef(line, s, &builder)
 			if err != nil {
 				return "", err
 			}
 
-			if format {
+			if ft {
 				continue
 			}
 		}
diff --git a/tools/goctl/api/gogen/gentypes.go b/tools/goctl/api/gogen/gentypes.go
index 3b2e53ad..9e91735f 100644
--- a/tools/goctl/api/gogen/gentypes.go
+++ b/tools/goctl/api/gogen/gentypes.go
@@ -21,7 +21,7 @@ const typesFile = "types"
 var typesTemplate string
 
 // BuildTypes gen types to string
-func BuildTypes(types []spec.Type, api *spec.ApiSpec) (string, error) {
+func BuildTypes(types []spec.Type) (string, error) {
 	var builder strings.Builder
 	first := true
 	for _, tp := range types {
@@ -30,7 +30,7 @@ func BuildTypes(types []spec.Type, api *spec.ApiSpec) (string, error) {
 		} else {
 			builder.WriteString("\n\n")
 		}
-		if err := writeType(&builder, tp, api); err != nil {
+		if err := writeType(&builder, tp); err != nil {
 			return "", apiutil.WrapErr(err, "Type "+tp.Name()+" generate error")
 		}
 	}
@@ -39,7 +39,7 @@ func BuildTypes(types []spec.Type, api *spec.ApiSpec) (string, error) {
 }
 
 func genTypes(dir string, cfg *config.Config, api *spec.ApiSpec) error {
-	val, err := BuildTypes(api.Types, api)
+	val, err := BuildTypes(api.Types)
 	if err != nil {
 		return err
 	}
@@ -68,7 +68,7 @@ func genTypes(dir string, cfg *config.Config, api *spec.ApiSpec) error {
 	})
 }
 
-func writeType(writer io.Writer, tp spec.Type, api *spec.ApiSpec) error {
+func writeType(writer io.Writer, tp spec.Type) error {
 	structType, ok := tp.(spec.DefineStruct)
 	if !ok {
 		return fmt.Errorf("unspport struct type: %s", tp.Name())
@@ -76,7 +76,15 @@ func writeType(writer io.Writer, tp spec.Type, api *spec.ApiSpec) error {
 
 	fmt.Fprintf(writer, "type %s struct {\n", util.Title(tp.Name()))
 	for _, member := range structType.Members {
-		if err := writeProperty(writer, member.Name, member.Tag, member.GetComment(), member.Type, 1, api); err != nil {
+		if member.IsInline {
+			if _, err := fmt.Fprintf(writer, "%s\n", strings.Title(member.Type.Name())); err != nil {
+				return err
+			}
+
+			continue
+		}
+
+		if err := writeProperty(writer, member.Name, member.Tag, member.GetComment(), member.Type, 1); err != nil {
 			return err
 		}
 	}
diff --git a/tools/goctl/api/gogen/util.go b/tools/goctl/api/gogen/util.go
index 82e259e3..a8798ebd 100644
--- a/tools/goctl/api/gogen/util.go
+++ b/tools/goctl/api/gogen/util.go
@@ -4,7 +4,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"os"
 	"strings"
 	"text/template"
 
@@ -58,21 +57,15 @@ func genFile(c fileGenConfig) error {
 	return err
 }
 
-func writeProperty(writer io.Writer, name, tag, comment string, tp spec.Type, indent int, api *spec.ApiSpec) error {
+func writeProperty(writer io.Writer, name, tag, comment string, tp spec.Type, indent int) error {
 	util.WriteIndent(writer, indent)
 	var err error
-	var refPropertyName = tp.Name()
-	if isCustomType(refPropertyName) {
-		strs := getRefProperty(api, refPropertyName, name)
-		_, err = fmt.Fprintf(writer, "%s\n", strs)
+	if len(comment) > 0 {
+		comment = strings.TrimPrefix(comment, "//")
+		comment = "//" + comment
+		_, err = fmt.Fprintf(writer, "%s %s %s %s\n", strings.Title(name), tp.Name(), tag, comment)
 	} else {
-		if len(comment) > 0 {
-			comment = strings.TrimPrefix(comment, "//")
-			comment = "//" + comment
-			_, err = fmt.Fprintf(writer, "%s %s %s %s\n", strings.Title(name), tp.Name(), tag, comment)
-		} else {
-			_, err = fmt.Fprintf(writer, "%s %s %s\n", strings.Title(name), tp.Name(), tag)
-		}
+		_, err = fmt.Fprintf(writer, "%s %s %s\n", strings.Title(name), tp.Name(), tag)
 	}
 
 	return err
@@ -188,58 +181,3 @@ func golangExpr(ty spec.Type, pkg ...string) string {
 
 	return ""
 }
-
-func isCustomType(t string) bool {
-	var builtinType = []string{"string", "bool", "int", "uint", "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "float32", "float64", "uintptr", "complex64", "complex128"}
-	var is bool = true
-	for _, v := range builtinType {
-		if t == v {
-			is = false
-			break
-		}
-	}
-	return is
-}
-
-// Generate nested types recursively
-func getRefProperty(api *spec.ApiSpec, refPropertyName string, name string) string {
-	var str string = ""
-	for _, t := range api.Types {
-		if strings.TrimLeft(refPropertyName, "*") == t.Name() {
-			switch tm := t.(type) {
-			case spec.DefineStruct:
-				for _, m := range tm.Members {
-					if isCustomType(m.Type.Name()) {
-						// recursive
-						str += getRefProperty(api, m.Type.Name(), m.Name)
-					} else {
-						if len(m.Comment) > 0 {
-							comment := strings.TrimPrefix(m.Comment, "//")
-							comment = "//" + comment
-							str += fmt.Sprintf("%s %s %s %s\n\t", m.Name, m.Type.Name(), m.Tag, comment)
-						} else {
-							str += fmt.Sprintf("%s %s %s\n\t", m.Name, m.Type.Name(), m.Tag)
-						}
-
-					}
-
-				}
-			}
-		}
-	}
-	if name == "" {
-		temp := `${str}`
-		return os.Expand(temp, func(k string) string {
-			return str
-		})
-	} else {
-		temp := `${name} struct {
-			${str}}`
-		return os.Expand(temp, func(k string) string {
-			return map[string]string{
-				"name": name,
-				"str":  str,
-			}[k]
-		})
-	}
-}
diff --git a/tools/goctl/api/parser/g4/ast/apiparser.go b/tools/goctl/api/parser/g4/ast/apiparser.go
index 46cc6740..2b2c1665 100644
--- a/tools/goctl/api/parser/g4/ast/apiparser.go
+++ b/tools/goctl/api/parser/g4/ast/apiparser.go
@@ -2,7 +2,7 @@ package ast
 
 import (
 	"fmt"
-	"io/ioutil"
+	"os"
 	"path"
 	"path/filepath"
 	"strings"
@@ -498,7 +498,7 @@ func (p *Parser) checkType(linePrefix string, types map[string]TypeExpr, expr Da
 
 func (p *Parser) readContent(filename string) (string, error) {
 	filename = strings.ReplaceAll(filename, `"`, "")
-	data, err := ioutil.ReadFile(filename)
+	data, err := os.ReadFile(filename)
 	if err != nil {
 		return "", err
 	}
diff --git a/tools/goctl/pkg/env/env.go b/tools/goctl/pkg/env/env.go
index c240e205..99fc11d9 100644
--- a/tools/goctl/pkg/env/env.go
+++ b/tools/goctl/pkg/env/env.go
@@ -2,8 +2,8 @@ package env
 
 import (
 	"fmt"
-	"io/ioutil"
 	"log"
+	"os"
 	"path/filepath"
 	"runtime"
 	"strings"
@@ -94,7 +94,7 @@ func GetOr(key, def string) string {
 
 func readEnv(goctlHome string) *sortedmap.SortedMap {
 	envFile := filepath.Join(goctlHome, envFileDir)
-	data, err := ioutil.ReadFile(envFile)
+	data, err := os.ReadFile(envFile)
 	if err != nil {
 		return nil
 	}
@@ -143,5 +143,5 @@ func WriteEnv(kv []string) error {
 		return err
 	}
 	envFile := filepath.Join(defaultGoctlHome, envFileDir)
-	return ioutil.WriteFile(envFile, []byte(strings.Join(goctlEnv.Format(), "\n")), 0o777)
+	return os.WriteFile(envFile, []byte(strings.Join(goctlEnv.Format(), "\n")), 0o777)
 }
diff --git a/tools/goctl/update/update.go b/tools/goctl/update/update.go
index a7126abd..06ec1df2 100644
--- a/tools/goctl/update/update.go
+++ b/tools/goctl/update/update.go
@@ -2,8 +2,8 @@ package main
 
 import (
 	"flag"
-	"io/ioutil"
 	"net/http"
+	"os"
 	"path"
 
 	"github.com/zeromicro/go-zero/core/conf"
@@ -28,7 +28,7 @@ func forChksumHandler(file string, next http.Handler) http.Handler {
 			return
 		}
 
-		content, err := ioutil.ReadFile(file)
+		content, err := os.ReadFile(file)
 		if err != nil {
 			logx.Error(err)
 			http.Error(w, err.Error(), http.StatusInternalServerError)
diff --git a/tools/goctl/util/pathx/file.go b/tools/goctl/util/pathx/file.go
index 8049e0ac..5b1c62fc 100644
--- a/tools/goctl/util/pathx/file.go
+++ b/tools/goctl/util/pathx/file.go
@@ -213,7 +213,7 @@ func LoadTemplate(category, file, builtin string) (string, error) {
 		return builtin, nil
 	}
 
-	content, err := ioutil.ReadFile(file)
+	content, err := os.ReadFile(file)
 	if err != nil {
 		return "", err
 	}


Test patch:
diff --git a/core/conf/config_test.go b/core/conf/config_test.go
index 77c9c8da..83928bb3 100644
--- a/core/conf/config_test.go
+++ b/core/conf/config_test.go
@@ -1,7 +1,6 @@
 package conf
 
 import (
-	"io/ioutil"
 	"os"
 	"testing"
 
@@ -146,12 +145,12 @@ func TestConfigJsonEnv(t *testing.T) {
 }
 
 func createTempFile(ext, text string) (string, error) {
-	tmpfile, err := ioutil.TempFile(os.TempDir(), hash.Md5Hex([]byte(text))+"*"+ext)
+	tmpfile, err := os.CreateTemp(os.TempDir(), hash.Md5Hex([]byte(text))+"*"+ext)
 	if err != nil {
 		return "", err
 	}
 
-	if err := ioutil.WriteFile(tmpfile.Name(), []byte(text), os.ModeTemporary); err != nil {
+	if err := os.WriteFile(tmpfile.Name(), []byte(text), os.ModeTemporary); err != nil {
 		return "", err
 	}
 
diff --git a/core/fs/temps_test.go b/core/fs/temps_test.go
index 0cf1fc04..1e2ed6e9 100644
--- a/core/fs/temps_test.go
+++ b/core/fs/temps_test.go
@@ -1,7 +1,7 @@
 package fs
 
 import (
-	"io/ioutil"
+	"io"
 	"os"
 	"testing"
 
@@ -21,7 +21,7 @@ func TestTempFileWithText(t *testing.T) {
 	}
 	defer os.Remove(f.Name())
 
-	bs, err := ioutil.ReadAll(f)
+	bs, err := io.ReadAll(f)
 	assert.Nil(t, err)
 	if len(bs) != 4 {
 		t.Error("TempFileWithText returned wrong file size")
@@ -41,7 +41,7 @@ func TestTempFilenameWithText(t *testing.T) {
 	}
 	defer os.Remove(f)
 
-	bs, err := ioutil.ReadFile(f)
+	bs, err := os.ReadFile(f)
 	assert.Nil(t, err)
 	if len(bs) != 4 {
 		t.Error("TempFilenameWithText returned wrong file size")
diff --git a/core/fx/stream_test.go b/core/fx/stream_test.go
index 4d5976b2..993cbe7e 100644
--- a/core/fx/stream_test.go
+++ b/core/fx/stream_test.go
@@ -1,7 +1,7 @@
 package fx
 
 import (
-	"io/ioutil"
+	"io"
 	"log"
 	"math/rand"
 	"reflect"
@@ -238,7 +238,7 @@ func TestLast(t *testing.T) {
 
 func TestMap(t *testing.T) {
 	runCheckedTest(t, func(t *testing.T) {
-		log.SetOutput(ioutil.Discard)
+		log.SetOutput(io.Discard)
 
 		tests := []struct {
 			mapper MapFunc
diff --git a/core/iox/read_test.go b/core/iox/read_test.go
index 4576d207..56d1b359 100644
--- a/core/iox/read_test.go
+++ b/core/iox/read_test.go
@@ -3,7 +3,6 @@ package iox
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"os"
 	"testing"
 	"time"
@@ -97,10 +96,10 @@ func TestReadTextLines(t *testing.T) {
 
 func TestDupReadCloser(t *testing.T) {
 	input := "hello"
-	reader := ioutil.NopCloser(bytes.NewBufferString(input))
+	reader := io.NopCloser(bytes.NewBufferString(input))
 	r1, r2 := DupReadCloser(reader)
 	verify := func(r io.Reader) {
-		output, err := ioutil.ReadAll(r)
+		output, err := io.ReadAll(r)
 		assert.Nil(t, err)
 		assert.Equal(t, input, string(output))
 	}
@@ -110,7 +109,7 @@ func TestDupReadCloser(t *testing.T) {
 }
 
 func TestReadBytes(t *testing.T) {
-	reader := ioutil.NopCloser(bytes.NewBufferString("helloworld"))
+	reader := io.NopCloser(bytes.NewBufferString("helloworld"))
 	buf := make([]byte, 5)
 	err := ReadBytes(reader, buf)
 	assert.Nil(t, err)
@@ -118,7 +117,7 @@ func TestReadBytes(t *testing.T) {
 }
 
 func TestReadBytesNotEnough(t *testing.T) {
-	reader := ioutil.NopCloser(bytes.NewBufferString("hell"))
+	reader := io.NopCloser(bytes.NewBufferString("hell"))
 	buf := make([]byte, 5)
 	err := ReadBytes(reader, buf)
 	assert.Equal(t, io.EOF, err)
diff --git a/core/iox/textfile_test.go b/core/iox/textfile_test.go
index 2c5f58e3..011d674b 100644
--- a/core/iox/textfile_test.go
+++ b/core/iox/textfile_test.go
@@ -1,7 +1,6 @@
 package iox
 
 import (
-	"io/ioutil"
 	"os"
 	"testing"
 
@@ -13,7 +12,7 @@ func TestCountLines(t *testing.T) {
 2
 3
 4`
-	file, err := ioutil.TempFile(os.TempDir(), "test-")
+	file, err := os.CreateTemp(os.TempDir(), "test-")
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/core/logx/logs_test.go b/core/logx/logs_test.go
index 6c741539..718e7438 100644
--- a/core/logx/logs_test.go
+++ b/core/logx/logs_test.go
@@ -4,7 +4,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"os"
 	"reflect"
@@ -649,7 +649,7 @@ func BenchmarkCopyByteSlice(b *testing.B) {
 		buf = make([]byte, len(s))
 		copy(buf, s)
 	}
-	fmt.Fprint(ioutil.Discard, buf)
+	fmt.Fprint(io.Discard, buf)
 }
 
 func BenchmarkCopyOnWriteByteSlice(b *testing.B) {
@@ -658,7 +658,7 @@ func BenchmarkCopyOnWriteByteSlice(b *testing.B) {
 		size := len(s)
 		buf = s[:size:size]
 	}
-	fmt.Fprint(ioutil.Discard, buf)
+	fmt.Fprint(io.Discard, buf)
 }
 
 func BenchmarkCacheByteSlice(b *testing.B) {
@@ -672,7 +672,7 @@ func BenchmarkCacheByteSlice(b *testing.B) {
 func BenchmarkLogs(b *testing.B) {
 	b.ReportAllocs()
 
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 	for i := 0; i < b.N; i++ {
 		Info(i)
 	}
diff --git a/core/mr/mapreduce_test.go b/core/mr/mapreduce_test.go
index b43f3f00..c2b37796 100644
--- a/core/mr/mapreduce_test.go
+++ b/core/mr/mapreduce_test.go
@@ -3,7 +3,7 @@ package mr
 import (
 	"context"
 	"errors"
-	"io/ioutil"
+	"io"
 	"log"
 	"runtime"
 	"sync/atomic"
@@ -17,7 +17,7 @@ import (
 var errDummy = errors.New("dummy")
 
 func init() {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 }
 
 func TestFinish(t *testing.T) {
diff --git a/core/stores/mongoc/cachedcollection_test.go b/core/stores/mongoc/cachedcollection_test.go
index f7eaa254..3d590e39 100644
--- a/core/stores/mongoc/cachedcollection_test.go
+++ b/core/stores/mongoc/cachedcollection_test.go
@@ -3,7 +3,7 @@ package mongoc
 import (
 	"encoding/json"
 	"errors"
-	"io/ioutil"
+	"io"
 	"log"
 	"os"
 	"runtime"
@@ -117,7 +117,7 @@ func TestStat(t *testing.T) {
 
 func TestStatCacheFails(t *testing.T) {
 	resetStats()
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 	defer log.SetOutput(os.Stdout)
 
 	r := redis.New("localhost:59999")
diff --git a/core/stores/sqlc/cachedsql_test.go b/core/stores/sqlc/cachedsql_test.go
index f42e49ba..199cb6bc 100644
--- a/core/stores/sqlc/cachedsql_test.go
+++ b/core/stores/sqlc/cachedsql_test.go
@@ -6,7 +6,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"os"
 	"runtime"
@@ -284,7 +284,7 @@ func TestCachedConn_QueryRowIndex_HasWrongCache(t *testing.T) {
 
 func TestStatCacheFails(t *testing.T) {
 	resetStats()
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 	defer log.SetOutput(os.Stdout)
 
 	r := redis.New("localhost:59999")
diff --git a/core/threading/routinegroup_test.go b/core/threading/routinegroup_test.go
index 454b3623..7f4dd086 100644
--- a/core/threading/routinegroup_test.go
+++ b/core/threading/routinegroup_test.go
@@ -1,7 +1,7 @@
 package threading
 
 import (
-	"io/ioutil"
+	"io"
 	"log"
 	"sync"
 	"sync/atomic"
@@ -25,7 +25,7 @@ func TestRoutineGroupRun(t *testing.T) {
 }
 
 func TestRoutingGroupRunSafe(t *testing.T) {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 
 	var count int32
 	group := NewRoutineGroup()
diff --git a/core/threading/routines_test.go b/core/threading/routines_test.go
index 763c9ad9..6a12dca0 100644
--- a/core/threading/routines_test.go
+++ b/core/threading/routines_test.go
@@ -1,7 +1,7 @@
 package threading
 
 import (
-	"io/ioutil"
+	"io"
 	"log"
 	"testing"
 
@@ -14,7 +14,7 @@ func TestRoutineId(t *testing.T) {
 }
 
 func TestRunSafe(t *testing.T) {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 
 	i := 0
 
diff --git a/gateway/internal/descriptorsource_test.go b/gateway/internal/descriptorsource_test.go
index 0d6e8e37..d0957132 100644
--- a/gateway/internal/descriptorsource_test.go
+++ b/gateway/internal/descriptorsource_test.go
@@ -2,7 +2,6 @@ package internal
 
 import (
 	"encoding/base64"
-	"io/ioutil"
 	"net/http"
 	"os"
 	"testing"
@@ -18,11 +17,11 @@ const (
 )
 
 func TestGetMethods(t *testing.T) {
-	tmpfile, err := ioutil.TempFile(os.TempDir(), hash.Md5Hex([]byte(b64pb)))
+	tmpfile, err := os.CreateTemp(os.TempDir(), hash.Md5Hex([]byte(b64pb)))
 	assert.Nil(t, err)
 	b, err := base64.StdEncoding.DecodeString(b64pb)
 	assert.Nil(t, err)
-	assert.Nil(t, ioutil.WriteFile(tmpfile.Name(), b, os.ModeTemporary))
+	assert.Nil(t, os.WriteFile(tmpfile.Name(), b, os.ModeTemporary))
 	defer os.Remove(tmpfile.Name())
 
 	source, err := grpcurl.DescriptorSourceFromProtoSets(tmpfile.Name())
@@ -37,11 +36,11 @@ func TestGetMethods(t *testing.T) {
 }
 
 func TestGetMethodsWithAnnotations(t *testing.T) {
-	tmpfile, err := ioutil.TempFile(os.TempDir(), hash.Md5Hex([]byte(b64pb)))
+	tmpfile, err := os.CreateTemp(os.TempDir(), hash.Md5Hex([]byte(b64pb)))
 	assert.Nil(t, err)
 	b, err := base64.StdEncoding.DecodeString(b64pbWithAnnotations)
 	assert.Nil(t, err)
-	assert.Nil(t, ioutil.WriteFile(tmpfile.Name(), b, os.ModeTemporary))
+	assert.Nil(t, os.WriteFile(tmpfile.Name(), b, os.ModeTemporary))
 	defer os.Remove(tmpfile.Name())
 
 	source, err := grpcurl.DescriptorSourceFromProtoSets(tmpfile.Name())
diff --git a/rest/handler/contentsecurityhandler_test.go b/rest/handler/contentsecurityhandler_test.go
index a8e4d1d6..12ca7eea 100644
--- a/rest/handler/contentsecurityhandler_test.go
+++ b/rest/handler/contentsecurityhandler_test.go
@@ -6,7 +6,6 @@ import (
 	"encoding/base64"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -64,7 +63,7 @@ type requestSettings struct {
 }
 
 func init() {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 }
 
 func TestContentSecurityHandler(t *testing.T) {
@@ -374,13 +373,13 @@ func buildRequest(rs requestSettings) (*http.Request, error) {
 }
 
 func createTempFile(body []byte) (string, error) {
-	tmpFile, err := ioutil.TempFile(os.TempDir(), "go-unit-*.tmp")
+	tmpFile, err := os.CreateTemp(os.TempDir(), "go-unit-*.tmp")
 	if err != nil {
 		return "", err
 	}
 
 	tmpFile.Close()
-	err = ioutil.WriteFile(tmpFile.Name(), body, os.ModePerm)
+	err = os.WriteFile(tmpFile.Name(), body, os.ModePerm)
 	if err != nil {
 		return "", err
 	}
diff --git a/rest/handler/cryptionhandler_test.go b/rest/handler/cryptionhandler_test.go
index 0d9fba47..aa698292 100644
--- a/rest/handler/cryptionhandler_test.go
+++ b/rest/handler/cryptionhandler_test.go
@@ -3,7 +3,7 @@ package handler
 import (
 	"bytes"
 	"encoding/base64"
-	"io/ioutil"
+	"io"
 	"log"
 	"math/rand"
 	"net/http"
@@ -22,7 +22,7 @@ const (
 var aesKey = []byte(`PdSgVkYp3s6v9y$B&E)H+MbQeThWmZq4`)
 
 func init() {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 }
 
 func TestCryptionHandlerGet(t *testing.T) {
@@ -50,7 +50,7 @@ func TestCryptionHandlerPost(t *testing.T) {
 
 	req := httptest.NewRequest(http.MethodPost, "/any", &buf)
 	handler := CryptionHandler(aesKey)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		body, err := ioutil.ReadAll(r.Body)
+		body, err := io.ReadAll(r.Body)
 		assert.Nil(t, err)
 		assert.Equal(t, reqText, string(body))
 
diff --git a/rest/handler/gunziphandler_test.go b/rest/handler/gunziphandler_test.go
index eb783a06..8c00a630 100644
--- a/rest/handler/gunziphandler_test.go
+++ b/rest/handler/gunziphandler_test.go
@@ -2,7 +2,7 @@ package handler
 
 import (
 	"bytes"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http/httptest"
 	"strings"
@@ -19,7 +19,7 @@ func TestGunzipHandler(t *testing.T) {
 	var wg sync.WaitGroup
 	wg.Add(1)
 	handler := GunzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		body, err := ioutil.ReadAll(r.Body)
+		body, err := io.ReadAll(r.Body)
 		assert.Nil(t, err)
 		assert.Equal(t, string(body), message)
 		wg.Done()
@@ -39,7 +39,7 @@ func TestGunzipHandler_NoGzip(t *testing.T) {
 	var wg sync.WaitGroup
 	wg.Add(1)
 	handler := GunzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		body, err := ioutil.ReadAll(r.Body)
+		body, err := io.ReadAll(r.Body)
 		assert.Nil(t, err)
 		assert.Equal(t, string(body), message)
 		wg.Done()
diff --git a/rest/handler/loghandler_test.go b/rest/handler/loghandler_test.go
index 25019dbf..5de9adcf 100644
--- a/rest/handler/loghandler_test.go
+++ b/rest/handler/loghandler_test.go
@@ -3,7 +3,6 @@ package handler
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -15,7 +14,7 @@ import (
 )
 
 func init() {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 }
 
 func TestLogHandler(t *testing.T) {
@@ -55,7 +54,7 @@ func TestLogHandlerVeryLong(t *testing.T) {
 	req := httptest.NewRequest(http.MethodPost, "http://localhost", &buf)
 	handler := LogHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		r.Context().Value(internal.LogContext).(*internal.LogCollector).Append("anything")
-		io.Copy(ioutil.Discard, r.Body)
+		io.Copy(io.Discard, r.Body)
 		w.Header().Set("X-Test", "test")
 		w.WriteHeader(http.StatusServiceUnavailable)
 		_, err := w.Write([]byte("content"))
diff --git a/rest/handler/maxconnshandler_test.go b/rest/handler/maxconnshandler_test.go
index a662ad9a..1286f720 100644
--- a/rest/handler/maxconnshandler_test.go
+++ b/rest/handler/maxconnshandler_test.go
@@ -1,7 +1,7 @@
 package handler
 
 import (
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -15,7 +15,7 @@ import (
 const conns = 4
 
 func init() {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 }
 
 func TestMaxConnsHandler(t *testing.T) {
diff --git a/rest/handler/recoverhandler_test.go b/rest/handler/recoverhandler_test.go
index 1ea491f8..538ac6f2 100644
--- a/rest/handler/recoverhandler_test.go
+++ b/rest/handler/recoverhandler_test.go
@@ -1,7 +1,7 @@
 package handler
 
 import (
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -11,7 +11,7 @@ import (
 )
 
 func init() {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 }
 
 func TestWithPanic(t *testing.T) {
diff --git a/rest/handler/sheddinghandler_test.go b/rest/handler/sheddinghandler_test.go
index 4bf63e2b..6fa513b2 100644
--- a/rest/handler/sheddinghandler_test.go
+++ b/rest/handler/sheddinghandler_test.go
@@ -1,7 +1,7 @@
 package handler
 
 import (
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -13,7 +13,7 @@ import (
 )
 
 func init() {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 }
 
 func TestSheddingHandlerAccept(t *testing.T) {
diff --git a/rest/handler/timeouthandler_test.go b/rest/handler/timeouthandler_test.go
index f084a681..531785ce 100644
--- a/rest/handler/timeouthandler_test.go
+++ b/rest/handler/timeouthandler_test.go
@@ -2,7 +2,7 @@ package handler
 
 import (
 	"context"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -13,7 +13,7 @@ import (
 )
 
 func init() {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 }
 
 func TestTimeout(t *testing.T) {
diff --git a/rest/server_test.go b/rest/server_test.go
index f356ff4a..26912e2c 100644
--- a/rest/server_test.go
+++ b/rest/server_test.go
@@ -4,7 +4,6 @@ import (
 	"crypto/tls"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
 	"os"
@@ -25,7 +24,7 @@ import (
 func TestNewServer(t *testing.T) {
 	writer := logx.Reset()
 	defer logx.SetWriter(writer)
-	logx.SetWriter(logx.NewWriter(ioutil.Discard))
+	logx.SetWriter(logx.NewWriter(io.Discard))
 
 	const configYaml = `
 Name: foo
diff --git a/tools/goctl/api/gogen/gen_test.go b/tools/goctl/api/gogen/gen_test.go
index b1a283a1..2aab5c68 100644
--- a/tools/goctl/api/gogen/gen_test.go
+++ b/tools/goctl/api/gogen/gen_test.go
@@ -3,7 +3,6 @@ package gogen
 import (
 	_ "embed"
 	goformat "go/format"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -52,7 +51,7 @@ var (
 
 func TestParser(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
+	err := os.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -73,7 +72,7 @@ func TestParser(t *testing.T) {
 
 func TestMultiService(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(testMultiServiceTemplate), os.ModePerm)
+	err := os.WriteFile(filename, []byte(testMultiServiceTemplate), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -88,7 +87,7 @@ func TestMultiService(t *testing.T) {
 
 func TestApiNoInfo(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(apiNoInfo), os.ModePerm)
+	err := os.WriteFile(filename, []byte(apiNoInfo), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -100,7 +99,7 @@ func TestApiNoInfo(t *testing.T) {
 
 func TestInvalidApiFile(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(invalidApiFile), os.ModePerm)
+	err := os.WriteFile(filename, []byte(invalidApiFile), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -110,7 +109,7 @@ func TestInvalidApiFile(t *testing.T) {
 
 func TestAnonymousAnnotation(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(anonymousAnnotation), os.ModePerm)
+	err := os.WriteFile(filename, []byte(anonymousAnnotation), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -125,7 +124,7 @@ func TestAnonymousAnnotation(t *testing.T) {
 
 func TestApiHasMiddleware(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(apiHasMiddleware), os.ModePerm)
+	err := os.WriteFile(filename, []byte(apiHasMiddleware), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -137,7 +136,7 @@ func TestApiHasMiddleware(t *testing.T) {
 
 func TestApiHasJwt(t *testing.T) {
 	filename := "jwt.api"
-	err := ioutil.WriteFile(filename, []byte(apiJwt), os.ModePerm)
+	err := os.WriteFile(filename, []byte(apiJwt), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -149,7 +148,7 @@ func TestApiHasJwt(t *testing.T) {
 
 func TestApiHasJwtAndMiddleware(t *testing.T) {
 	filename := "jwt.api"
-	err := ioutil.WriteFile(filename, []byte(apiJwtWithMiddleware), os.ModePerm)
+	err := os.WriteFile(filename, []byte(apiJwtWithMiddleware), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -161,7 +160,7 @@ func TestApiHasJwtAndMiddleware(t *testing.T) {
 
 func TestApiHasNoRequestBody(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(apiHasNoRequest), os.ModePerm)
+	err := os.WriteFile(filename, []byte(apiHasNoRequest), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -171,7 +170,7 @@ func TestApiHasNoRequestBody(t *testing.T) {
 
 func TestApiRoutes(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(apiRouteTest), os.ModePerm)
+	err := os.WriteFile(filename, []byte(apiRouteTest), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -183,7 +182,7 @@ func TestApiRoutes(t *testing.T) {
 
 func TestHasCommentRoutes(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(hasCommentApiTest), os.ModePerm)
+	err := os.WriteFile(filename, []byte(hasCommentApiTest), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -195,7 +194,7 @@ func TestHasCommentRoutes(t *testing.T) {
 
 func TestInlineTypeNotExist(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(hasInlineNoExistTest), os.ModePerm)
+	err := os.WriteFile(filename, []byte(hasInlineNoExistTest), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -205,12 +204,12 @@ func TestInlineTypeNotExist(t *testing.T) {
 
 func TestHasImportApi(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(hasImportApi), os.ModePerm)
+	err := os.WriteFile(filename, []byte(hasImportApi), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
 	importApiName := "importApi.api"
-	err = ioutil.WriteFile(importApiName, []byte(importApi), os.ModePerm)
+	err = os.WriteFile(importApiName, []byte(importApi), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(importApiName)
 
@@ -231,7 +230,7 @@ func TestHasImportApi(t *testing.T) {
 
 func TestNoStructApi(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(noStructTagApi), os.ModePerm)
+	err := os.WriteFile(filename, []byte(noStructTagApi), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -244,7 +243,7 @@ func TestNoStructApi(t *testing.T) {
 
 func TestNestTypeApi(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(nestTypeApi), os.ModePerm)
+	err := os.WriteFile(filename, []byte(nestTypeApi), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -254,7 +253,7 @@ func TestNestTypeApi(t *testing.T) {
 
 func TestCamelStyle(t *testing.T) {
 	filename := "greet.api"
-	err := ioutil.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
+	err := os.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
 	assert.Nil(t, err)
 	defer os.Remove(filename)
 
@@ -281,7 +280,7 @@ func validateWithCamel(t *testing.T, api, camel string) {
 	assert.Nil(t, err)
 	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
 		if strings.HasSuffix(path, ".go") {
-			code, err := ioutil.ReadFile(path)
+			code, err := os.ReadFile(path)
 			assert.Nil(t, err)
 			assert.Nil(t, validateCode(string(code)))
 		}
diff --git a/tools/goctl/api/gogen/template_test.go b/tools/goctl/api/gogen/template_test.go
index 9d757bfc..6ff75372 100644
--- a/tools/goctl/api/gogen/template_test.go
+++ b/tools/goctl/api/gogen/template_test.go
@@ -1,7 +1,7 @@
 package gogen
 
 import (
-	"io/ioutil"
+	"os"
 	"path/filepath"
 	"testing"
 
@@ -15,7 +15,7 @@ func TestGenTemplates(t *testing.T) {
 	dir, err := pathx.GetTemplateDir(category)
 	assert.Nil(t, err)
 	file := filepath.Join(dir, "main.tpl")
-	data, err := ioutil.ReadFile(file)
+	data, err := os.ReadFile(file)
 	assert.Nil(t, err)
 	assert.Equal(t, string(data), mainTemplate)
 }
@@ -29,21 +29,21 @@ func TestRevertTemplate(t *testing.T) {
 	assert.Nil(t, err)
 
 	file := filepath.Join(dir, name)
-	data, err := ioutil.ReadFile(file)
+	data, err := os.ReadFile(file)
 	assert.Nil(t, err)
 
 	modifyData := string(data) + "modify"
 	err = pathx.CreateTemplate(category, name, modifyData)
 	assert.Nil(t, err)
 
-	data, err = ioutil.ReadFile(file)
+	data, err = os.ReadFile(file)
 	assert.Nil(t, err)
 
 	assert.Equal(t, string(data), modifyData)
 
 	assert.Nil(t, RevertTemplate(name))
 
-	data, err = ioutil.ReadFile(file)
+	data, err = os.ReadFile(file)
 	assert.Nil(t, err)
 	assert.Equal(t, mainTemplate, string(data))
 }
@@ -59,7 +59,7 @@ func TestClean(t *testing.T) {
 	assert.Nil(t, err)
 
 	file := filepath.Join(dir, name)
-	_, err = ioutil.ReadFile(file)
+	_, err = os.ReadFile(file)
 	assert.NotNil(t, err)
 }
 
@@ -72,21 +72,21 @@ func TestUpdate(t *testing.T) {
 	assert.Nil(t, err)
 
 	file := filepath.Join(dir, name)
-	data, err := ioutil.ReadFile(file)
+	data, err := os.ReadFile(file)
 	assert.Nil(t, err)
 
 	modifyData := string(data) + "modify"
 	err = pathx.CreateTemplate(category, name, modifyData)
 	assert.Nil(t, err)
 
-	data, err = ioutil.ReadFile(file)
+	data, err = os.ReadFile(file)
 	assert.Nil(t, err)
 
 	assert.Equal(t, string(data), modifyData)
 
 	assert.Nil(t, Update())
 
-	data, err = ioutil.ReadFile(file)
+	data, err = os.ReadFile(file)
 	assert.Nil(t, err)
 	assert.Equal(t, mainTemplate, string(data))
 }
diff --git a/tools/goctl/api/gogen/testdata/api_common.api b/tools/goctl/api/gogen/testdata/api_common.api
deleted file mode 100644
index 3cdfe869..00000000
--- a/tools/goctl/api/gogen/testdata/api_common.api
+++ /dev/null
@@ -1,3 +0,0 @@
-type Common {
-	Some string `json:"some"` // some imported type
-}
\ No newline at end of file
diff --git a/tools/goctl/api/gogen/testdata/api_has_nested_type.api b/tools/goctl/api/gogen/testdata/api_has_nested_type.api
deleted file mode 100644
index e75ae13d..00000000
--- a/tools/goctl/api/gogen/testdata/api_has_nested_type.api
+++ /dev/null
@@ -1,48 +0,0 @@
-import "./api_common.api"
-type Resp {
-	R1 string `json:"r1"`
-	R2 bool   `json:"r2"`
-	R3 Common `json:"r3"`
-}
-type CommonResponse {
-	Code    int    `json:"code"` // 100 | 200
-	Message string `json:"message"`
-	Common
-	Response Resp `json:"response"`
-}
-
-type LoginResponseDto {
-	Id          string `bson:"_id" json:"id"`
-	Name        string `json:"name"`
-	AccessToken string `json:"accessToken"`
-}
-
-type UserCreateDto {
-	Id string `json:"id"`
-}
-type LoginRequest {
-	Username string `json:"username,optional"` // user name is optional
-	Password string `json:"password,optional"`
-}
-type LoginResponse {
-	*CommonResponse
-	Result *LoginResponseDto `json:"result"`
-}
-
-type UserCreateRequest {
-	Username string `json:"username,optional"` // some dsada
-	Password string `json:"password,optional"`
-}
-
-type UserCreateResponse {
-	*CommonResponse
-	Result *UserCreateDto `json:"result"` // result
-}
-
-service user-api {
-	@handler UserHandler
-	post /user/signin(UserCreateRequest) returns (UserCreateResponse)
-	
-	@handler LoginHandler
-	post /user/login(LoginRequest) returns (LoginResponse)
-}
\ No newline at end of file
diff --git a/tools/goctl/api/parser/g4/gen/api/file_splitor_test.go b/tools/goctl/api/parser/g4/gen/api/file_splitor_test.go
index 541d6cbe..77ac0b1d 100644
--- a/tools/goctl/api/parser/g4/gen/api/file_splitor_test.go
+++ b/tools/goctl/api/parser/g4/gen/api/file_splitor_test.go
@@ -9,7 +9,6 @@ import (
 	"bytes"
 	"fmt"
 	"go/format"
-	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
@@ -18,7 +17,7 @@ import (
 
 func TestFileSplitor(t *testing.T) {
 	dir := "."
-	data, err := ioutil.ReadFile(filepath.Join(dir, "apiparser_parser.go"))
+	data, err := os.ReadFile(filepath.Join(dir, "apiparser_parser.go"))
 	if err != nil {
 		log.Fatalln(err)
 	}
@@ -67,7 +66,7 @@ import "github.com/zeromicro/antlr"
 			fmt.Printf("%+v\n", err)
 			break
 		}
-		err = ioutil.WriteFile(fp, src, os.ModePerm)
+		err = os.WriteFile(fp, src, os.ModePerm)
 		if err != nil {
 			fmt.Printf("%+v\n", err)
 		}
diff --git a/tools/goctl/model/sql/gen/template_test.go b/tools/goctl/model/sql/gen/template_test.go
index bcf9602e..206ed565 100644
--- a/tools/goctl/model/sql/gen/template_test.go
+++ b/tools/goctl/model/sql/gen/template_test.go
@@ -1,7 +1,7 @@
 package gen
 
 import (
-	"io/ioutil"
+	"os"
 	"path/filepath"
 	"testing"
 
@@ -16,7 +16,7 @@ func TestGenTemplates(t *testing.T) {
 	dir, err := pathx.GetTemplateDir(category)
 	assert.Nil(t, err)
 	file := filepath.Join(dir, "model-new.tpl")
-	data, err := ioutil.ReadFile(file)
+	data, err := os.ReadFile(file)
 	assert.Nil(t, err)
 	assert.Equal(t, string(data), template.New)
 }
@@ -30,21 +30,21 @@ func TestRevertTemplate(t *testing.T) {
 	assert.Nil(t, err)
 
 	file := filepath.Join(dir, name)
-	data, err := ioutil.ReadFile(file)
+	data, err := os.ReadFile(file)
 	assert.Nil(t, err)
 
 	modifyData := string(data) + "modify"
 	err = pathx.CreateTemplate(category, name, modifyData)
 	assert.Nil(t, err)
 
-	data, err = ioutil.ReadFile(file)
+	data, err = os.ReadFile(file)
 	assert.Nil(t, err)
 
 	assert.Equal(t, string(data), modifyData)
 
 	assert.Nil(t, RevertTemplate(name))
 
-	data, err = ioutil.ReadFile(file)
+	data, err = os.ReadFile(file)
 	assert.Nil(t, err)
 	assert.Equal(t, template.New, string(data))
 }
@@ -60,7 +60,7 @@ func TestClean(t *testing.T) {
 	assert.Nil(t, err)
 
 	file := filepath.Join(dir, name)
-	_, err = ioutil.ReadFile(file)
+	_, err = os.ReadFile(file)
 	assert.NotNil(t, err)
 }
 
@@ -73,21 +73,21 @@ func TestUpdate(t *testing.T) {
 	assert.Nil(t, err)
 
 	file := filepath.Join(dir, name)
-	data, err := ioutil.ReadFile(file)
+	data, err := os.ReadFile(file)
 	assert.Nil(t, err)
 
 	modifyData := string(data) + "modify"
 	err = pathx.CreateTemplate(category, name, modifyData)
 	assert.Nil(t, err)
 
-	data, err = ioutil.ReadFile(file)
+	data, err = os.ReadFile(file)
 	assert.Nil(t, err)
 
 	assert.Equal(t, string(data), modifyData)
 
 	assert.Nil(t, Update())
 
-	data, err = ioutil.ReadFile(file)
+	data, err = os.ReadFile(file)
 	assert.Nil(t, err)
 	assert.Equal(t, template.New, string(data))
 }
diff --git a/tools/goctl/rpc/generator/template_test.go b/tools/goctl/rpc/generator/template_test.go
index 7850ee60..eff29c39 100644
--- a/tools/goctl/rpc/generator/template_test.go
+++ b/tools/goctl/rpc/generator/template_test.go
@@ -1,7 +1,6 @@
 package generator
 
 import (
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -25,7 +24,7 @@ func TestRevertTemplate(t *testing.T) {
 		return
 	}
 	mainTpl := filepath.Join(fp, mainTemplateFile)
-	data, err := ioutil.ReadFile(mainTpl)
+	data, err := os.ReadFile(mainTpl)
 	if err != nil {
 		return
 	}
@@ -36,12 +35,12 @@ func TestRevertTemplate(t *testing.T) {
 		assert.Equal(t, "test: no such file name", err.Error())
 	}
 
-	err = ioutil.WriteFile(mainTpl, []byte("modify"), os.ModePerm)
+	err = os.WriteFile(mainTpl, []byte("modify"), os.ModePerm)
 	if err != nil {
 		return
 	}
 
-	data, err = ioutil.ReadFile(mainTpl)
+	data, err = os.ReadFile(mainTpl)
 	if err != nil {
 		return
 	}
@@ -50,7 +49,7 @@ func TestRevertTemplate(t *testing.T) {
 	err = RevertTemplate(mainTemplateFile)
 	assert.Nil(t, err)
 
-	data, err = ioutil.ReadFile(mainTpl)
+	data, err = os.ReadFile(mainTpl)
 	if err != nil {
 		return
 	}
@@ -86,12 +85,12 @@ func TestUpdate(t *testing.T) {
 	}
 	mainTpl := filepath.Join(fp, mainTemplateFile)
 
-	err = ioutil.WriteFile(mainTpl, []byte("modify"), os.ModePerm)
+	err = os.WriteFile(mainTpl, []byte("modify"), os.ModePerm)
 	if err != nil {
 		return
 	}
 
-	data, err := ioutil.ReadFile(mainTpl)
+	data, err := os.ReadFile(mainTpl)
 	if err != nil {
 		return
 	}
@@ -99,7 +98,7 @@ func TestUpdate(t *testing.T) {
 
 	assert.Nil(t, Update())
 
-	data, err = ioutil.ReadFile(mainTpl)
+	data, err = os.ReadFile(mainTpl)
 	if err != nil {
 		return
 	}