== Some things that force Go to call the C library for name resolution on Linux Traditionally on Unix systems there is no official standard for how to do various sorts of network name lookups, or rather the official standard is 'call the functions in the system C library'. There is generally no actual specification for how name lookup works at the level that would permit you to create an independent implementation (although there is generally documentation on how to configure it). This presents a problem for people who are creating non-C languages; they must either arrange to call the C library (through the C library's limited interfaces for this) or write their own versions that may not resolve things exactly like the C library does, so that you get inconsistent behavior between C programs and programs written in the other language. Go kind of takes both approaches. As covered in [[the net package's documentation https://golang.org/pkg/net/]], Go can both call the C library routines (using cgo) and do its own name lookups in pure Go. Go normally tries to use the pure Go approach as much as possible because it's considered better (partly because [[cgo calls can be relatively expensive http://www.cockroachlabs.com/blog/the-cost-and-complexity-of-cgo/]]). In theory the pure Go approach should give you the same results as the cgo approach; in practice, the two can behave somewhat differently in some situations, [[sometimes because of oversights https://github.com/golang/go/issues/13610]]. (Although the net package's documentation talks only about DNS related lookups, this also affects how at least _net.LookupPort()_ works.) Go normally attempts to be pretty hyper-intelligent about whether or not it can use its pure Go lookup functions. It makes this decision in part by reading through your _/etc/resolv.conf_ and _/etc/nsswitch.conf_ to see if you're using anything that it doesn't think it can handle. This raises the question of what things in either of these files can accidentally force Go to use cgo calls to the C library, instead of its own more efficient (and more consistent across systems) pure Go version. For _/etc/resolv.conf_, Go understands all of the common things but anything else will force it to cgo, including any mistakes you may have lurking in there. For _/etc/nsswitch.conf_, Go looks at the '_hosts_' line and a few complications can be common on modern Linuxes: * if your _hosts_ includes [[_myhostname_ http://www.freedesktop.org/software/systemd/man/nss-myhostname.html]], only lookups of names with dots in them can be done in pure Go. Because of an implementation quirk, this currently means that _net.LookupPort()_ is forced to use the C library. (Some other things are also forced to use the C library, but arguably they should in this situation because they involve hostnames.) * if your _hosts_ includes [[_mymachines_ http://www.freedesktop.org/software/systemd/man/nss-mymachines.html]], all lookups go to the C library. This is probably common on modern systemd-based Linux distributions. If you're using Go programs and you don't use containers or don't need the magic functionality of [[_mymachines_]], you may want to strip it out of your _nsswitch.conf_. If you're like me, you may even be surprised to find it there in the first place. You may not want _myhostname_ either, especially if your host has IP aliases that are most definitely not included in what a name to IP lookup for its hostname should return. Note that contrary to what you might think, _net.LookupPort()_ (and things that call it to get ports, like _net.ResolveTCPAddr()_) does not look at the _services_ line in _/etc/nsswitch.conf_, only the _hosts_ line. And of course the pure Go port lookup only looks at _/etc/services_ (and may not parse it exactly like the C library does). At the moment a missing or unreadable _/etc/services_ seems not to force a fallback to the C library but instead uses a tiny built in default version. (This probably doesn't affect anyone. I can't imagine that there are very many people who use NIS or otherwise do something funny for _services_ lookups and not _hosts_ lookups.) You can see what sort of lookup is used for specific queries by setting the _GODEBUG_ environment variable to a verbosity of 2 or more, ie '_GODEBUG=netdns=2_'. The resulting report may look something like this: .pn prewrap on > go package net: dynamic selection of DNS resolver > go package net: hostLookupOrder() = cgo > go package net: hostLookupOrder(smtp.cs) = files,dns This is on a Linux machine where I set _hosts_ to include _myhostname_ but not _mymachines_. The first _hostLookupOrder()_ is for looking up the port number for _smtp_; here the presence of _myhostname_ forced it to resort to cgo. A blank argument to _hostLookupOrder()_ is used by several sorts of lookups, including _net.LookupAddr()_ and _net.LookupCNAME()_. (This is of course an implementation detail and may change at some point.)