In the last few months, from time to time I experimented with the programming language Go, a new systems language released only in 2009 and developed by people like Ken Thompson, Rob Pike and Russ Cox at Google. While still staying relatively low-level, it adds a garbage collector, and simple object/interface system, and the mechanisms of goroutines and channels as means of concurrency and inter-process communication (or should I say inter-goroutine communication).
In the last few days, I found more time to experiment with Go, and finally fully got the hang of the object system, and I must say that I really like it, both for the simplicity and the expressiveness. Objects in Go feel so simple, so natural, and at the same time powerful, with very little syntactic overhead. So that's what I want to write about today.
Let's start with a simple example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Here we created a new type Vehicle with one private member "speed", and a method Speed() that returns the current speed. Of course, a vehicle all by its own isn't very useful, so we define the minimal requirements for a vehicle that's actually usable:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Here we define an interface named Drivable that defines the required methods for an object to be drivable, in our case, it must be able to accelerate, brake and show the current speed. Based on this, we construct our first actually usable vehicle:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
And voila, we have our first Car that is also Drivable. What did we exactly do here?
We created a new type Car that is a struct, and embedded the type Vehicle: instead of adding a named member, we added an unnamed member, only specified by the type. This embedding also makes all available methods for this type available to our new type, i.e. a method Speed() is now also available for our type Car.
In addition, we implemented two new methods, Accelerate() and Brake(), in order to match the interface Drivable. And last but not least, we implemented a function to create a new Car.
Now, let's create another type of Drivable vehicle, let's say a boat:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
So far, so uninteresting. The implementation of the boat is basically the same as the car, so nothing new.
But now I want to go a step further and implement and amphibious vehicle that is both a car and a boat. Let's just do that:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
But that doesn't quite work out, because when we try to compile it, we will see an error message like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Since we embedded both Car and Boat into Amphibian, the compiler can't decide which Accelerate() method it shall use, thus communicating it as ambiguous. Based on that, it also says that it can't create an object of type Amphibian as Drivable because it has no proper Accelerate() function. This is the classic problem of diamond inheritance that we need to resolve here, not only for Accelerate(), but also for Brake() and Speed(). In the case of the amphibious vehicle, we do this by returning the right speed depending on whether the vehicle is in the water or on land:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
And of course, the object perfectly works as Drivable:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
So, what I just showed you are the capabilities in what Go modestly calls embedding but that feels like multiple inheritance and is really simple at the same time.
For a more complete view on Go and its features, I recommend the official Go documentation, and especially "Effective Go", a document that introduces the most important Go features and shows how to write idiomatic Go code. The complete example source code can be found here.
Nachdem gestern Google Chrome veröffentlicht worden war, beschloss ich heute früh, diesen neuen Browser zu installieren und etwas auszuprobieren. Eine der ersten Tasks war, Google Chrome mit dem SilkPerformer zu recorden. Also fügte ich Google Chrome als aufzunehmende Applikation hinzu, und startete den Recorder. Der Recorder startete wiederum Google Chrome. Ich fing an, eine URL in die Adressleiste einzutippen, und als ich gerade einmal ein paar Zeichen eingetippt hatte, sah ich plötzlich zu meinem Erstaunen, dass der SilkPerformer Recorder schon 8 Requests aufgenommen hatte. Sofort brach ich das Tippen ab (ich habe zu keinem Zeitpunkt die Return-Taste betätigt, d.h. keinen Requests abgesetzt), und ließ mir vom Recorder ein SilkPerformer-Skript generieren.
Das Ergebnis war folgendes BDL-Skript wie dieses (nachgestellt mit "derstandard.at"):
Wie an diesem Skript gut zu erkennen ist, hat Google Chrome in der kurzen Zeit, in der ich "derstandard.at" in die Adressleiste eingetippt hatte, ohne jedoch einen tatsächlichen Request abzusetzen, 8 Requests an http://clients1.google.at/complete/search verschickt, jeweils mit dem aktuellen Inhalt meiner Adressleiste.
Meiner Meinung nach ist dieses Verhalten aus Privacy-Sicht äußerst kritisch zu beurteilen: Google Chrome zeigt bei Eingaben in der Adressleiste ein Verhalten ähnlich dem eines Keyloggers. Selbst Tippfehler, Korrekturen oder versehentlich eingegebene Daten (wem ist es nicht schon einmal passiert, z.B. Passwörter in einem falschen Eingabefeld eingegeben zu haben?) landen bei Google, und das noch dazu über eine unverschlüsselte Verbindung. Bisher hat Google ja schon etliche Daten über ihre User gesammelt, in Form von Sucheingaben. Dass nun aber auch einfach alles, was in ein bestimmtes Eingabefeld eingetippt wird, ohne dass der User explizit einen Request absetzen will, das ist schon eine neue Qualität. Selbst wenn es dafür eine Konfigurationsoption geben sollte, dieses Verhalten abzuschalten: das Default ist, dass jede Menge Daten über das, was ich in meine Adressliste eintippe, an Google gehen. Selbst annähernd genaue Timingdaten über das Tippverhalten könnten daraus gewonnen werden, und wie schon seit 2005 bekannt ist, kann diese Information verwendet werden, um Personen an ihrem Tipp-Timing zu identifizieren.
Ich hab mir grad den Spaß gemacht, mit Google Translate das zu übersetzen, was Borland Japan über den SilkPerformer 2007 schreibt. Google Translate hat anscheinend die Eigenschaft, Wörter, die es nicht kennt, in ihrer Transkription in lateinischen Großbuchstaben auszugeben. Im Inhalt der verlinkten Seite war das besonders interessant, da offenbar einige englische Begriffe bzw. Eigennamen in japanischen Schriftzeichen niedergeschrieben wurde. Eine Auswahl der Wörter, die ich so gefunden habe, und meine, die Bedeutung erkannt zu haben:
Das geht mit der neuen Version von Google Earth, das einen Flugsimulator enthält. Das Flugmodell ist zwar sehr stark vereinfacht, das Fliegen durch z.B. den Himalaye macht aber trotzdem ziemlich viel Spaß (mit Maus, mangels Joystick, BTW, deswegen wirken manche Manöver evtl. etwas skurril):