My issues with Go's net package
I would like to like the Go language, but right now I can't get past my annoyance at its net package. I have several network-related things that I would like to do with Go, and the net package's current state is getting in the way of all of them.
The fundamental problem is that Go's net package is both incomplete and what I'll call sealed. The easiest way for me to explain this is to contrast it with Python's socket support.
Both Go and Python represent network connections with language-level objects that have an abstract interface; underlying both of them are OS level file descriptors. Go and Python both have operations to create new network connections and so on, which return their high-level objects. The difference between Go and Python is that in Python you can both get at the OS level file descriptor behind a network connection and create a new network connection object from an OS level file descriptor, and in Go you cannot.
There are two limitations this imposes. First, you cannot create network connections from file descriptors that you obtain or inherit and in turn this means that you cannot write an inetd-started network daemon in Go (at least not without reimplementing a chunk of the net package yourself). As it happens, some version of this is one of the things that I would like to do in Go.
Second, this means that you can't do things that need the file
descriptor itself. On the one hand this is sort of fair (the network
connection object doesn't want the state of the socket changed behind
its back), but on the other hand this is where the incompleteness of the
net package comes in, because it doesn't have anywhere near all of the
functionality that you'd want. The instance that is directly annoying
me right now is that the net package does not implement shutdown()
on network connection objects, which I need for one of my standard
learning exercises.
One of the reasons that this makes me somewhat unhappy with Go the
language is that it argues for two things at once: that Go is an
opinionated language environment and that the opinions of its creators
are not mine. For example, one of the things that you can't do without
access to the file descriptors is write a multiple connection select()
or poll()
based server. But I suspect that if you raised this argument
with the Go people, they would tell you that you should use goroutines
and channels to implement this.
(I am far from convinced that goroutines and channels are the right
answer for some of the things you can do easily in a poll()
based
system, but that's another entry.)
PS: I am deliberately simplifying the Go situation when I talk about 'network connection objects'. What you deal with is actually a Go interface that is implemented by a number of different concrete types, one for each of the different major network connection types (like 'tcp' and 'udp').
|
|