From 26fc4aa956783268d7a289240a028774e1ea3878 Mon Sep 17 00:00:00 2001 From: Jes Cok Date: Tue, 6 Jun 2023 23:25:42 +0000 Subject: [PATCH] errors: optimize *joinError's Error method for less allocation and faster execution Handle the case of one error at the beginning. Use unsafe.String to avoid memory allocation when converting byte slice to string. Change-Id: Ib23576f72b1d87489e6f17762be483f62ca4998a GitHub-Last-Rev: ed8003bfbcae8efd42e54895db0554c139b9d3a7 GitHub-Pull-Request: golang/go#60026 Reviewed-on: https://go-review.googlesource.com/c/go/+/493237 Reviewed-by: Damien Neil TryBot-Result: Gopher Robot Reviewed-by: David Chase Run-TryBot: Ian Lance Taylor --- src/errors/join.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/errors/join.go b/src/errors/join.go index 1c486d591e..349fc06ed9 100644 --- a/src/errors/join.go +++ b/src/errors/join.go @@ -4,6 +4,10 @@ package errors +import ( + "unsafe" +) + // Join returns an error that wraps the given errors. // Any nil error values are discarded. // Join returns nil if every value in errs is nil. @@ -38,14 +42,19 @@ type joinError struct { } func (e *joinError) Error() string { - var b []byte - for i, err := range e.errs { - if i > 0 { - b = append(b, '\n') - } + // Since Join returns nil if every value in errs is nil, + // e.errs cannot be empty. + if len(e.errs) == 1 { + return e.errs[0].Error() + } + + b := []byte(e.errs[0].Error()) + for _, err := range e.errs[1:] { + b = append(b, '\n') b = append(b, err.Error()...) } - return string(b) + // At this point, b has at least one byte '\n'. + return unsafe.String(&b[0], len(b)) } func (e *joinError) Unwrap() []error { -- 2.48.1