gopls version

Build info

golang.org/x/tools/gopls v0.19.1 golang.org/x/tools/gopls@v0.19.1 h1:Yodhp3rnpnag60lVZrYPYbGMxTlTCIAj/B2Rv7AKuhA= github.com/BurntSushi/toml@v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/fatih/camelcase@v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/gomodifytags@v1.17.1-0.20250423142747-f3939df9aa3c h1:dDSgAjoOMp8da3egfz0t2S+t8RGOpEmEXZubcGuc0Bg= github.com/fatih/structtag@v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/google/go-cmp@v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= golang.org/x/exp/typeparams@v0.0.0-20250218142911-aa4b98e5adaa h1:Br3+0EZZohShrmVVc85znGpxw7Ca8hsUJlrdT/JQGw8= golang.org/x/mod@v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= golang.org/x/sync@v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= golang.org/x/telemetry@v0.0.0-20250417124945-06ef541f3fa3 h1:RXY2+rSHXvxO2Y+gKrPjYVaEoGOqh3VEXFhnWAt1Irg= golang.org/x/text@v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/tools@v0.34.1-0.20250610205101-c26dd3ba555e h1:XnjOegqwH6kBJoae6InSGbIFPHcLtUT/Eq8HjrZKbmQ= golang.org/x/vuln@v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I= honnef.co/go/tools@v0.7.0-0.dev.0.20250523013057-bbc2f4dd71ea h1:fj8r9irJSpolAGUdZBxJIRY3lLc4jH2Dt4lwnWyWwpw= mvdan.cc/gofumpt@v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= mvdan.cc/xurls/v2@v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI= go: go1.24.3

go env

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/oakad/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/oakad/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build466808813=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/oakad/go/pkg/mod'
GOOS='linux'
GOPATH='/home/oakad/go'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/oakad/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.3'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

S1030 warning is misleading and either should not be there or Buffer.String() needs to be altered (though, the later is unlikely, so first option).

The Buffer.String method is implemented as following:

func (b *Buffer) String() string {
    if b == nil {
        // Special case, useful in debugging.
        return "<nil>"
    }
    return string(b.buf[b.off:])
}

However, in vast majority of practical applications of buffer content being converted to string (usually as a result of some encoding operation that took place) the user never expects to see the ostensibly helpful string "<nil>". If the buffer is empty, the expectation is always "", empty string.

A typical program logic usually goes as "some data in" -> "nothing was encoded for whatever reason" -> "outcome is empty string for which there's a check".

Also, compare with strings.Builder.String().

What did you see happen?

S1030 warning is raised when I use string(b.Bytes()).

What did you expect to see?

Don't expect to see S1030 warning. :-)

Editor and settings

No response

Logs

No response

Comment From: gabyhelp

Related Issues

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: dominikh

(*bytes.Buffer).String returns "<nil>" when the Buffer is nil, not when it is empty. And in that case, (*bytes.Buffer).Bytes would panic.

Comment From: adonovan

As @dominikh said, the only time b.String() differs from string(b.Bytes()) is when the latter would panic, which indicates a mistake in your program. So I think you may be misinterpreting what the condition b==nil actually means.

Someone might argue that it's better to learn about the mistake from a panic than to cover it up and proceed with a bad string value, and that might be an argument for a more detailed diagnostic message, but I don't see how this fix breaks a working program.

Closing this issue. Please re-open if you disagree with my logic.