Google just released a new programming language, called Go. It’s exciting, different, and intended as a concurrent systems language. It’s also fairly controversial, because it changes a lot of little things, and a lot of big things that developers do and think about. It’s making some people very happy, and some people very unhappy.
I decided that it was a good time to play and try to write a module, so I looked in the initial library release, and I saw that the random number generator package, rand could only support pseudo random numbers, using a standard seeded random number generator. I thought to myself that it would be nice to be able to use one of the secure random sources, e.g., /dev/random
on most unices, to provide a source of randomness. So began a cute little project …
The rand package is broken up a little, into 2 distinct types. One, is a struct called Rand that implements many of the convenience methods to retrieve random numbers that conform in some way to a range, like 0-6. The other is an interface that is intended to yield random numbers, called a Source
. Source is an interface in the Go tradition, which analogous to interfaces or full abstract classes in Java and C++, for instance. I decided to override this Source interface as an exercise; I’ve put the results up online on my github repository for everyone to follow along on. It’s a quick write-up, more as a learning exercise than anything else, so here I went.
First things first, I realised I just wanted to back my Source with a user specified file – usually something like /dev/random
. I created a new interface that added one method to the Source, namely a Close method, to allow the file to be closed.
type FileBasedSource interface {
rand.Source;
Close();
}
Wow, that was easy. I just declared an included Interface, and a zero argument method. Thats it. I extended an interface this easily.
Then, what I really love, is the use of Duck typing. I just wrote a couple of methods that basically create a private struct, and return the FileBasedSource interface defined above. Pretty easy. I had to fiddle with the sys calls to open the file descriptors, and then one more fiddly part to convert an 8byte into an int64, which can almost certainly be improved. What I do is, byte by byte, convert to a uint64, and shift its bits. I’m not sure that there’s a better way, but, I leave it as a TODO.
Then, a quick test, and a second function in the package, to allow for a /dev/urandom
style of implementation. Using defer was very natural, and it felt right to place an opener, and its relevant closing functionality right next to each other. After all that, a little bit of a main to test that randomness was doing its right thing, and here it is, whacked into git. Take a look at the code, compiling is straightforward and very fast, as expected.
So what was the experience like? Easy. Fun. I had no trouble hooking together the bits that I wanted to, and testing was a breeze too. Duck typing was a breath of fresh air, and in this case at least, the interface and struct system felt very comfortable to use. Extending an interface was natural; The syntax was comfortable, even though some complain about the reversed order, I found that it made no difference to the way I read code.
Whats next? something more meaty. Or maybe, if people think this package is useful, I’ll clean it up. Your feedback is very appreciated, so please, get back to me. Frankly though, I haven’t verified any security properties here, just had fun overriding one interface. A read of the rand package in full would be good in that case.