I Started to learn go about 4 years ago (circa 2012), during the week ends. Here are some interesting programming bits, during my initial learning phase.

Function Pointers in Go

Go language handles function pointers very elegantly, therefore I love it better than C.

Here is a Hello world example for function pointer in golang.

package main

import (
    "fmt"
)

type Transform func(in string) (out string, cascade bool)

func Hello(in string) (out string, cascade bool) {
    out = "Hello "+in
    return out, true
}

func print(xf Transform, in string) {
    t,b := xf(in)
    fmt.Println(t,b)
}
func main() {
    print(Hello, "Ashish")

}

Try this at Go Playground…

Next, I tested out the function pointer map.

package main

import (
    "fmt"
)

type Transform func(in string) (out string, cascade bool)

var XMap map[string] Transform = make(map[string] Transform)

func init() {
  XMap["HASH"] = Hello
}

func Hello(in string) (out string, cascade bool) {
    out = "Hi "+in
    return out, true
}

func Default(in string) (out string, cascade bool) {
    out = "Default: "+in
    return out, true
}

func print(fname, in string) {
    var xf Transform =  Default
    x := XMap[fname]
    if x != nil {
        xf = x
    }
    t,b := xf(in)
    fmt.Println(t,b)
}

func main() {
    print("HASH", "Ashish")
}

Check this out at Go Playground…

I will now demonstrate use of array of function pointers.

package main

import (
 "fmt"
)

type Transform func(in string) (out string, cascade bool)

var XArr []Transform

func init() {
  XArr = []Transform{Hello, Default}
}

func XForm(in string) (out string, cascade bool) {
 out = in

 for _, fx := range XArr {
   out, cascade = fx(out)
   if !cascade {
     break
   }
 }
 return out, false
}

func Hello(in string) (out string, cascade bool) {
 out = "Hi " + in
 return out, true
}

func Default(in string) (out string, cascade bool) {
 out = "Default: " + in
 return out, true
}

func print(in string) {
     var xf Transform = XForm
     t, b := xf(in)
     fmt.Println(t, b)
}

func main() {
  print("Ashish")
}

Try it at Go Playground…

One Line Tokenizer

I liked the one liner in go, by FB programmer, Gaurav

func tokenize(exp string) []string {
 return strings.Fields(
 strings.Replace(strings.Replace(exp, "(", " ( ", -1), ")", " ) ", -1),
 )
}

Here is the source code.

Go Nano Http Server

A micro light Http Server, which I use for serving web contents internally, mainly for Java DOCs rendering, and my daughter uses it for HTML5, CSS3 and JS rendering during development.

I have installed it in my GOLANG PATH so that it can be run from anywhere.

This code has been derived from golang.org sample.

/*
  A Micro Lite Http File Server
  http://golang.org/pkg/net/http/#example_FileServer
  go build nano_httpd.go
  ./nano_httpd --root="/home/ashish/ABLabs/AIAComponents"
*/
package main

import (
    "flag"
    "fmt"
 "log"
 "net/http"
)

func main() {
    inPort := flag.String("port","7070","Input Port Number, default 7070")
    flDir :=  flag.String("root", "~", "root content directory default is ~")
    flag.Parse()

    httpPort := ":" + *inPort
    fmt.Printf("Port %s, Doc Root [%s]\n",httpPort,*flDir)

 // Simple static webserver:
 log.Fatal(http.ListenAndServe(httpPort, http.FileServer(http.Dir(*flDir))))
}

Here is the source, nano_httpd.go

Go generate UUID

Here is a simple UUID generator, it uses version 4, Pseudo Random, as described in RFC 4122

uuid.go

package uuid

import (
 "encoding/hex"
 "crypto/rand"
)

func GenUUID() (string, error) {
 uuid := make([]byte, 16)
 n, err := rand.Read(uuid)
 if n != len(uuid) || err != nil {
 return "", err
 }
 // TODO: verify the two lines implement RFC 4122 correctly
 uuid[8] = 0x80 // variant bits see page 5
 uuid[4] = 0x40 // version 4 Pseudo Random, see page 7

 return hex.EncodeToString(uuid), nil
}

uuid test & benchmark routine, uuid_test.go

package uuid

import (
 "testing"
 )

func TestUUID(t *testing.T) {
    uuid, err := GenUUID()
    if  err != nil {
        t.Fatalf("GenUUID error %s",err)
    }
    t.Logf("uuid[%s]\n",uuid)
}

func BenchmarkUUID(b *testing.B) {
    m := make(map[string]int,1000)
    for i := 0; i < b.N; i++ {
       uuid, err := GenUUID()
       if  err != nil {
        b.Fatalf("GenUUID error %s",err)
       }
       b.StopTimer()
       c := m[uuid]
       if c > 0 {
         b.Fatalf("duplicate uuid[%s] count %d",uuid,c )
       }
       m[uuid] = c+1
       b.StartTimer()
    }
}

command to build uuid.go go build uuid.go

command to run test & benchmark:

go test -v -bench=".*UUID"  uuid.go uuid_test.go

sample output, i5 Dell Latitude E6410 laptop, running Ubuntu 12.04 (this was about 4 years ago, in 2012 :)

 RUN TestUUID
 PASS: TestUUID (0.00 seconds)
 uuid_test.go:13: uuid[50a4cca6402223f280541ed8135a08b9]
PASS
BenchmarkUUID  1000000       1914 ns/op
ok   command-line-arguments 2.982s

The source code of uuid.go and uuid_test.go.

HTTP UUID Service

I wanted to write a couchDB like UUID generator service. So, here you go…

You need to build and install the uuid.go described in the previous section.

To install the code you need to have it under GOPATH. Please refer to go documentation or type "go help" on the command console.

Here is the code for HTTP UUID Server.

package main

import (
    "fmt"
    "log"
    "net/http"
    "strconv"
    "uuid"
)

// uuid, the web server
func UUIDServer(w http.ResponseWriter, req *http.Request) {
    values := req.URL.Query()
    count := 1
    var err error
    if values != nil {
        cnt := values.Get("count")
        if cnt != "" {
            count, err = strconv.Atoi(cnt)
            if err != nil {
                fmt.Fprintf(w, "{\"Error\":\"%s\"}\n", err)
                return
            }
        }
    }
    for ; count > 0; count -= 1 {
        uuid, err := uuid.GenUUID()
        if err != nil {
            fmt.Fprintf(w, "{\"Error\":\"%s\"}\n", err)
        } else {
            fmt.Fprintf(w, "{\"uuid\":[\"%s\"]}\n", uuid)
        }
    }
}

func main() {
    http.HandleFunc("/_uuid", UUIDServer)
    err := http.ListenAndServe(":12345", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

Compile and run it.

go run uid_srv.go

This will spawn a server at localhost port 12345

To test it, run the command

curl -X GET "http://127.0.0.1:12345/_uuid?count=2"
Output:
{"uuid":["dccc3a2340ff48e28045576961d2dad2"]}
{"uuid":["0fcad33e405695ea8046acb5fd0fd758"]}

You can vary the count parameter to change the output UUID count.

Source code is here, uid_srv.go

Please feel free to use my go source code, here in my blog under UPL