Repository: zeromicro/go-zero
Pull request #2375 (2022-09-10 02:37:47)

feat: support baggage propagation in httpc


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 a276e998..c6640bf3 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
diff --git a/go.sum b/go.sum
index 0a048105..566cb49d 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=
@@ -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,7 +456,6 @@ 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=
@@ -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/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/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/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
 	}