Search This Blog

Showing posts with label Go. Show all posts
Showing posts with label Go. Show all posts

Saturday, 19 March 2016

Go implementation of Fibonacci - two ways

There are various ways how to go about the implementation of Fibonacci, or other series, in Go. Some are common to different languages, like a recursive function or using a closure. One approach is Go specific, taking advantage of its concept of channels. I shall be showing and explaining the closure based and channel based implementations.

Closure based implementation

Closures are functions that "close over"  the scope of the parent namespace and, as a result, have access to and remember variables in the parent scope, even after they finished running. As a result, closures have been used abundantly to implement, for instance, counter incrementing.


Channel based implementation

Go introduced a concept of channels, that serve for communication between goroutines, the Go approach to concurrency. If a channel is created without specifying its capacity, it is blocking and the processing will stop until the channel receives or can send data (depending on whether a sender or a receiver).


Full program


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package main

import (
 "fmt"
 "time"
)

func main() {
        max := 15

 fmt.Println("================== FIBONACCI CLOSURE implementation ==================")
 start := time.Now()
 fmt.Println("%s", start)

 f := fib_closure()

 for n := 0; n < max; n++ {
  fmt.Printf(">>> %d\n", n)
  fmt.Println(f(n))
 }
 end := time.Now()
 fmt.Printf("Calculation finished in %s \n", end.Sub(start))

 fmt.Println("================== FIBONACCI: CHANNEL implementation ==================")
 fmt.Println("%s", start)

 start = time.Now()
 c := fib_chan()

 for n := 0; n < max; n++ {
  fmt.Printf(">>> %d\n", n)
  fmt.Println(<-c)
 }
 end = time.Now()
 fmt.Printf("Calculation finished in %s \n", end.Sub(start)) 

}

func fib_closure() func(int) int {
 i, j := 1, 1

 return func(n int) int {
  switch {
  case n == 0 || n == 1:
   return 1
  default:
   i, j = j, i+j
  }

  return i
 }
}

func fib_chan() chan int {
 c := make(chan int)

 go func() {
  for i, j := 0, 1; ; i, j = i+j, i {
   c <- i
  }
 }()

 return c
}


Explanation


Shared by both approaches:


We decide how many Fibonnaci numbers we want calculated.

Performance comparison        max := 15

We are also interested in the performance of each approach, so we shall do some benchmaking using start := time.Now(), end :+ time.Now() and subtraction end.Sub(start).

Fibonacci - closure implementation


func fib_closure() func(int) int {

i, j := 1, 1 ..... for 0 and 1, the fibonnaci is 1

return func(n int) int { .... We are returning a closure, that on each subsequent invocation remembers the                                                            values  of i and j.

switch {
case n == 0 || n == 1:
return 1
default:
i, j = j, i+j  ........ The previous state is remembered (i, j) and the new one calculated (j, i+j)
}

return i
}
}

Then doing the calculations: 

fmt.Println("================== FIBONACCI CLOSURE implementation ==================")
start := time.Now()
fmt.Println("%s", start)

f := fib_closure() ............ We initialize the state by running the fib_closure()  and creating a reference to its                                                        return function/closure.

for n := 0; n < max; n++ {
fmt.Printf(">>> %d\n", n)
fmt.Println(f(n)) ..... The closure f(n) remembers calculations of < n
}
end := time.Now()
fmt.Printf("Calculation finished in %s \n", end.Sub(start))


Fibonacci - channel implementation


func fib_chan() chan int {
c := make(chan int)

go func() {
for i, j := 0, 1; ; i, j = i+j, i { ..... the logic of the fibonnaci calculation
c <- i  ................................. the result is sent to the channel
}
}()

return c
}

Then doing the calculations:

fmt.Println("================== FIBONACCI: CHANNEL implementation ==================")
fmt.Println("%s", start)

start = time.Now()
c := fib_chan() ................ Go channel which returns the Fibonacci result sent to it

for n := 0; n < max; n++ {
fmt.Printf(">>> %d\n", n)
fmt.Println(<-c) ...... the channel returns received the calculated value
}
end = time.Now()
fmt.Printf("Calculation finished in %s \n", end.Sub(start)) 


Performance comparison


On different runs, I got the following runtimes:

Closure - Channel

      222 - 140 us
      253 - 168 us
      255 - 175 us

The difference is due to what else the OS was doing at the time when the program ran. The closure implementation is roughly 1.5 times slower. (The recursive approach is the slowest.)

Tuesday, 15 December 2015

Golang Tips and Tricks


Installation of Go crypto/ssh module (Ubuntu 15.04)

 

go get -v code.google.com/p/go.crypto/ssh

code.google.com/p/go.crypto (download)
go: missing Mercurial command. See http://golang.org/s/gogetcmd
package code.google.com/p/go.crypto/ssh: exec: "hg": executable file not found in $PATH

This failure in downloading the crypto/ssh package is due to the fact the crypto/ssh repo was moved to golang.org/x/crypto/ssh.

go get -v  golang.org/x/crypto/ssh

Fetching https://golang.org/x/crypto/ssh?go-get=1
Parsing meta tags from https://golang.org/x/crypto/ssh?go-get=1 (status code 200)
...
...
# golang.org/x/crypto/ssh
/home/tamara/.gvm/pkgsets/go1.3.3/global/src/golang.org/x/crypto/ssh/keys.go:492: undefined: crypto.Signer

This error is fixed by upgrading Go to at least 1.4.

go get -v  golang.org/x/crypto/ssh

golang.org/x/crypto/curve25519
golang.org/x/crypto/ssh

Setting $GOPATH (golang workspace) when installing Go with gvm

 

Ubuntu comes with an obsolete Go version. We can use gvm, Go version manager, to install a higher Go version by following steps in the http://www.hostingadvice.com/how-to/install-golang-on-ubuntu/

Starting to use a particular Go version (gvm use go1.4.2) resets some of the Go environment variables:

go env

GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/tamara/.gvm/pkgsets/go1.4.2/global"
GORACE=""
GOROOT="/home/tamara/.gvm/gos/go1.4.2"
GOTOOLDIR="/home/tamara/.gvm/gos/go1.4.2/pkg/tool/linux_amd64"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

gvm pkgset list

gvm go package sets (go1.4.2)

=>  global

gvm pkgset create tamarakaufler
gvm pkgset use tamarakaufler

=> Now using version go1.4.2@tamarakaufler
gvm pkgset list
gvm go package sets (go1.4.2)

    global
=>  tamarakaufler
 
gvm pkgenv tamarakaufler
opens the default editor for configuration of the 
project specific workspace. Edit the lines 12 
and 16 accordingly (bold parts)  

# line 12
export GOPATH; GOPATH="/home/tamara/.gvm/pkgsets/go1.4.2/tamarakaufler:$HOME/programming/go:$GOPATH"

# line 16
export PATH; PATH="/home/tamara/.gvm/pkgsets/go1.4.2/tamarakaufler/bin:${GVM_OVERLAY_PREFIX}/bin:$HOME/programming/go/bin:${PATH}"

Sunday, 1 November 2015

Literals in Go

BACKGROUND

  • Go source code is written in Unicode characters, encoded in UTF-8
  • Literals represent fixed, ie constant, values
  • There are two types of literals in Go, related to textual context: rune literals and string literals.

RUNE literals

Rune is an integer (uint32, 4 byte binary number), representing a Unicode code point, a unique identifier of a character within a particular encoding. In UTF-8, the most common Unicode encoding, a code point can represent a sequence of one to 4 bytes. ASCII (representing the old English and a group of unprintable characters) has 128 code points; extended ASCII, representing most Western languages 256.

Rune literal is expressed as one or more characters in single quotes, excluding unquoted single quotes and newlines.

STRING literals

String literal is a concatenation of characters, a character sequence. There are two types: interpreted string literals and raw string literals.
Interpreted string literals are enclosed in double quotes with any character allowed, except for unquoted double quote and newline.

Raw string literals are enclosed in back quotes. The character sequence can contain newlines and backslashes have no special escaping effect. Any carriage returns (\r) within the literal are stripped from the raw string.

Example


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
 "log"
 "net/http"
)

func main() {

 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte('<html><head>
    <title>Chatting away</title>
    </head><body>Go and chat!</body></html>
    '))
 })

 if err := http.ListenAndServe(":3333", nil); err != nil {
  log.Fatal("Starting server : ", err)
 }

}

The above code produces errors on lines 11 and 14: rune literal not terminated.

Keeping the single quotes and putting the whole string value on one line results in:  illegal rune literal. Single quotes are reserved for characters, so no surprise there.

Changing the single quotes to double quotes still results in error, this time: string literal not terminated. You may find it puzzling, just as I did, until you realize this is an interpreted string literal (because enclosed in double quotes) and recall these cannot contain newlines.

There are two options here:
  1. Put the whole string value on one line:
            "<html><head><title>Chatting away</title></head><body>Go and chat!</body></html>"
  1. Use back quotes, ie use a raw string literal, rather than an interpreted one. This will allow to spread the string value over several lines, because the back quoted raw string literal removes the carriage return: 
             `<html>
              <head><title>Chatting away</title></head>
              <body>Go and chat!</body>
              </html>`