all: replace += with strings.Builder
Replace repeated string += string concatenation operations with calls to
Go 1.10's strings.Builder.
Generated by
go fix -stringsbuilder ./...
using
go version go1.26-devel_ad85395442 Wed Dec 17 15:56:48 2025 -0800 linux/amd64
diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go
index a11b2dd..f096f0c 100644
--- a/src/bufio/bufio_test.go
+++ b/src/bufio/bufio_test.go
@@ -92,7 +92,7 @@
// Call ReadString (which ends up calling everything else)
// to accumulate the text of a file.
func readLines(b *Reader) string {
- s := ""
+ var s strings.Builder
for {
s1, err := b.ReadString('\n')
if err == io.EOF {
@@ -101,9 +101,9 @@
if err != nil && err != iotest.ErrTimeout {
panic("GetLines: " + err.Error())
}
- s += s1
+ s.WriteString(s1)
}
- return s
+ return s.String()
}
// Call Read to accumulate the text of a file
@@ -145,13 +145,13 @@
func TestReader(t *testing.T) {
var texts [31]string
str := ""
- all := ""
+ var all strings.Builder
for i := range len(texts) - 1 {
texts[i] = str + "\n"
- all += texts[i]
+ all.WriteString(texts[i])
str += string(rune(i%26 + 'a'))
}
- texts[len(texts)-1] = all
+ texts[len(texts)-1] = all.String()
for h := range len(texts) {
text := texts[h]
diff --git a/src/crypto/x509/pkix/pkix.go b/src/crypto/x509/pkix/pkix.go
index 7cc851b..16e463b 100644
--- a/src/crypto/x509/pkix/pkix.go
+++ b/src/crypto/x509/pkix/pkix.go
@@ -11,6 +11,7 @@
"encoding/hex"
"fmt"
"math/big"
+ "strings"
"time"
)
@@ -38,15 +39,15 @@
// String returns a string representation of the sequence r,
// roughly following the RFC 2253 Distinguished Names syntax.
func (r RDNSequence) String() string {
- s := ""
+ var s strings.Builder
for i := range r {
rdn := r[len(r)-1-i]
if i > 0 {
- s += ","
+ s.WriteString(",")
}
for j, tv := range rdn {
if j > 0 {
- s += "+"
+ s.WriteString("+")
}
oidString := tv.Type.String()
@@ -54,7 +55,7 @@
if !ok {
derBytes, err := asn1.Marshal(tv.Value)
if err == nil {
- s += oidString + "=#" + hex.EncodeToString(derBytes)
+ s.WriteString(oidString + "=#" + hex.EncodeToString(derBytes))
continue // No value escaping necessary.
}
@@ -85,11 +86,11 @@
}
}
- s += typeName + "=" + string(escaped)
+ s.WriteString(typeName + "=" + string(escaped))
}
}
- return s
+ return s.String()
}
type RelativeDistinguishedNameSET []AttributeTypeAndValue
diff --git a/src/debug/dwarf/type.go b/src/debug/dwarf/type.go
index 627d3a1..6327c52 100644
--- a/src/debug/dwarf/type.go
+++ b/src/debug/dwarf/type.go
@@ -8,6 +8,8 @@
package dwarf
+import "strings"
+
import "strconv"
// A Type conventionally represents a pointer to any of the
@@ -291,19 +293,20 @@
}
func (t *EnumType) String() string {
- s := "enum"
+ var s strings.Builder
+ s.WriteString("enum")
if t.EnumName != "" {
- s += " " + t.EnumName
+ s.WriteString(" " + t.EnumName)
}
- s += " {"
+ s.WriteString(" {")
for i, v := range t.Val {
if i > 0 {
- s += "; "
+ s.WriteString("; ")
}
- s += v.Name + "=" + strconv.FormatInt(v.Val, 10)
+ s.WriteString(v.Name + "=" + strconv.FormatInt(v.Val, 10))
}
- s += "}"
- return s
+ s.WriteString("}")
+ return s.String()
}
// A FuncType represents a function type.
@@ -314,18 +317,19 @@
}
func (t *FuncType) String() string {
- s := "func("
+ var s strings.Builder
+ s.WriteString("func(")
for i, t := range t.ParamType {
if i > 0 {
- s += ", "
+ s.WriteString(", ")
}
- s += t.String()
+ s.WriteString(t.String())
}
- s += ")"
+ s.WriteString(")")
if t.ReturnType != nil {
- s += " " + t.ReturnType.String()
+ s.WriteString(" " + t.ReturnType.String())
}
- return s
+ return s.String()
}
// A DotDotDotType represents the variadic ... function parameter.
diff --git a/src/encoding/gob/type.go b/src/encoding/gob/type.go
index a260707..c7918dd 100644
--- a/src/encoding/gob/type.go
+++ b/src/encoding/gob/type.go
@@ -11,6 +11,7 @@
"maps"
"os"
"reflect"
+ "strings"
"sync"
"sync/atomic"
"unicode"
@@ -427,12 +428,13 @@
return s.Name
}
seen[s.Id] = true
- str := s.Name + " = struct { "
+ var str strings.Builder
+ str.WriteString(s.Name + " = struct { ")
for _, f := range s.Field {
- str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen))
+ str.WriteString(fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)))
}
- str += "}"
- return str
+ str.WriteString("}")
+ return str.String()
}
func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) }
diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go
index d3138fe..b8db68f 100644
--- a/src/fmt/fmt_test.go
+++ b/src/fmt/fmt_test.go
@@ -1175,14 +1175,15 @@
pattern = "PTR"
chars = "0123456789abcdefABCDEF"
}
- p := s[:i] + pattern
+ var p strings.Builder
+ p.WriteString(s[:i] + pattern)
for j := i; j < len(s); j++ {
if !strings.ContainsRune(chars, rune(s[j])) {
- p += s[j:]
+ p.WriteString(s[j:])
break
}
}
- s = p
+ s = p.String()
}
if s != tt.out {
if _, ok := tt.val.(string); ok {
@@ -1537,20 +1538,21 @@
type flagPrinter struct{}
func (flagPrinter) Format(f State, c rune) {
- s := "%"
+ var s strings.Builder
+ s.WriteString("%")
for i := range 128 {
if f.Flag(i) {
- s += string(rune(i))
+ s.WriteString(string(rune(i)))
}
}
if w, ok := f.Width(); ok {
- s += Sprintf("%d", w)
+ s.WriteString(Sprintf("%d", w))
}
if p, ok := f.Precision(); ok {
- s += Sprintf(".%d", p)
+ s.WriteString(Sprintf(".%d", p))
}
- s += string(c)
- io.WriteString(f, "["+s+"]")
+ s.WriteString(string(c))
+ io.WriteString(f, "["+s.String()+"]")
}
var flagtests = []struct {
diff --git a/src/go/types/decl.go b/src/go/types/decl.go
index 80b8c20..9aa86fc 100644
--- a/src/go/types/decl.go
+++ b/src/go/types/decl.go
@@ -11,6 +11,7 @@
"go/token"
. "internal/types/errors"
"slices"
+ "strings"
)
func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token.Pos) {
@@ -35,14 +36,14 @@
// pathString returns a string of the form a->b-> ... ->g for a path [a, b, ... g].
func pathString(path []Object) string {
- var s string
+ var s strings.Builder
for i, p := range path {
if i > 0 {
- s += "->"
+ s.WriteString("->")
}
- s += p.Name()
+ s.WriteString(p.Name())
}
- return s
+ return s.String()
}
// objDecl type-checks the declaration of obj in its respective (file) environment.
diff --git a/src/internal/coverage/pods/pods_test.go b/src/internal/coverage/pods/pods_test.go
index eed0169..ec82431 100644
--- a/src/internal/coverage/pods/pods_test.go
+++ b/src/internal/coverage/pods/pods_test.go
@@ -12,6 +12,7 @@
"os"
"path/filepath"
"runtime"
+ "strings"
"testing"
)
@@ -58,15 +59,16 @@
}
podToString := func(p pods.Pod) string {
- rv := trim(p.MetaFile) + " [\n"
+ var rv strings.Builder
+ rv.WriteString(trim(p.MetaFile) + " [\n")
for k, df := range p.CounterDataFiles {
- rv += trim(df)
+ rv.WriteString(trim(df))
if p.Origins != nil {
- rv += fmt.Sprintf(" o:%d", p.Origins[k])
+ rv.WriteString(fmt.Sprintf(" o:%d", p.Origins[k]))
}
- rv += "\n"
+ rv.WriteString("\n")
}
- return rv + "]"
+ return rv.String() + "]"
}
// Create a couple of directories.
diff --git a/src/log/syslog/syslog_test.go b/src/log/syslog/syslog_test.go
index 5b163cb..1f48432b 100644
--- a/src/log/syslog/syslog_test.go
+++ b/src/log/syslog/syslog_test.go
@@ -14,6 +14,7 @@
"os"
"path/filepath"
"runtime"
+ "strings"
"sync"
"testing"
"time"
@@ -21,7 +22,7 @@
func runPktSyslog(c net.PacketConn, done chan<- string) {
var buf [4096]byte
- var rcvd string
+ var rcvd strings.Builder
ct := 0
for {
var n int
@@ -29,7 +30,7 @@
c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
n, _, err = c.ReadFrom(buf[:])
- rcvd += string(buf[:n])
+ rcvd.WriteString(string(buf[:n]))
if err != nil {
if oe, ok := err.(*net.OpError); ok {
if ct < 3 && oe.Temporary() {
@@ -41,7 +42,7 @@
}
}
c.Close()
- done <- rcvd
+ done <- rcvd.String()
}
var crashy = false
diff --git a/src/math/big/hilbert_test.go b/src/math/big/hilbert_test.go
index 30977dc..e4bb252 100644
--- a/src/math/big/hilbert_test.go
+++ b/src/math/big/hilbert_test.go
@@ -10,6 +10,7 @@
import (
"fmt"
+ "strings"
"testing"
)
@@ -123,14 +124,14 @@
}
func (a *matrix) String() string {
- s := ""
+ var s strings.Builder
for i := 0; i < a.n; i++ {
for j := 0; j < a.m; j++ {
- s += fmt.Sprintf("\t%s", a.at(i, j))
+ s.WriteString(fmt.Sprintf("\t%s", a.at(i, j)))
}
- s += "\n"
+ s.WriteString("\n")
}
- return s
+ return s.String()
}
func doHilbert(t *testing.T, n int) {
diff --git a/src/net/dnsconfig_unix_test.go b/src/net/dnsconfig_unix_test.go
index c750771..54e235b 100644
--- a/src/net/dnsconfig_unix_test.go
+++ b/src/net/dnsconfig_unix_test.go
@@ -262,11 +262,11 @@
defer func() { getHostname = origGetHostname }()
getHostname = func() (string, error) { return "host.domain.local", nil }
- var char63 = ""
+ var char63 strings.Builder
for range 63 {
- char63 += "a"
+ char63.WriteString("a")
}
- longDomain := strings.Repeat(char63+".", 5) + "example"
+ longDomain := strings.Repeat(char63.String()+".", 5) + "example"
for _, tt := range dnsReadConfigTests {
conf := dnsReadConfig(tt.name)
diff --git a/src/net/mail/message.go b/src/net/mail/message.go
index 1502b35..72023da 100644
--- a/src/net/mail/message.go
+++ b/src/net/mail/message.go
@@ -832,7 +832,7 @@
// '(' already consumed.
depth := 1
- var comment string
+ var comment strings.Builder
for {
if p.empty() || depth == 0 {
break
@@ -846,12 +846,12 @@
depth--
}
if depth > 0 {
- comment += p.s[:1]
+ comment.WriteString(p.s[:1])
}
p.s = p.s[1:]
}
- return comment, depth == 0
+ return comment.String(), depth == 0
}
func (p *addrParser) decodeRFC2047Word(s string) (word string, isEncoded bool, err error) {
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index fb8f42b..aa39745 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -3285,11 +3285,12 @@
// Failed
t.Errorf("want NumIn() = 2, In(0) = int, In(1) = []float64")
- s := fmt.Sprintf("have NumIn() = %d", typ.NumIn())
+ var s strings.Builder
+ s.WriteString(fmt.Sprintf("have NumIn() = %d", typ.NumIn()))
for i := 0; i < typ.NumIn(); i++ {
- s += fmt.Sprintf(", In(%d) = %s", i, typ.In(i))
+ s.WriteString(fmt.Sprintf(", In(%d) = %s", i, typ.In(i)))
}
- t.Error(s)
+ t.Error(s.String())
}
type inner struct {
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index c41c18a..105e0fd 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -1637,13 +1637,14 @@
return
}
if len(locations) < 4 || len(locations) > 5 {
- message := fmt.Sprintf("leaked goroutine stack expected 4 or 5 locations but found %d", len(locations))
+ var message strings.Builder
+ message.WriteString(fmt.Sprintf("leaked goroutine stack expected 4 or 5 locations but found %d", len(locations)))
for _, location := range locations {
for _, line := range location.Line {
- message += fmt.Sprintf("\n%s:%d", line.Function.Name, line.Line)
+ message.WriteString(fmt.Sprintf("\n%s:%d", line.Function.Name, line.Line))
}
}
- t.Errorf("%s", message)
+ t.Errorf("%s", message.String())
return
}
// We expect a receive operation. This is the typical stack.
diff --git a/src/time/format_test.go b/src/time/format_test.go
index 2537c76..ff57a6f 100644
--- a/src/time/format_test.go
+++ b/src/time/format_test.go
@@ -38,16 +38,16 @@
// Note that NextStdChunk and StdChunkNames
// are not part of time's public API.
// They are exported in export_test for this test.
- out := ""
+ var out strings.Builder
for s := format; s != ""; {
prefix, std, suffix := NextStdChunk(s)
- out += prefix
+ out.WriteString(prefix)
if std > 0 {
- out += "(" + StdChunkNames[std] + ")"
+ out.WriteString("(" + StdChunkNames[std] + ")")
}
s = suffix
}
- return out
+ return out.String()
}
noParens := func(r rune) rune {
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Please do a manual post processing. If you make these changes you might as well make the code simpler.
str.WriteString(fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)))simpler: fmt.Fprintf(&str, "%s %s; ", f.Name, f.Id.gobType().safeString(seen))
s.WriteString(string(rune(i)))s.WriteRune ?
s.WriteString(Sprintf("%d", w))fmt.Fprintf(&s, "%d", w)
rv.WriteString(fmt.Sprintf(" o:%d", p.Origins[k]))fmt.Fprintf(&rv, " o:%d", p.Origins[k]))
rcvd.WriteString(string(buf[:n]))WriteByte?
s.WriteString(fmt.Sprintf("\t%s", a.at(i, j))) s.WriteString(fmt.Sprintf("have NumIn() = %d", typ.NumIn()))use fmt.Fprintf(%s, ...
message.WriteString(fmt.Sprintf("leaked goroutine stack expected 4 or 5 locations but found %d", len(locations)))use fmt.Fprintf
message.WriteString(fmt.Sprintf("\n%s:%d", line.Function.Name, line.Line))ditto
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Commit-Queue | +1 |
Please do a manual post processing. If you make these changes you might as well make the code simpler.
done
str.WriteString(fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)))simpler: fmt.Fprintf(&str, "%s %s; ", f.Name, f.Id.gobType().safeString(seen))
Done
s.WriteString(string(rune(i)))Kirill Kolyshkins.WriteRune ?
Done
s.WriteString(Sprintf("%d", w))Kirill Kolyshkinfmt.Fprintf(&s, "%d", w)
Done
fmt.Fprintf(&rv, " o:%d", p.Origins[k]))
Done
rcvd.WriteString(string(buf[:n]))Kirill KolyshkinWriteByte?
Done
fmt.Fprintf(&s, "\t%s", a.at(i, j))
Done
for range 63 {Kirill Kolyshkinuse strings.Repeat
Done
s.WriteString(fmt.Sprintf("have NumIn() = %d", typ.NumIn()))Kirill Kolyshkinuse fmt.Fprintf(%s, ...
Done
message.WriteString(fmt.Sprintf("leaked goroutine stack expected 4 or 5 locations but found %d", len(locations)))Kirill Kolyshkinuse fmt.Fprintf
Done
message.WriteString(fmt.Sprintf("\n%s:%d", line.Function.Name, line.Line))Kirill Kolyshkinditto
Done
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
with some manual changes on top.Thanks. It might be better to split this into two CLs: one that is autogenerated with go fix, and then a follow-up with the manual changes. This makes it easier to review and also helps if there's an issue down the road.
Just re-apply the go fix changes on a clean baseline and then cherry-pick this CL on top. The git merge should do the rest.
s.WriteString(",")use WriteRune, or even WriteByte
s.WriteString("+")ditto
return rv.String() + "]"rv.WriteRune(']')
return rv.String()
After all, you make these changes to avoid allocations and for speed. So why stop halfway.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |