Today I’m going to present two important concepts you’ll need to know for your Go journey: Objects and Concurrency. That will allow us to talk about toolkit, frameworks, ORMs and so on, in future posts.
Is Go an Object Oriented language? If we use the most simple definition of Object as an abstract data type that has state (data) and provide a behaviour (code), I say Yes.
Since there is no inheritance in Go, we need to think in terms of composition. Except for that, we can find many of the same features like:
Now let me introduce some concepts with examples that will illustrate it.
Go has pointers, but no pointer arithmetic.
x := 5
y := &x
fmt.Println(*y)
Output :
5
y points to x and the value of y is obtained using a * operator. The & operator is used to get the address of a variable.
The new operator is used to allocate memory to a pointer variable.
x := new(int)
*x = 9
fmt.Println(*x)
Output :
9
Are user-define data types which contains named fields. We can think of them as “object” in Go.
We declare structures using the type and struct keyword. Individual elements of the structure are accessed using the dot operator.
In the next example I also show composition:
type Person struct {
Name string
Address Address
age int
}
type Address struct {
Number string
Street string
City string
State string
Zip string
}
Note that Go makes a difference between lower case and capitals in field definitions. The letter case refers to the scope of the field. Name and Address (above) are public variables and age is a private variable. Capital names are publicly accessible.
This example in PHP looks like:
<?php
class Person {
public $Name;
public $Address;
private $age;
}
class Address {
public $Number;
public $Street;
public $City;
public $State;
public $Zip;
}
PHP does not have type hinting at the variable definition level, only the function level.
This type hinting / scalar values gives Go an upper hand when it comes to syntax checking.
We can declare methods on any user-defined type.
A method declaration in Go is just like a function, except it has an explicit receiver, declared immediately before func. This function also takes advantage of named return variables, pre-initializing them for us.
Let’s extend the structures/classes defined in the previous example
func (p *Person) Greet() {
fmt.Println("Hi, my name is", p.Name)
}
func (p *Person) Location() {
fmt.Println("I’m at", p.Address.Number, p.Address.Street, p.Address.City, p.Address.State, p.Address.Zip)
}
In PHP:
<?php
class Person {
public $Name;
public $Address;
private $age;
public function __construct($Name,Address $Address, $age)
{
$this->Name = $Name;
$this->Address = $Address;
$this->age = $age;
}
public function Greet()
{
print_r("Hi, my name is " . $this->Name);
}
public function Location()
{
print_r("I’m at "
. $this->Address->Number
. " " . $this->Address->Street
. " " . $this->Address->City
. " " . $this->p.Address->State
. " " . $this->Address->Zip
);
}
}
class Address {
public $Number;
public $Street;
public $City;
public $State;
public $Zip;
public function __construct($Number, $Street, $City, $State, $Zip)
{
$this->Number = $Number;
$this->Street = $Street;
$this->City = $City;
$this->State = $State;
$this->Zip = $Zip;
}
}
An interface type is defined by a set of methods. A value of interface type can hold any value that implements those methods.
package main
import "fmt"
import "math"
type geometry interface {
area() float64
perim() float64
}
type rect struct {
width, height float64
}
type circle struct {
radius float64
}
func (r rect) area() float64 {
return r.width * r.height
}
func (r rect) perim() float64 {
return 2*r.width + 2*r.height
}
func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
}
func measure(g geometry) {
fmt.Println(g)
fmt.Println(g.area())
fmt.Println(g.perim())
}
func main() {
r := rect{width: 3, height: 4}
c := circle{radius: 5}
measure(r)
measure(c)
}
And this how it looks in PHP
<?php
interface geometry
{
public function area();
public function perim();
}
class rect implements geometry
{
public $width;
public $height;
public function area()
{
return $this->width * $this->height;
}
public function perim()
{
return (2 * $this->width) + (2 * $this->height);
}
}
class circle implements geometry
{
public $radius;
public function area()
{
return pi() * pow($this->radius,2);
}
public function perim()
{
return 2 * pi() * $this->radius;
}
}
function measure($geometry) {
print_r($geometry);
print_r($geometry->area());
print_r($geometry->perim());
}
$r = new rect();
$r->width = 3;
$r->height = 4;
$c = new circle();
$c->radius = 5;
measure($r);
measure($c);
Concurrency refers not only to CPU parallelism, but also to asynchrony: letting slow operations like a database or network-read run while the program does other work.
Even though, “Concurrency is not parallelism”, if this sentence means nothing to you, I suggest to check out Rob Pike’s excellent talk on the subject. It’s a great explanation with funny examples of gophers working in parallel and concurrent, you will enjoy all 30 minutes.
Go has a rich support for concurrency via goroutines and channels. This is one of the highlights of the language.
A goroutine is a lightweight thread of execution.
Goroutines can be described as functions which run concurrently from other functions.
They’re invoked following the go keyword. As the function is invoked it runs concurrently and the rest of the code is executed without waiting for the completion of that function.
In comparison with other languages, we can consider goroutines as “green threads“. What does it mean? Go use multiplexing strategies to group goroutines and run them in a less number of OS threads. The advantages, among others, is that you can run concurrent applications in a single core system, threads are managed by virtual machine or binary library using User space instead of Kernel space, they start faster and with a low stack that can grow based on needs, just to mention some.
Here’s a small example of a goroutine:
package main
import "fmt"
func f(from string) {
for i := 0; i < 3; i++ {
fmt.Println(from, ":", i)
}
}
func main() {
f("direct")
go f("goroutine")
go func(msg string) {
fmt.Println(msg)
}("going")
var input string
fmt.Scanln(&input)
fmt.Println("done")
}
Channels are the pipes that connect concurrent goroutines. We can think on channels as process intercommunication. Go uses cooperative multitasking between goroutines. So if one routine never yields, then the other will never run.
You can send values into channels from one goroutine and receive those values into another goroutine.
We can use channels to synchronize execution across goroutines.
Channels must be created before being used, using the chan keyword.
package main
import "fmt"
func main() {
messages := make(chan string)
go func() { messages <- "ping" }()
msg := <-messages
fmt.Println(msg)
}
Since I couldn’t find a better example without the need of writing a post explaining its concepts, I bring you a simple one in Java using multi-threading:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
class Server
{
public static void main(String[] args) throws IOException
{
ServerSocket socket = new ServerSocket(9000);
while (true)
{
final Socket s = socket.accept();
Runnable r = new Runnable()
{
@Override
public void run()
{
doWork(s);
}
};
new Thread(r).start();
}
}
static void doWork(Socket s)
{
}
}
Thanks for reading! I hope you enjoy it.
See you on the next post!
Tags: control structures, golang, programming
Categories: Golang, Programming
Lets talk!
Join our mailing list, we promise not to spam.