Repository: zeromicro/go-zero
Pull request #3217 (2023-05-06 09:03:58)

io/ioutil deprecated

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/zeromicro/go-zero/pull/3217?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#3217](https://app.codecov.io/gh/zeromicro/go-zero/pull/3217?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (29281e6) into [master](https://app.codecov.io/gh/zeromicro/go-zero/commit/4f13fe8188335acd79d2dd76963d1e43c503373b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (4f13fe8) will **increase** coverage by `0.01%`.
> The diff coverage is `n/a`.


[see 1 file with indirect coverage changes](https://app.codecov.io/gh/zeromicro/go-zero/pull/3217/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)


Patch:
diff --git a/tools/goctl/api/dartgen/genvars.go b/tools/goctl/api/dartgen/genvars.go
index ac1b0fac..64cce8c5 100644
--- a/tools/goctl/api/dartgen/genvars.go
+++ b/tools/goctl/api/dartgen/genvars.go
@@ -2,7 +2,6 @@ package dartgen
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 )
 
@@ -83,7 +82,7 @@ func genVars(dir string, isLegacy bool, scheme string, hostname string) error {
 	}
 
 	if !fileExists(dir + "vars.dart") {
-		err = ioutil.WriteFile(dir+"vars.dart", []byte(fmt.Sprintf(`const serverHost='%s://%s';`, scheme, hostname)), 0o644)
+		err = os.WriteFile(dir+"vars.dart", []byte(fmt.Sprintf(`const serverHost='%s://%s';`, scheme, hostname)), 0o644)
 		if err != nil {
 			return err
 		}
@@ -94,7 +93,7 @@ func genVars(dir string, isLegacy bool, scheme string, hostname string) error {
 		if isLegacy {
 			tpl = varTemplate
 		}
-		err = ioutil.WriteFile(dir+"kv.dart", []byte(tpl), 0o644)
+		err = os.WriteFile(dir+"kv.dart", []byte(tpl), 0o644)
 		if err != nil {
 			return err
 		}
diff --git a/tools/goctl/migrate/migrate.go b/tools/goctl/migrate/migrate.go
index 4f4b80a0..4eee9459 100644
--- a/tools/goctl/migrate/migrate.go
+++ b/tools/goctl/migrate/migrate.go
@@ -8,7 +8,6 @@ import (
 	"go/parser"
 	"go/token"
 	"io/fs"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -163,7 +162,7 @@ func writeFile(pkgs []*ast.Package, verbose bool) error {
 				return fmt.Errorf("[rewriteImport] format file %s error: %w", filename, err)
 			}
 
-			err = ioutil.WriteFile(filename, w.Bytes(), os.ModePerm)
+			err = os.WriteFile(filename, w.Bytes(), os.ModePerm)
 			if err != nil {
 				return fmt.Errorf("[rewriteImport] write file %s error: %w", filename, err)
 			}
diff --git a/tools/goctl/migrate/version.go b/tools/goctl/migrate/version.go
index de6b8fb0..37a4eec0 100644
--- a/tools/goctl/migrate/version.go
+++ b/tools/goctl/migrate/version.go
@@ -2,7 +2,7 @@ package migrate
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"strings"
 	"time"
@@ -34,7 +34,7 @@ func getLatest(repo string, verbose bool) ([]string, error) {
 			continue
 		}
 		defer resp.Body.Close()
-		data, err := ioutil.ReadAll(resp.Body)
+		data, err := io.ReadAll(resp.Body)
 		if err != nil {
 			log(err)
 			continue
diff --git a/tools/goctl/model/sql/command/migrationnotes/v1.3.4.go b/tools/goctl/model/sql/command/migrationnotes/v1.3.4.go
index 0f5cb759..dc9df2c5 100644
--- a/tools/goctl/model/sql/command/migrationnotes/v1.3.4.go
+++ b/tools/goctl/model/sql/command/migrationnotes/v1.3.4.go
@@ -2,7 +2,7 @@ package migrationnotes
 
 import (
 	"fmt"
-	"io/ioutil"
+	"os"
 	"strings"
 )
 
@@ -24,7 +24,7 @@ func migrateBefore1_3_4(dir, style string) error {
 }
 
 func needShow1_3_4(dir, style string) (bool, error) {
-	files, err := ioutil.ReadDir(dir)
+	files, err := os.ReadDir(dir)
 	if err != nil {
 		return false, nil
 	}
diff --git a/tools/goctl/model/sql/gen/gen.go b/tools/goctl/model/sql/gen/gen.go
index 5b7bfea3..34a07517 100644
--- a/tools/goctl/model/sql/gen/gen.go
+++ b/tools/goctl/model/sql/gen/gen.go
@@ -3,7 +3,6 @@ package gen
 import (
 	"bytes"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -168,7 +167,7 @@ func (g *defaultGenerator) createFile(modelList map[string]*codeTuple) error {
 
 		name := util.SafeString(modelFilename) + "_gen.go"
 		filename := filepath.Join(dirAbs, name)
-		err = ioutil.WriteFile(filename, []byte(codes.modelCode), os.ModePerm)
+		err = os.WriteFile(filename, []byte(codes.modelCode), os.ModePerm)
 		if err != nil {
 			return err
 		}
@@ -179,7 +178,7 @@ func (g *defaultGenerator) createFile(modelList map[string]*codeTuple) error {
 			g.Warning("%s already exists, ignored.", name)
 			continue
 		}
-		err = ioutil.WriteFile(filename, []byte(codes.modelCustomCode), os.ModePerm)
+		err = os.WriteFile(filename, []byte(codes.modelCustomCode), os.ModePerm)
 		if err != nil {
 			return err
 		}
diff --git a/tools/goctl/model/sql/util/matcher.go b/tools/goctl/model/sql/util/matcher.go
index b7e84e05..5824426f 100644
--- a/tools/goctl/model/sql/util/matcher.go
+++ b/tools/goctl/model/sql/util/matcher.go
@@ -1,7 +1,7 @@
 package util
 
 import (
-	"io/ioutil"
+	"os"
 	"path/filepath"
 )
 
@@ -13,7 +13,7 @@ func MatchFiles(in string) ([]string, error) {
 		return nil, err
 	}
 
-	files, err := ioutil.ReadDir(abs)
+	files, err := os.ReadDir(abs)
 	if err != nil {
 		return nil, err
 	}
diff --git a/tools/goctl/pkg/parser/api/format/format.go b/tools/goctl/pkg/parser/api/format/format.go
index e7b3aa72..128580c7 100644
--- a/tools/goctl/pkg/parser/api/format/format.go
+++ b/tools/goctl/pkg/parser/api/format/format.go
@@ -3,14 +3,14 @@ package format
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
+	"os"
 
 	"github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/parser"
 )
 
 // File formats the api file.
 func File(filename string) error {
-	data, err := ioutil.ReadFile(filename)
+	data, err := os.ReadFile(filename)
 	if err != nil {
 		return err
 	}
@@ -18,7 +18,7 @@ func File(filename string) error {
 	if err := Source(data, buffer); err != nil {
 		return err
 	}
-	return ioutil.WriteFile(filename, buffer.Bytes(), 0666)
+	return os.WriteFile(filename, buffer.Bytes(), 0666)
 }
 
 // Source formats the api source.
diff --git a/tools/goctl/pkg/parser/api/scanner/scanner.go b/tools/goctl/pkg/parser/api/scanner/scanner.go
index 802684c6..35a9332d 100644
--- a/tools/goctl/pkg/parser/api/scanner/scanner.go
+++ b/tools/goctl/pkg/parser/api/scanner/scanner.go
@@ -4,8 +4,8 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
-	"io/ioutil"
 	"log"
+	"os"
 	"path/filepath"
 	"strings"
 
@@ -647,7 +647,7 @@ func NewScanner(filename string, src interface{}) (*Scanner, error) {
 }
 
 func readData(filename string, src interface{}) ([]byte, error) {
-	data, err := ioutil.ReadFile(filename)
+	data, err := os.ReadFile(filename)
 	if err == nil {
 		return data, nil
 	}
diff --git a/tools/goctl/plugin/plugin.go b/tools/goctl/plugin/plugin.go
index 321d6132..cf10685b 100644
--- a/tools/goctl/plugin/plugin.go
+++ b/tools/goctl/plugin/plugin.go
@@ -6,7 +6,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"os"
 	"os/exec"
@@ -171,7 +170,7 @@ func downloadFile(filepath, url string) error {
 // NewPlugin returns contextual resources when written in other languages
 func NewPlugin() (*Plugin, error) {
 	var plugin Plugin
-	content, err := ioutil.ReadAll(os.Stdin)
+	content, err := io.ReadAll(os.Stdin)
 	if err != nil {
 		return nil, err
 	}
diff --git a/tools/goctl/quickstart/micro.go b/tools/goctl/quickstart/micro.go
index 4d73af8e..ad776440 100644
--- a/tools/goctl/quickstart/micro.go
+++ b/tools/goctl/quickstart/micro.go
@@ -2,7 +2,7 @@ package quickstart
 
 import (
 	_ "embed"
-	"io/ioutil"
+	"os"
 	"path/filepath"
 
 	"github.com/zeromicro/go-zero/core/logx"
@@ -38,7 +38,7 @@ func initRPCProto() error {
 
 	protoFilename := filepath.Join(zrpcWorkDir, protoName)
 	rpcBytes := []byte(protocContent)
-	return ioutil.WriteFile(protoFilename, rpcBytes, 0o666)
+	return os.WriteFile(protoFilename, rpcBytes, 0o666)
 }
 
 type micro struct{}
@@ -55,7 +55,7 @@ func (m micro) mustStartRPCProject() {
 	arg := "goctl rpc protoc " + protoName + " --go_out=. --go-grpc_out=. --zrpc_out=. --verbose"
 	execCommand(zrpcWorkDir, arg)
 	etcFile := filepath.Join(zrpcWorkDir, "etc", "greet.yaml")
-	logx.Must(ioutil.WriteFile(etcFile, []byte(rpcEtcContent), 0o666))
+	logx.Must(os.WriteFile(etcFile, []byte(rpcEtcContent), 0o666))
 }
 
 func (m micro) start() {
diff --git a/tools/goctl/quickstart/mono.go b/tools/goctl/quickstart/mono.go
index 4710b1b3..5d04bf5d 100644
--- a/tools/goctl/quickstart/mono.go
+++ b/tools/goctl/quickstart/mono.go
@@ -2,7 +2,7 @@ package quickstart
 
 import (
 	_ "embed"
-	"io/ioutil"
+	"os"
 	"path/filepath"
 
 	"github.com/zeromicro/go-zero/core/logx"
@@ -35,7 +35,7 @@ func initAPIFlags() error {
 
 	apiFilename := filepath.Join(apiWorkDir, "greet.api")
 	apiBytes := []byte(apiContent)
-	if err := ioutil.WriteFile(apiFilename, apiBytes, 0o666); err != nil {
+	if err := os.WriteFile(apiFilename, apiBytes, 0o666); err != nil {
 		return err
 	}
 
@@ -59,7 +59,7 @@ func (m mono) createAPIProject() {
 	log.Debug(">> Generating quickstart api project...")
 	logx.Must(gogen.GoCommand(nil, nil))
 	etcFile := filepath.Join(apiWorkDir, "etc", "greet.yaml")
-	logx.Must(ioutil.WriteFile(etcFile, []byte(apiEtcContent), 0o666))
+	logx.Must(os.WriteFile(etcFile, []byte(apiEtcContent), 0o666))
 	logicFile := filepath.Join(apiWorkDir, "internal", "logic", "pinglogic.go")
 	svcFile := filepath.Join(apiWorkDir, "internal", "svc", "servicecontext.go")
 	configPath := filepath.Join(apiWorkDir, "internal", "config")
diff --git a/tools/goctl/rpc/generator/genconfig.go b/tools/goctl/rpc/generator/genconfig.go
index a81a07a8..2af78496 100644
--- a/tools/goctl/rpc/generator/genconfig.go
+++ b/tools/goctl/rpc/generator/genconfig.go
@@ -2,7 +2,6 @@ package generator
 
 import (
 	_ "embed"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 
@@ -36,5 +35,5 @@ func (g *Generator) GenConfig(ctx DirContext, _ parser.Proto, cfg *conf.Config)
 		return err
 	}
 
-	return ioutil.WriteFile(fileName, []byte(text), os.ModePerm)
+	return os.WriteFile(fileName, []byte(text), os.ModePerm)
 }
diff --git a/tools/goctl/util/pathx/file.go b/tools/goctl/util/pathx/file.go
index 6cbd037d..3121a19f 100644
--- a/tools/goctl/util/pathx/file.go
+++ b/tools/goctl/util/pathx/file.go
@@ -6,7 +6,7 @@ import (
 	"encoding/hex"
 	"fmt"
 	"io"
-	"io/ioutil"
+	"io/fs"
 	"log"
 	"os"
 	"path/filepath"
@@ -145,9 +145,20 @@ func GetTemplateDir(category string) (string, error) {
 		// backward compatible, it will be removed in the feature
 		// backward compatible start.
 		beforeTemplateDir := filepath.Join(home, version.GetGoctlVersion(), category)
-		fs, _ := ioutil.ReadDir(beforeTemplateDir)
+		entries, err := os.ReadDir(beforeTemplateDir)
+		if err != nil {
+			return "", err
+		}
+		infos := make([]fs.FileInfo, 0, len(entries))
+		for _, entry := range entries {
+			info, err := entry.Info()
+			if err != nil {
+				return "", err
+			}
+			infos = append(infos, info)
+		}
 		var hasContent bool
-		for _, e := range fs {
+		for _, e := range infos {
 			if e.Size() > 0 {
 				hasContent = true
 			}
@@ -256,7 +267,7 @@ func createTemplate(file, content string, force bool) error {
 
 // MustTempDir creates a temporary directory.
 func MustTempDir() string {
-	dir, err := ioutil.TempDir("", "")
+	dir, err := os.MkdirTemp("", "")
 	if err != nil {
 		log.Fatalln(err)
 	}
diff --git a/tools/goctl/util/templatex.go b/tools/goctl/util/templatex.go
index 981a6af6..726544c5 100644
--- a/tools/goctl/util/templatex.go
+++ b/tools/goctl/util/templatex.go
@@ -3,7 +3,7 @@ package util
 import (
 	"bytes"
 	goformat "go/format"
-	"io/ioutil"
+	"os"
 	"regexp"
 	"text/template"
 
@@ -50,7 +50,7 @@ func (t *DefaultTemplate) SaveTo(data any, path string, forceUpdate bool) error
 		return err
 	}
 
-	return ioutil.WriteFile(path, output.Bytes(), regularPerm)
+	return os.WriteFile(path, output.Bytes(), regularPerm)
 }
 
 // Execute returns the codes after the template executed


Test patch:
diff --git a/tools/goctl/api/format/format_test.go b/tools/goctl/api/format/format_test.go
index 786ac42b..da49bf1c 100644
--- a/tools/goctl/api/format/format_test.go
+++ b/tools/goctl/api/format/format_test.go
@@ -3,7 +3,6 @@ package format
 import (
 	"fmt"
 	"io/fs"
-	"io/ioutil"
 	"os"
 	"path"
 	"testing"
@@ -71,11 +70,11 @@ func Test_apiFormatReader_issue1721(t *testing.T) {
 	require.NoError(t, err)
 
 	importedFilename := path.Join(dir, "foo.api")
-	err = ioutil.WriteFile(importedFilename, []byte{}, fs.ModePerm)
+	err = os.WriteFile(importedFilename, []byte{}, fs.ModePerm)
 	require.NoError(t, err)
 
 	filename := path.Join(subDir, "bar.api")
-	err = ioutil.WriteFile(filename, []byte(fmt.Sprintf(`import "%s"`, importedFilename)), 0o644)
+	err = os.WriteFile(filename, []byte(fmt.Sprintf(`import "%s"`, importedFilename)), 0o644)
 	require.NoError(t, err)
 
 	f, err := os.Open(filename)
diff --git a/tools/goctl/api/parser/g4/ast/apiparser_test.go b/tools/goctl/api/parser/g4/ast/apiparser_test.go
index f873f397..71d73650 100644
--- a/tools/goctl/api/parser/g4/ast/apiparser_test.go
+++ b/tools/goctl/api/parser/g4/ast/apiparser_test.go
@@ -1,7 +1,6 @@
 package ast
 
 import (
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -25,13 +24,13 @@ func Test_ImportCycle(t *testing.T) {
 	defer os.RemoveAll(dir)
 
 	mainPath := filepath.Join(dir, mainFilename)
-	err = ioutil.WriteFile(mainPath, []byte(mainSrc), 0o777)
+	err = os.WriteFile(mainPath, []byte(mainSrc), 0o777)
 	require.NoError(t, err)
 	subAPath := filepath.Join(dir, subAFilename)
-	err = ioutil.WriteFile(subAPath, []byte(subASrc), 0o777)
+	err = os.WriteFile(subAPath, []byte(subASrc), 0o777)
 	require.NoError(t, err)
 	subBPath := filepath.Join(dir, subBFilename)
-	err = ioutil.WriteFile(subBPath, []byte(subBSrc), 0o777)
+	err = os.WriteFile(subBPath, []byte(subBSrc), 0o777)
 	require.NoError(t, err)
 
 	_, err = NewParser().Parse(mainPath)
@@ -55,13 +54,13 @@ func Test_MultiImportedShouldAllowed(t *testing.T) {
 	defer os.RemoveAll(dir)
 
 	mainPath := filepath.Join(dir, mainFilename)
-	err = ioutil.WriteFile(mainPath, []byte(mainSrc), 0o777)
+	err = os.WriteFile(mainPath, []byte(mainSrc), 0o777)
 	require.NoError(t, err)
 	subAPath := filepath.Join(dir, subAFilename)
-	err = ioutil.WriteFile(subAPath, []byte(subASrc), 0o777)
+	err = os.WriteFile(subAPath, []byte(subASrc), 0o777)
 	require.NoError(t, err)
 	subBPath := filepath.Join(dir, subBFilename)
-	err = ioutil.WriteFile(subBPath, []byte(subBSrc), 0o777)
+	err = os.WriteFile(subBPath, []byte(subBSrc), 0o777)
 	require.NoError(t, err)
 
 	_, err = NewParser().Parse(mainPath)
@@ -84,13 +83,13 @@ func Test_RedundantDeclarationShouldNotBeAllowed(t *testing.T) {
 	defer os.RemoveAll(dir)
 
 	mainPath := filepath.Join(dir, mainFilename)
-	err = ioutil.WriteFile(mainPath, []byte(mainSrc), 0o777)
+	err = os.WriteFile(mainPath, []byte(mainSrc), 0o777)
 	require.NoError(t, err)
 	subAPath := filepath.Join(dir, subAFilename)
-	err = ioutil.WriteFile(subAPath, []byte(subASrc), 0o777)
+	err = os.WriteFile(subAPath, []byte(subASrc), 0o777)
 	require.NoError(t, err)
 	subBPath := filepath.Join(dir, subBFilename)
-	err = ioutil.WriteFile(subBPath, []byte(subBSrc), 0o777)
+	err = os.WriteFile(subBPath, []byte(subBSrc), 0o777)
 	require.NoError(t, err)
 
 	_, err = NewParser().Parse(mainPath)
diff --git a/tools/goctl/api/parser/g4/test/apiparser_test.go b/tools/goctl/api/parser/g4/test/apiparser_test.go
index 764ef1fd..e00ba69a 100644
--- a/tools/goctl/api/parser/g4/test/apiparser_test.go
+++ b/tools/goctl/api/parser/g4/test/apiparser_test.go
@@ -2,7 +2,6 @@ package test
 
 import (
 	"fmt"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -120,7 +119,7 @@ func TestApiParser(t *testing.T) {
 
 	t.Run("nestedImport", func(t *testing.T) {
 		file := filepath.Join(pathx.MustTempDir(), "foo.api")
-		err := ioutil.WriteFile(file, []byte(nestedAPIImport), os.ModePerm)
+		err := os.WriteFile(file, []byte(nestedAPIImport), os.ModePerm)
 		if err != nil {
 			return
 		}
@@ -150,7 +149,7 @@ func TestApiParser(t *testing.T) {
 
 	t.Run("ambiguousSyntax", func(t *testing.T) {
 		file := filepath.Join(pathx.MustTempDir(), "foo.api")
-		err := ioutil.WriteFile(file, []byte(ambiguousSyntax), os.ModePerm)
+		err := os.WriteFile(file, []byte(ambiguousSyntax), os.ModePerm)
 		if err != nil {
 			return
 		}
@@ -164,7 +163,7 @@ func TestApiParser(t *testing.T) {
 
 	t.Run("ambiguousSyntax", func(t *testing.T) {
 		file := filepath.Join(pathx.MustTempDir(), "foo.api")
-		err := ioutil.WriteFile(file, []byte(ambiguousSyntax), os.ModePerm)
+		err := os.WriteFile(file, []byte(ambiguousSyntax), os.ModePerm)
 		if err != nil {
 			return
 		}
@@ -178,7 +177,7 @@ func TestApiParser(t *testing.T) {
 
 	t.Run("ambiguousService", func(t *testing.T) {
 		file := filepath.Join(pathx.MustTempDir(), "foo.api")
-		err := ioutil.WriteFile(file, []byte(ambiguousService), os.ModePerm)
+		err := os.WriteFile(file, []byte(ambiguousService), os.ModePerm)
 		if err != nil {
 			return
 		}
@@ -208,7 +207,7 @@ func TestApiParser(t *testing.T) {
 		assert.Error(t, err)
 
 		file := filepath.Join(pathx.MustTempDir(), "foo.api")
-		err = ioutil.WriteFile(file, []byte(duplicateHandler), os.ModePerm)
+		err = os.WriteFile(file, []byte(duplicateHandler), os.ModePerm)
 		if err != nil {
 			return
 		}
@@ -237,7 +236,7 @@ func TestApiParser(t *testing.T) {
 		assert.Error(t, err)
 
 		file := filepath.Join(pathx.MustTempDir(), "foo.api")
-		err = ioutil.WriteFile(file, []byte(duplicateRoute), os.ModePerm)
+		err = os.WriteFile(file, []byte(duplicateRoute), os.ModePerm)
 		if err != nil {
 			return
 		}
@@ -261,7 +260,7 @@ func TestApiParser(t *testing.T) {
 		assert.Error(t, err)
 
 		file := filepath.Join(pathx.MustTempDir(), "foo.api")
-		err = ioutil.WriteFile(file, []byte(duplicateType), os.ModePerm)
+		err = os.WriteFile(file, []byte(duplicateType), os.ModePerm)
 		if err != nil {
 			return
 		}
diff --git a/tools/goctl/compare/testdata/testdata.go b/tools/goctl/compare/testdata/testdata.go
index efed937c..c11b3d0a 100644
--- a/tools/goctl/compare/testdata/testdata.go
+++ b/tools/goctl/compare/testdata/testdata.go
@@ -2,7 +2,6 @@ package testdata
 
 import (
 	"fmt"
-	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
@@ -78,7 +77,7 @@ func mustGetTestData(baseDir string) (Files, Files) {
 			return data, nil
 		}
 
-		return data, ioutil.WriteFile(fp, []byte(data.Content), os.ModePerm)
+		return data, os.WriteFile(fp, []byte(data.Content), os.ModePerm)
 	}
 	oldDir := filepath.Join(baseDir, "old_fs")
 	newDir := filepath.Join(baseDir, "new_fs")
diff --git a/tools/goctl/model/mongo/generate/generate_test.go b/tools/goctl/model/mongo/generate/generate_test.go
index 3586b60a..2ea6c758 100644
--- a/tools/goctl/model/mongo/generate/generate_test.go
+++ b/tools/goctl/model/mongo/generate/generate_test.go
@@ -1,7 +1,7 @@
 package generate
 
 import (
-	"io/ioutil"
+	"os"
 	"path/filepath"
 	"testing"
 
@@ -22,7 +22,7 @@ func TestDo(t *testing.T) {
 
 		tempDir := pathx.MustTempDir()
 		typesfile := filepath.Join(tempDir, "types.go")
-		err = ioutil.WriteFile(typesfile, []byte(testTypes), 0o666)
+		err = os.WriteFile(typesfile, []byte(testTypes), 0o666)
 		assert.Nil(t, err)
 
 		err = Do(&Context{
@@ -38,7 +38,7 @@ func TestDo(t *testing.T) {
 	t.Run("missing config", func(t *testing.T) {
 		tempDir := t.TempDir()
 		typesfile := filepath.Join(tempDir, "types.go")
-		err := ioutil.WriteFile(typesfile, []byte(testTypes), 0o666)
+		err := os.WriteFile(typesfile, []byte(testTypes), 0o666)
 		assert.Nil(t, err)
 
 		err = Do(&Context{
@@ -54,7 +54,7 @@ func TestDo(t *testing.T) {
 		cfg := &config.Config{NamingFormat: "foo"}
 		tempDir := t.TempDir()
 		typesfile := filepath.Join(tempDir, "types.go")
-		err := ioutil.WriteFile(typesfile, []byte(testTypes), 0o666)
+		err := os.WriteFile(typesfile, []byte(testTypes), 0o666)
 		assert.Nil(t, err)
 
 		err = Do(&Context{
diff --git a/tools/goctl/model/sql/command/command_test.go b/tools/goctl/model/sql/command/command_test.go
index 330a6630..fa85e6e8 100644
--- a/tools/goctl/model/sql/command/command_test.go
+++ b/tools/goctl/model/sql/command/command_test.go
@@ -2,7 +2,6 @@ package command
 
 import (
 	_ "embed"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"sort"
@@ -76,12 +75,12 @@ func TestFromDDl(t *testing.T) {
 	user1Sql := filepath.Join(tempDir, "user1.sql")
 	user2Sql := filepath.Join(tempDir, "user2.sql")
 
-	err = ioutil.WriteFile(user1Sql, []byte(sql), os.ModePerm)
+	err = os.WriteFile(user1Sql, []byte(sql), os.ModePerm)
 	if err != nil {
 		return
 	}
 
-	err = ioutil.WriteFile(user2Sql, []byte(sql), os.ModePerm)
+	err = os.WriteFile(user2Sql, []byte(sql), os.ModePerm)
 	if err != nil {
 		return
 	}
diff --git a/tools/goctl/model/sql/command/migrationnotes/v1.3.4_test.go b/tools/goctl/model/sql/command/migrationnotes/v1.3.4_test.go
index 4d77bbfc..80642833 100644
--- a/tools/goctl/model/sql/command/migrationnotes/v1.3.4_test.go
+++ b/tools/goctl/model/sql/command/migrationnotes/v1.3.4_test.go
@@ -2,7 +2,6 @@ package migrationnotes
 
 import (
 	"io/fs"
-	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -18,15 +17,15 @@ func Test_needShow1_3_4(t *testing.T) {
 
 	dir1 := path.Join(root, "dir1")
 	require.NoError(t, os.Mkdir(dir1, fs.ModePerm))
-	ioutil.WriteFile(filepath.Join(dir1, "foo_gen.go"), nil, fs.ModePerm)
+	os.WriteFile(filepath.Join(dir1, "foo_gen.go"), nil, fs.ModePerm)
 
 	dir2 := path.Join(root, "dir2")
 	require.NoError(t, os.Mkdir(dir2, fs.ModePerm))
-	ioutil.WriteFile(filepath.Join(dir2, "foomodel.go"), nil, fs.ModePerm)
+	os.WriteFile(filepath.Join(dir2, "foomodel.go"), nil, fs.ModePerm)
 
 	dir3 := path.Join(root, "dir3")
 	require.NoError(t, os.Mkdir(dir3, fs.ModePerm))
-	ioutil.WriteFile(filepath.Join(dir3, "irrelevant.go"), nil, fs.ModePerm)
+	os.WriteFile(filepath.Join(dir3, "irrelevant.go"), nil, fs.ModePerm)
 
 	type args struct {
 		dir   string
diff --git a/tools/goctl/model/sql/gen/gen_test.go b/tools/goctl/model/sql/gen/gen_test.go
index 48d1060d..676e044c 100644
--- a/tools/goctl/model/sql/gen/gen_test.go
+++ b/tools/goctl/model/sql/gen/gen_test.go
@@ -3,7 +3,6 @@ package gen
 import (
 	"database/sql"
 	_ "embed"
-	"io/ioutil"
 	"os"
 	"path"
 	"path/filepath"
@@ -30,7 +29,7 @@ func TestCacheModel(t *testing.T) {
 	_ = Clean()
 
 	sqlFile := filepath.Join(pathx.MustTempDir(), "tmp.sql")
-	err := ioutil.WriteFile(sqlFile, []byte(source), 0o777)
+	err := os.WriteFile(sqlFile, []byte(source), 0o777)
 	assert.Nil(t, err)
 
 	dir := filepath.Join(pathx.MustTempDir(), "./testmodel")
@@ -65,7 +64,7 @@ func TestNamingModel(t *testing.T) {
 	_ = Clean()
 
 	sqlFile := filepath.Join(pathx.MustTempDir(), "tmp.sql")
-	err := ioutil.WriteFile(sqlFile, []byte(source), 0o777)
+	err := os.WriteFile(sqlFile, []byte(source), 0o777)
 	assert.Nil(t, err)
 
 	dir, _ := filepath.Abs("./testmodel")
@@ -103,7 +102,7 @@ func TestFolderName(t *testing.T) {
 	_ = Clean()
 
 	sqlFile := filepath.Join(pathx.MustTempDir(), "tmp.sql")
-	err := ioutil.WriteFile(sqlFile, []byte(source), 0o777)
+	err := os.WriteFile(sqlFile, []byte(source), 0o777)
 	assert.Nil(t, err)
 
 	dir, _ := filepath.Abs("./testmodel")
@@ -179,7 +178,7 @@ func Test_genPublicModel(t *testing.T) {
 	defer os.RemoveAll(dir)
 
 	modelFilename := filepath.Join(modelDir, "foo.sql")
-	err = ioutil.WriteFile(modelFilename, []byte(source), 0o777)
+	err = os.WriteFile(modelFilename, []byte(source), 0o777)
 	require.NoError(t, err)
 
 	g, err := NewDefaultGenerator(modelDir, &config.Config{
diff --git a/tools/goctl/model/sql/parser/parser_test.go b/tools/goctl/model/sql/parser/parser_test.go
index 0d205287..3f67a81d 100644
--- a/tools/goctl/model/sql/parser/parser_test.go
+++ b/tools/goctl/model/sql/parser/parser_test.go
@@ -2,7 +2,7 @@ package parser
 
 import (
 	_ "embed"
-	"io/ioutil"
+	"os"
 	"path/filepath"
 	"testing"
 
@@ -15,7 +15,7 @@ import (
 
 func TestParsePlainText(t *testing.T) {
 	sqlFile := filepath.Join(pathx.MustTempDir(), "tmp.sql")
-	err := ioutil.WriteFile(sqlFile, []byte("plain text"), 0o777)
+	err := os.WriteFile(sqlFile, []byte("plain text"), 0o777)
 	assert.Nil(t, err)
 
 	_, err = Parse(sqlFile, "go_zero", false)
@@ -24,7 +24,7 @@ func TestParsePlainText(t *testing.T) {
 
 func TestParseSelect(t *testing.T) {
 	sqlFile := filepath.Join(pathx.MustTempDir(), "tmp.sql")
-	err := ioutil.WriteFile(sqlFile, []byte("select * from user"), 0o777)
+	err := os.WriteFile(sqlFile, []byte("select * from user"), 0o777)
 	assert.Nil(t, err)
 
 	tables, err := Parse(sqlFile, "go_zero", false)
@@ -37,7 +37,7 @@ var user string
 
 func TestParseCreateTable(t *testing.T) {
 	sqlFile := filepath.Join(pathx.MustTempDir(), "tmp.sql")
-	err := ioutil.WriteFile(sqlFile, []byte(user), 0o777)
+	err := os.WriteFile(sqlFile, []byte(user), 0o777)
 	assert.Nil(t, err)
 
 	tables, err := Parse(sqlFile, "go_zero", false)
diff --git a/tools/goctl/pkg/parser/api/parser/analyzer_test.go b/tools/goctl/pkg/parser/api/parser/analyzer_test.go
index 28266f32..de4193b6 100644
--- a/tools/goctl/pkg/parser/api/parser/analyzer_test.go
+++ b/tools/goctl/pkg/parser/api/parser/analyzer_test.go
@@ -3,7 +3,7 @@ package parser
 import (
 	"bytes"
 	"fmt"
-	"io/ioutil"
+	"os"
 	"path/filepath"
 	"strings"
 	"testing"
@@ -18,7 +18,7 @@ func Test_Parse(t *testing.T) {
 		assert.Nil(t, err)
 	})
 	t.Run("invalid", func(t *testing.T) {
-		data, err := ioutil.ReadFile("./testdata/invalid.api")
+		data, err := os.ReadFile("./testdata/invalid.api")
 		assert.NoError(t, err)
 		splits := bytes.Split(data, []byte("-----"))
 		var testFile []string
@@ -29,7 +29,7 @@ func Test_Parse(t *testing.T) {
 				continue
 			}
 			filename := filepath.Join(t.TempDir(), fmt.Sprintf("invalid%d.api", idx))
-			err := ioutil.WriteFile(filename, split, 0666)
+			err := os.WriteFile(filename, split, 0666)
 			assert.NoError(t, err)
 			testFile = append(testFile, filename)
 		}
diff --git a/tools/goctl/rpc/generator/genpb_test.go b/tools/goctl/rpc/generator/genpb_test.go
index 04f7fcf8..9ed939a4 100644
--- a/tools/goctl/rpc/generator/genpb_test.go
+++ b/tools/goctl/rpc/generator/genpb_test.go
@@ -1,7 +1,6 @@
 package generator
 
 import (
-	"io/ioutil"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -14,7 +13,7 @@ import (
 func Test_findPbFile(t *testing.T) {
 	dir := t.TempDir()
 	protoFile := filepath.Join(dir, "greet.proto")
-	err := ioutil.WriteFile(protoFile, []byte(`
+	err := os.WriteFile(protoFile, []byte(`
 syntax = "proto3";
 
 package greet;
diff --git a/tools/goctl/util/pathx/file_test.go b/tools/goctl/util/pathx/file_test.go
index 7505fe49..99833e39 100644
--- a/tools/goctl/util/pathx/file_test.go
+++ b/tools/goctl/util/pathx/file_test.go
@@ -1,7 +1,6 @@
 package pathx
 
 import (
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -23,7 +22,7 @@ func TestGetTemplateDir(t *testing.T) {
 			return
 		}
 		tempFile := filepath.Join(dir, "bar.txt")
-		err = ioutil.WriteFile(tempFile, []byte("foo"), os.ModePerm)
+		err = os.WriteFile(tempFile, []byte("foo"), os.ModePerm)
 		if err != nil {
 			return
 		}
@@ -79,7 +78,7 @@ func TestGetGoctlHome(t *testing.T) {
 	t.Run("goctl_is_file", func(t *testing.T) {
 		tmpFile := filepath.Join(t.TempDir(), "a.tmp")
 		backupTempFile := tmpFile + ".old"
-		err := ioutil.WriteFile(tmpFile, nil, 0o666)
+		err := os.WriteFile(tmpFile, nil, 0o666)
 		if err != nil {
 			return
 		}
diff --git a/tools/goctl/util/pathx/path_test.go b/tools/goctl/util/pathx/path_test.go
index 67b5a4b5..0b7c2a82 100644
--- a/tools/goctl/util/pathx/path_test.go
+++ b/tools/goctl/util/pathx/path_test.go
@@ -1,7 +1,6 @@
 package pathx
 
 import (
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"testing"
@@ -10,9 +9,9 @@ import (
 )
 
 func TestReadLink(t *testing.T) {
-	dir, err := ioutil.TempDir("", "go-zero")
+	dir, err := os.CreateTemp("", "go-zero")
 	assert.Nil(t, err)
-	symLink := filepath.Join(dir, "test")
+	symLink := filepath.Join(dir.Name(), "test")
 	pwd, err := os.Getwd()
 	assertError(err, t)