Repository: goccy/go-yaml
Pull request #703 (2025-04-22 06:15:25)

Clean up encoder.go
While working on another issue, I noticed a few minor problems in encoder.go. I could include the fixes in the same PR, but I thought it would be better to create a separate PR for easier review.

- defer statements can be placed inside the if statement
- Some variables are shadowing external functions or variables

---

- [x] Describe the purpose for which you created this PR.  
- [x] Create test code that corresponds to the modification

codecov-commenter: :warning: Please install the !['codecov app svg image'](https://github.com/codecov/engineering-team/assets/152432831/e90313f4-9d3a-4b63-8b54-cfe14e7ec20d) to ensure uploads and comments are reliably processed by Codecov.

## [Codecov](https://app.codecov.io/gh/goccy/go-yaml/pull/703?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Masaaki+Goshima) Report
Attention: Patch coverage is `91.66667%` with `5 lines` in your changes missing coverage. Please review.
> Project coverage is 77.86%. Comparing base [(`d1e3460`)](https://app.codecov.io/gh/goccy/go-yaml/commit/d1e3460292544f8aa9df85f227df26d3d2298bd9?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Masaaki+Goshima) to head [(`6c4b4af`)](https://app.codecov.io/gh/goccy/go-yaml/commit/6c4b4af57e3551a7915972f75408770e6008ad30?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Masaaki+Goshima).

:exclamation: Your organization needs to install the [Codecov GitHub app](https://github.com/apps/codecov/installations/select_target) to enable full functionality.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #703      +/-   ##
==========================================
- Coverage   77.89%   77.86%   -0.03%     
==========================================
  Files          22       22              
  Lines        7965     7957       -8     
==========================================
- Hits         6204     6196       -8     
  Misses       1348     1348              
  Partials      413      413              
```

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>

Patch:
diff --git a/.golangci.yml b/.golangci.yml
index 9ba6690..05675c8 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,49 +1,65 @@
-run:
-  timeout: 5m
-
-linters-settings:
-  errcheck:
-    check-type-assertions: true
-  gci:
-    sections:
-      - "standard"
-      - "default"
-      - "prefix(github.com/goccy/go-yaml)"
-      - "blank"
-      - "dot"
-  gofmt:
-    simplify: true
-  govet:
-    disable:
-      - tests
-  misspell:
-    locale: US
-  perfsprint:
-    int-conversion: false
-    err-error: false
-    errorf: true
-    sprintf1: false
-    strconcat: false
-  staticcheck:
-    checks: ["all", "-ST1000", "-ST1005"]
-
+version: "2"
 linters:
-  disable-all: true
+  default: none
   enable:
     - errcheck
-    - gci
-    - gofmt
-    - gosimple
     - govet
     - ineffassign
     - misspell
     - perfsprint
     - staticcheck
-    - typecheck
     - unused
-
-issues:
-  exclude-rules:
-    - path: _test\.go
-      linters:
-        - staticcheck
+  settings:
+    errcheck:
+      without_tests: true
+    govet:
+      disable:
+        - tests
+    misspell:
+      locale: US
+    perfsprint:
+      int-conversion: false
+      err-error: false
+      errorf: true
+      sprintf1: false
+      strconcat: false
+    staticcheck:
+      checks:
+        - -ST1000
+        - -ST1005
+        - all
+  exclusions:
+    generated: lax
+    presets:
+      - comments
+      - common-false-positives
+      - legacy
+      - std-error-handling
+    rules:
+      - linters:
+          - staticcheck
+        path: _test\.go
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
+formatters:
+  enable:
+    - gci
+    - gofmt
+  settings:
+    gci:
+      sections:
+        - standard
+        - default
+        - prefix(github.com/goccy/go-yaml)
+        - blank
+        - dot
+    gofmt:
+      simplify: true
+  exclusions:
+    generated: lax
+    paths:
+      - third_party$
+      - builtin$
+      - examples$
diff --git a/Makefile b/Makefile
index 9166062..5993616 100644
--- a/Makefile
+++ b/Makefile
@@ -5,17 +5,13 @@ TESTMOD := testdata/go_test.mod
 $(LOCALBIN):
 	mkdir -p $(LOCALBIN)
 
-.PHONY: testmod
-	cp go.mod testdata/go_test.mod
-	go mod tidy -modfile=$(TESTMOD)
-
 .PHONY: test
-test: testmod
+test:
 	go test -v -race ./...
 	go test -v -race ./testdata -modfile=$(TESTMOD)
 
 .PHONY: simple-test
-simple-test: testmod
+simple-test:
 	go test -v ./...
 	go test -v ./testdata -modfile=$(TESTMOD)
 
@@ -24,7 +20,7 @@ fuzz:
 	go test -fuzz=Fuzz -fuzztime 60s
 
 .PHONY: cover
-cover: testmod
+cover:
 	go test -coverpkg=.,./ast,./lexer,./parser,./printer,./scanner,./token -coverprofile=cover.out -modfile=$(TESTMOD) ./... ./testdata
 
 .PHONY: cover-html
@@ -49,11 +45,11 @@ fmt: golangci-lint ## Ensure consistent code style
 GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint
 
 ## Tool Versions
-GOLANGCI_VERSION := 1.61.0
+GOLANGCI_VERSION := 2.1.2
 
 .PHONY: golangci-lint
 .PHONY: $(GOLANGCI_LINT)
 golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
 $(GOLANGCI_LINT): $(LOCALBIN)
-	@test -s $(LOCALBIN)/golangci-lint && $(LOCALBIN)/golangci-lint version --format short | grep -q $(GOLANGCI_VERSION) || \
+	@test -s $(LOCALBIN)/golangci-lint && $(LOCALBIN)/golangci-lint version --short | grep -q $(GOLANGCI_VERSION) || \
 	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(LOCALBIN) v$(GOLANGCI_VERSION)
diff --git a/benchmarks/go.mod b/benchmarks/go.mod
index 195db58..8895c6d 100644
--- a/benchmarks/go.mod
+++ b/benchmarks/go.mod
@@ -1,8 +1,8 @@
-module benchmarks
+module github.com/goccy/go-yaml/benchmarks
 
-go 1.12
+go 1.21.0
 
-replace github.com/goccy/go-yaml => ../
+replace github.com/goccy/go-yaml => ..
 
 require (
 	github.com/goccy/go-yaml v0.0.0-00010101000000-000000000000
diff --git a/benchmarks/go.sum b/benchmarks/go.sum
index 3c36f01..60008f2 100644
--- a/benchmarks/go.sum
+++ b/benchmarks/go.sum
@@ -1,116 +1,6 @@
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
-github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
-github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
-github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
-github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
-github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
-github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
-github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
-github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
-github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
-github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
-github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
-github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
-github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
-golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
-golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
-golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
-golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
-golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
-golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
-golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
-golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
-golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
-golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
-golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
-golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
-golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
-golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/decode.go b/decode.go
index 9d85a9b..052abee 100644
--- a/decode.go
+++ b/decode.go
@@ -295,7 +295,7 @@ func (d *Decoder) addSequenceNodeCommentToMap(node *ast.SequenceNode) {
 func (d *Decoder) addFootCommentToMap(node ast.Node) {
 	var (
 		footComment     *ast.CommentGroupNode
-		footCommentPath string = node.GetPath()
+		footCommentPath = node.GetPath()
 	)
 	switch n := node.(type) {
 	case *ast.SequenceNode:
diff --git a/encode.go b/encode.go
index 813d7fc..0a789bf 100644
--- a/encode.go
+++ b/encode.go
@@ -330,7 +330,7 @@ func (e *Encoder) canEncodeByMarshaler(v reflect.Value) bool {
 		return true
 	case InterfaceMarshaler:
 		return true
-	case time.Time:
+	case time.Time, *time.Time:
 		return true
 	case time.Duration:
 		return true
@@ -400,20 +400,21 @@ func (e *Encoder) encodeByMarshaler(ctx context.Context, v reflect.Value, column
 	if t, ok := iface.(time.Time); ok {
 		return e.encodeTime(t, column), nil
 	}
+	// Handle *time.Time explicitly since it implements TextMarshaler and shouldn't be treated as plain text
+	if t, ok := iface.(*time.Time); ok && t != nil {
+		return e.encodeTime(*t, column), nil
+	}
 
 	if t, ok := iface.(time.Duration); ok {
 		return e.encodeDuration(t, column), nil
 	}
 
 	if marshaler, ok := iface.(encoding.TextMarshaler); ok {
-		doc, err := marshaler.MarshalText()
-		if err != nil {
-			return nil, err
-		}
-		node, err := e.encodeDocument(doc)
+		text, err := marshaler.MarshalText()
 		if err != nil {
 			return nil, err
 		}
+		node := e.encodeString(string(text), column)
 		return node, nil
 	}
 
@@ -604,12 +605,8 @@ func (e *Encoder) encodeBool(v bool) *ast.BoolNode {
 func (e *Encoder) encodeSlice(ctx context.Context, value reflect.Value) (*ast.SequenceNode, error) {
 	if e.indentSequence {
 		e.column += e.indentNum
+		defer func() { e.column -= e.indentNum }()
 	}
-	defer func() {
-		if e.indentSequence {
-			e.column -= e.indentNum
-		}
-	}()
 	column := e.column
 	sequence := ast.Sequence(token.New("-", "-", e.pos(column)), e.isFlowStyle)
 	for i := 0; i < value.Len(); i++ {
@@ -625,12 +622,8 @@ func (e *Encoder) encodeSlice(ctx context.Context, value reflect.Value) (*ast.Se
 func (e *Encoder) encodeArray(ctx context.Context, value reflect.Value) (*ast.SequenceNode, error) {
 	if e.indentSequence {
 		e.column += e.indentNum
+		defer func() { e.column -= e.indentNum }()
 	}
-	defer func() {
-		if e.indentSequence {
-			e.column -= e.indentNum
-		}
-	}()
 	column := e.column
 	sequence := ast.Sequence(token.New("-", "-", e.pos(column)), e.isFlowStyle)
 	for i := 0; i < value.Len(); i++ {
@@ -666,11 +659,11 @@ func (e *Encoder) encodeMapItem(ctx context.Context, item MapItem, column int) (
 func (e *Encoder) encodeMapSlice(ctx context.Context, value MapSlice, column int) (*ast.MappingNode, error) {
 	node := ast.Mapping(token.New("", "", e.pos(column)), e.isFlowStyle)
 	for _, item := range value {
-		value, err := e.encodeMapItem(ctx, item, column)
+		encoded, err := e.encodeMapItem(ctx, item, column)
 		if err != nil {
 			return nil, err
 		}
-		node.Values = append(node.Values, value)
+		node.Values = append(node.Values, encoded)
 	}
 	return node, nil
 }
@@ -697,15 +690,15 @@ func (e *Encoder) encodeMap(ctx context.Context, value reflect.Value, column int
 	for _, key := range keys {
 		k := reflect.ValueOf(key)
 		v := value.MapIndex(k)
-		value, err := e.encodeValue(ctx, v, column)
+		encoded, err := e.encodeValue(ctx, v, column)
 		if err != nil {
 			return nil, err
 		}
-		if e.isMapNode(value) {
-			value.AddColumn(e.indentNum)
+		if e.isMapNode(encoded) {
+			encoded.AddColumn(e.indentNum)
 		}
-		if e.isTagAndMapNode(value) {
-			value.AddColumn(e.indentNum)
+		if e.isTagAndMapNode(encoded) {
+			encoded.AddColumn(e.indentNum)
 		}
 		keyText := fmt.Sprint(key)
 		vRef := e.toPointer(v)
@@ -715,13 +708,13 @@ func (e *Encoder) encodeMap(ctx context.Context, value reflect.Value, column int
 			anchorName := aliasName
 			anchorNode := ast.Anchor(token.New("&", "&", e.pos(column)))
 			anchorNode.Name = ast.String(token.New(anchorName, anchorName, e.pos(column)))
-			anchorNode.Value = value
-			value = anchorNode
+			anchorNode.Value = encoded
+			encoded = anchorNode
 		}
 		node.Values = append(node.Values, ast.MappingValue(
 			nil,
 			e.encodeString(keyText, column),
-			value,
+			encoded,
 		))
 		e.setSmartAnchor(vRef, keyText)
 	}
@@ -812,7 +805,7 @@ func (e *Encoder) encodeAnchor(anchorName string, value ast.Node, fieldValue ref
 func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column int) (ast.Node, error) {
 	node := ast.Mapping(token.New("", "", e.pos(column)), e.isFlowStyle)
 	structType := value.Type()
-	structFieldMap, err := structFieldMap(structType)
+	fieldMap, err := structFieldMap(structType)
 	if err != nil {
 		return nil, err
 	}
@@ -824,85 +817,85 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column
 			continue
 		}
 		fieldValue := value.FieldByName(field.Name)
-		structField := structFieldMap[field.Name]
-		if (e.omitEmpty || structField.IsOmitEmpty) && e.isZeroValue(fieldValue) {
+		sf := fieldMap[field.Name]
+		if (e.omitEmpty || sf.IsOmitEmpty) && e.isZeroValue(fieldValue) {
 			// omit encoding
 			continue
 		}
 		ve := e
-		if !e.isFlowStyle && structField.IsFlow {
+		if !e.isFlowStyle && sf.IsFlow {
 			ve = &Encoder{}
 			*ve = *e
 			ve.isFlowStyle = true
 		}
-		value, err := ve.encodeValue(ctx, fieldValue, column)
+		encoded, err := ve.encodeValue(ctx, fieldValue, column)
 		if err != nil {
 			return nil, err
 		}
-		if e.isMapNode(value) {
-			value.AddColumn(e.indentNum)
+		if e.isMapNode(encoded) {
+			encoded.AddColumn(e.indentNum)
 		}
-		var key ast.MapKeyNode = e.encodeString(structField.RenderName, column)
+		var key ast.MapKeyNode = e.encodeString(sf.RenderName, column)
 		switch {
-		case value.Type() == ast.AliasType:
-			if aliasName := structField.AliasName; aliasName != "" {
-				alias, ok := value.(*ast.AliasNode)
+		case encoded.Type() == ast.AliasType:
+			if aliasName := sf.AliasName; aliasName != "" {
+				alias, ok := encoded.(*ast.AliasNode)
 				if !ok {
-					return nil, errors.ErrUnexpectedNodeType(value.Type(), ast.AliasType, value.GetToken())
+					return nil, errors.ErrUnexpectedNodeType(encoded.Type(), ast.AliasType, encoded.GetToken())
 				}
 				got := alias.Value.String()
 				if aliasName != got {
 					return nil, fmt.Errorf("expected alias name is %q but got %q", aliasName, got)
 				}
 			}
-			if structField.IsInline {
+			if sf.IsInline {
 				// if both used alias and inline, output `<<: *alias`
 				key = ast.MergeKey(token.New("<<", "<<", e.pos(column)))
 			}
-		case structField.AnchorName != "":
-			anchorNode, err := e.encodeAnchor(structField.AnchorName, value, fieldValue, column)
+		case sf.AnchorName != "":
+			anchorNode, err := e.encodeAnchor(sf.AnchorName, encoded, fieldValue, column)
 			if err != nil {
 				return nil, err
 			}
-			value = anchorNode
-		case structField.IsInline:
-			isAutoAnchor := structField.IsAutoAnchor
+			encoded = anchorNode
+		case sf.IsInline:
+			isAutoAnchor := sf.IsAutoAnchor
 			if !hasInlineAnchorField {
 				hasInlineAnchorField = isAutoAnchor
 			}
 			if isAutoAnchor {
 				inlineAnchorValue = fieldValue
 			}
-			mapNode, ok := value.(ast.MapNode)
+			mapNode, ok := encoded.(ast.MapNode)
 			if !ok {
 				// if an inline field is null, skip encoding it
-				if _, ok := value.(*ast.NullNode); ok {
+				if _, ok := encoded.(*ast.NullNode); ok {
 					continue
 				}
 				return nil, errors.New("inline value is must be map or struct type")
 			}
 			mapIter := mapNode.MapRange()
 			for mapIter.Next() {
-				key := mapIter.Key()
-				value := mapIter.Value()
-				keyName := key.GetToken().Value
-				if structFieldMap.isIncludedRenderName(keyName) {
-					// if declared same key name, skip encoding this field
+				mapKey := mapIter.Key()
+				mapValue := mapIter.Value()
+				keyName := mapKey.GetToken().Value
+				if fieldMap.isIncludedRenderName(keyName) {
+					// if declared the same key name, skip encoding this field
 					continue
 				}
-				key.AddColumn(-e.indentNum)
-				value.AddColumn(-e.indentNum)
-				node.Values = append(node.Values, ast.MappingValue(nil, key, value))
+				mapKey.AddColumn(-e.indentNum)
+				mapValue.AddColumn(-e.indentNum)
+				node.Values = append(node.Values, ast.MappingValue(nil, mapKey, mapValue))
 			}
 			continue
-		case structField.IsAutoAnchor:
-			anchorNode, err := e.encodeAnchor(structField.RenderName, value, fieldValue, column)
+		case sf.IsAutoAnchor:
+			anchorNode, err := e.encodeAnchor(sf.RenderName, encoded, fieldValue, column)
 			if err != nil {
 				return nil, err
 			}
-			value = anchorNode
+			encoded = anchorNode
 		}
-		node.Values = append(node.Values, ast.MappingValue(nil, key, value))
+		node.Values = append(node.Values, ast.MappingValue(nil, key, encoded))
 	}
 	if hasInlineAnchorField {
 		node.AddColumn(e.indentNum)
diff --git a/printer/printer.go b/printer/printer.go
index e2a7c3c..9346983 100644
--- a/printer/printer.go
+++ b/printer/printer.go
@@ -251,10 +251,7 @@ func (p *Printer) isNewLineLastChar(s string) bool {
 }
 
 func (p *Printer) printBeforeTokens(tk *token.Token, minLine, extLine int) token.Tokens {
-	for {
-		if tk.Prev == nil {
-			break
-		}
+	for tk.Prev != nil {
 		if tk.Prev.Position.Line < minLine {
 			break
 		}
diff --git a/struct.go b/struct.go
index dae4d65..884924b 100644
--- a/struct.go
+++ b/struct.go
@@ -44,7 +44,7 @@ func structField(field reflect.StructField) *StructField {
 			fieldName = options[0]
 		}
 	}
-	structField := &StructField{
+	sf := &StructField{
 		FieldName:  field.Name,
 		RenderName: fieldName,
 	}
@@ -52,30 +52,30 @@ func structField(field reflect.StructField) *StructField {
 		for _, opt := range options[1:] {
 			switch {
 			case opt == "omitempty":
-				structField.IsOmitEmpty = true
+				sf.IsOmitEmpty = true
 			case opt == "flow":
-				structField.IsFlow = true
+				sf.IsFlow = true
 			case opt == "inline":
-				structField.IsInline = true
+				sf.IsInline = true
 			case strings.HasPrefix(opt, "anchor"):
 				anchor := strings.Split(opt, "=")
 				if len(anchor) > 1 {
-					structField.AnchorName = anchor[1]
+					sf.AnchorName = anchor[1]
 				} else {
-					structField.IsAutoAnchor = true
+					sf.IsAutoAnchor = true
 				}
 			case strings.HasPrefix(opt, "alias"):
 				alias := strings.Split(opt, "=")
 				if len(alias) > 1 {
-					structField.AliasName = alias[1]
+					sf.AliasName = alias[1]
 				} else {
-					structField.IsAutoAlias = true
+					sf.IsAutoAlias = true
 				}
 			default:
 			}
 		}
 	}
-	return structField
+	return sf
 }
 
 func isIgnoredStructField(field reflect.StructField) bool {
@@ -107,19 +107,19 @@ func (m StructFieldMap) hasMergeProperty() bool {
 }
 
 func structFieldMap(structType reflect.Type) (StructFieldMap, error) {
-	structFieldMap := StructFieldMap{}
+	fieldMap := StructFieldMap{}
 	renderNameMap := map[string]struct{}{}
 	for i := 0; i < structType.NumField(); i++ {
 		field := structType.Field(i)
 		if isIgnoredStructField(field) {
 			continue
 		}
-		structField := structField(field)
-		if _, exists := renderNameMap[structField.RenderName]; exists {
-			return nil, fmt.Errorf("duplicated struct field name %s", structField.RenderName)
+		sf := structField(field)
+		if _, exists := renderNameMap[sf.RenderName]; exists {
+			return nil, fmt.Errorf("duplicated struct field name %s", sf.RenderName)
 		}
-		structFieldMap[structField.FieldName] = structField
-		renderNameMap[structField.RenderName] = struct{}{}
+		fieldMap[sf.FieldName] = sf
+		renderNameMap[sf.RenderName] = struct{}{}
 	}
-	return structFieldMap, nil
+	return fieldMap, nil
 }


Test patch:
diff --git a/encode_test.go b/encode_test.go
index 9864725..613931c 100644
--- a/encode_test.go
+++ b/encode_test.go
@@ -22,6 +22,16 @@ import (
 var zero = 0
 var emptyStr = ""
 
+type TestTextMarshaler string
+
+func (t TestTextMarshaler) MarshalText() ([]byte, error) {
+	return []byte(t), nil
+}
+
+type TestTextUnmarshalerContainer struct {
+	V TestTextMarshaler
+}
+
 func TestEncoder(t *testing.T) {
 	tests := []struct {
 		source  string
@@ -731,6 +741,31 @@ func TestEncoder(t *testing.T) {
 			map[string]time.Duration{"v": 30 * time.Second},
 			nil,
 		},
+		{
+			"v: 30s\n",
+			map[string]*time.Duration{"v": ptr(30 * time.Second)},
+			nil,
+		},
+		{
+			"v: null\n",
+			map[string]*time.Duration{"v": nil},
+			nil,
+		},
+		{
+			"v: test\n",
+			TestTextUnmarshalerContainer{V: "test"},
+			nil,
+		},
+		{
+			"v: \"1\"\n",
+			TestTextUnmarshalerContainer{V: "1"},
+			nil,
+		},
+		{
+			"v: \"#\"\n",
+			TestTextUnmarshalerContainer{V: "#"},
+			nil,
+		},
 		// Quote style
 		{
 			`v: '''a''b'` + "\n",
@@ -1655,7 +1690,7 @@ func ExampleMarshal() {
 	// a: Hello speed demon
 	// b: 100
 	//
-	// field: 13
+	// field: "13"
 }
 
 func TestIssue356(t *testing.T) {
@@ -1939,3 +1974,7 @@ a: &anc !mytag
 		})
 	}
 }
+
+func ptr[T any](v T) *T {
+	return &v
+}