Go version
go1.25.6
Output of go env in your module/workspace:
AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/dgl/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/dgl/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3561637139=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='openbsd'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/home/dgl/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='openbsd'
GOPATH='/home/dgl/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/dgl/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/usr/local/go/pkg/tool/openbsd_amd64'
GOVCS=''
GOVERSION='go1.25.6'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
In RFC 6761 section 6.3 "localhost" and names falling within ".localhost"
https://datatracker.ietf.org/doc/html/rfc6761#section-6.3 it says in part 3:
3. Name resolution APIs and libraries SHOULD recognize localhost
names as special and SHOULD always return the IP loopback address
for address queries and negative responses for all other query
types. Name resolution APIs SHOULD NOT send queries for
localhost names to their configured caching DNS server(s).
The macOS and OpenBSD resolvers do this by default, various other platforms vary in their exact implementation.
This can be demonstrated fairly easily:
package main
import (
"log"
"net"
)
func main() {
log.Print(net.LookupHost("foo.localhost"))
}
What did you see happen?
$ GODEBUG=netdns=go+1 ./dnstest
go package net: GODEBUG setting forcing use of the Go resolver
2026/04/01 12:09:14 [] lookup foo.localhost on 8.8.8.8:53: no such host
$ GODEBUG=netdns=cgo+1 ./dnstest
go package net: GODEBUG setting forcing use of the cgo resolver
2026/04/01 12:09:45 [127.0.0.1 ::1] <nil>
What did you expect to see?
Always resolve foo.localhost. Note that 8.8.8.8 does not resolve foo.localhost but for example 9.9.9.9 does, so there are two workarounds for this, either force the cgo resolver as above, or use quad9 or another recursive resolver which does implement the other parts of RFC 6761:
$ grep '^nameserver' /etc/resolv.conf
nameserver 9.9.9.9
$ GODEBUG=netdns=go+1 ./dnstest
go package net: GODEBUG setting forcing use of the Go resolver
2026/04/01 12:10:49 [::1 127.0.0.1] <nil>
I would also expect that this resolution happens internally to the Go dns resolver code, so that a query for localhost or foo.localhost is never seen on the wire (localhost may be covered by the usual /etc/hosts entry, but subdomains are not).
Go version
go1.25.6
Output of
go envin your module/workspace:What did you do?
In RFC 6761 section 6.3 "localhost" and names falling within ".localhost"
https://datatracker.ietf.org/doc/html/rfc6761#section-6.3 it says in part 3:
The macOS and OpenBSD resolvers do this by default, various other platforms vary in their exact implementation.
This can be demonstrated fairly easily:
What did you see happen?
What did you expect to see?
Always resolve
foo.localhost. Note that8.8.8.8does not resolvefoo.localhostbut for example9.9.9.9does, so there are two workarounds for this, either force the cgo resolver as above, or use quad9 or another recursive resolver which does implement the other parts of RFC 6761:I would also expect that this resolution happens internally to the Go dns resolver code, so that a query for
localhostorfoo.localhostis never seen on the wire (localhostmay be covered by the usual/etc/hostsentry, but subdomains are not).