diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index c4782031a4..f7fca07301 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -138,12 +138,32 @@ func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args) } +var errnoErrorCache sync.Map + func (e Errno) Error() string { // deal with special go errors idx := int(e - APPLICATION_ERROR) if 0 <= idx && idx < len(errors) { return errors[idx] } + + cache := false + switch e { + case ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND: + if cached, ok := errnoErrorCache.Load(e); ok { + return cached.(string) + } + cache = true + } + + result := e.error() + if cache { + errnoErrorCache.Store(e, result) + } + return result +} + +func (e Errno) error() string { // ask windows for the remaining errors var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS b := make([]uint16, 300) diff --git a/src/syscall/syscall_windows_test.go b/src/syscall/syscall_windows_test.go index 882a279692..5e6ba9dbed 100644 --- a/src/syscall/syscall_windows_test.go +++ b/src/syscall/syscall_windows_test.go @@ -299,3 +299,10 @@ func FuzzUTF16FromString(f *testing.F) { } }) } + +func BenchmarkErrnoString(b *testing.B) { + b.ReportAllocs() + for b.Loop() { + _ = syscall.Errno(2).Error() + } +}