Composite with Go

 

Today I’d like to talk about design patterns, and one of them in particular. As announced in a preview post, Go language introduction, I will implement Composite in Go, the new programming language from google. Introduced by Erich GammaRichard HelmRalph JohnsonJohn M. Vlissides in their software designer bible: Design Patterns: Elements of Reusable Object-Oriented Software. I will implement one of these pattern in Go language, to exploring new features of this language and how they allow to use high level paradigm using a low level language.

Design patterns are a useful way to manage tipical problems emerging during develpment process. As said, I want to pay special attention to one of these patterns: Composite. It is not easy to explain whatg Composite is, so go on with a case study: imagine a system that send and receive packets in some stream. During the design process, we identify two important entity: Packet and Message. Messages are composed by Packet, each Packet has some data, and so on. But there is a special requirement: to meet the needs of the underlayng layers, the system should be able to group many Message objects to create other, bigger Messages. To make a long story short, sometimes Messages (group of Packets) act like single Packet, to be group again and so on. Hope it is clear.

Using Composite, we don’t need to consider Packets and Messages as different things: both of them should implement the same interface, PacketComposite, to define a Message as a collection of PacketComposite. So Messages and Packets will both implements the 2 needed methods: print() and addChild(). The first one will print the data if called from a Packet, the entire collection if called from Message. That’s what we call polymorfism in OO. The addChild() method will have an empty implementation for Packet, since we don’t need to add Packets to Packets. So, let’s take a look to the data structures needed:

package main

import "fmt"

type PacketComposite interface {

	print()
	addChild(p PacketComposite, i int)
}

type Packet struct {
	value		int
}

type Message struct {
	chain	[3]PacketComposite
	dim	int
	label	int
}

Ok, we declared what we need, fmt is a Go package that I will use to printf messages. Message contains a collection of PacketComposite, but we need a Packet/Message collection in it. There are no explicit relationships among these classes yet, so at this point we need to declare Packet and Message to be implementation of PacketComposite. Here the good news: in google’s go, it can’t be easy.

We just need to implement the methods print() and addChild() for Packet and Message, and they will automatically considered as PacketComposite implementation. That’s it, these classes are not declared to be an implementation of the interface, but they become that if we implement both the methods required by the interface. Let’s do it:

func (p Packet) print() {

	var n int
	n = p.value
	fmt.Printf("packet value: %d\n", n)
}

func (pa Packet) addChild(p PacketComposite, i int) {
	fmt.Printf("Nothing to add")
}

func (m *Message) print() {
	var i int

	fmt.Printf("\nMessage%d\n", m.label)

	if m.dim == 0 {
		return
	}

	for i=0; i

As announced, we leave the addChild() method empty for Packet. The implementation for Message is not the best I can do, you have to pass an integer to use as index for the array that implement the collection, of course we can do better, but keep concentrated on the topic: implement Composite in Go. At this point, we have all we need to speack about Composite. We can also define other methods for Packet and Message:

func (p Packet) set(i int) {
	p.value = i
}

// Equivalent to constructor
func newMessage(i int) *Message {
	return &Message{dim: 0, label: i}
}

func newPacket(i int) *Packet {
	return &Packet{value: i}
}

We implement set() method for Packet and two functions newMessage and NewPacket that will work as constructors (one really interesting features in Go is the {} notation for inizializing an object, simply pass the value in a name-value couple, we will talk in detail about it in a next post). So lets complete everything with a main example:

func main() {
	var m, m1 PacketComposite
	var p1, p2 PacketComposite

	p1 = newPacket(1)
	p2 = newPacket(2)

	m = newMessage(0)
	m1 = newMessage(1)

	m1.addChild(p1, 0)
	m1.addChild(p2, 1)

	m.addChild(p1, 0)
	m.addChild(m1, 1)

	m.print()
}

we declare m, m1, p1 and p2 as PacketComposite, and than we use the init function we defined to create Packet and Message. We can add p1 and p2 to m1 since they are declared to be PacketComposite, and we can add m1 to m for the same reason: they are both PacketComposite.

Here the output of the program, after been compiled using 8g composite.go and linked using 8l composite.8. You can found complete compiling and linking instruction for each allowed system in the official website golang.org. I indent manually the output text because the code to indent is out of topic and to keep the source clean

Message0
	packet value: 1
	Message1
		packet value: 1
		packet value: 2

In next posts, I will talk about initialization in Go, exploring new features of google's new programming language and to understand if they are good or not.

Thank you for reading,
Marco Zunino

 

Go language introduction

 

Today I will talk about Google new system programming language: GO (not GO! by Francis McCab Keith Clark).

Go is based and built on C, but it pretend to make system programming easy. With easy I mean fast not just at compiling time, but also at coding time: a lot of functionalities such as communication among processors and concurrency are natively supported (I want to talk about goroutines in a future post). I don’t want to write about how to install, I dont like redundance and you can learn how to install go here (not on Windows, sorry!), and also some bases are provided by the official site of the language. There are of course some lacks in documentation, but the project is young, and people seem to like that.  It is possible for everyone to contribute to the Go project development.

There some aspect really interesting, such as the fact that pointer are supported, but not pointer arithmetic. This is the answer to the sentence “Why pointer arithmetic is not supported?” the official site provides:

Safety. Without pointer arithmetic it’s possible to create a language that can never derive an illegal address that succeeds incorrectly.

How not agree? Perhaps one way is to talk about performances. The go team ensure that today, hardware improvements allow accessing an array by index almost as fast as accessing with pointer arithmetic. Plus, not allowing pointer arithmetic, it was possible to develope a performant garbage collector. Go developers didn’t say how, as I read on a blog post by Richard Adhikari (if you have some details on how they manage to slow down automatic memory management avoiding pointer arithmetic, please post as a comment). So they say it works, Ok, it’s enough for me, I feel I can trust Google (I will perform some benchmark asap :) ).

Anyway, I am one of those who said that often, a low level control of memory for a programmer can be source of errors more than other, and if we are not developing hardware firmware we didn’t really need it. Of course we will accept it only if with garbage collector we obtain same performances as without. Consider that we are talking about Go, so we can use it for high level development patterns, even if it is a low level language.

Another interesting fact about Go is the way they implement Object Oriented Paradigm. There is no hierarchy structure. But Go is an Object Oriented language. OO is implemented using interfaces and we will see how later. It is possible to define types and definig methods for them:

type Test struct { i int }
func (t *Test) get() int {
    return t.i
}

There are a lot of stuff there! no semi-colons and you have to keep the { on the same line as the function declaration; Go rules.

Look at the method get() implementation, there is (t *Test) in its signature. The variable t it’s similar to this pointer in c++, it declare the type to wich the method belongs.

I talked about defining  a “virtual class”, called interface.

Iterfaces are amazing because you can define an interface and declare a virtual method it must be implement, and if you implement this method for some type, this type became automagically an implementation of the interface we declared. Take a look to the following Go code:

type testInterface interface {
    set(i int)
}
type Test struct { n int }

// pay attention, the receiver is *Test
func (t *Test) set(n int) { t.i = n }

// this function accepts as parameter a testInterface
func genericFunc(x testInterface) {}
func f1() {
    var p Test
    // it works
    getAndSet(&p)
}

}

Even if not explicit declared, since there is a methof set(i int) defined for type Test, now Test is an implementation of testInterface.

I would you to think about it, that means there is no need to use explicit type hierarchy to implement OOP?  Using Go, we can implement type hierarchy using interfaces, and that’s I mean when I said that go is a fast-to-write language: I think that with this design decisi0n, they really make a low level language that allows to implement using all that stuffs that we all love in high level dinamic languages. In next posts, I’d like to talk about the implementation of some design patterns with Go, Composite in particular, since I think it can be a good way to explore the features I just described, and many others.

Thank you for reading,
firma Marco Zunino

The post that was announced is here: Composite with Go