Sunday, August 21, 2016

How to Use Vendoring in Go

Vendoring is a way to put dependencies in a Go project without having to mess with the GOPATH. The idea is simple, that is to put the dependencies in a directory called "vendor".
awesomego/
|-- foo (this directory contains a library, i.e. non-main package)
|   `-- foo.go
|-- main.go (this is the main program)
`-- vendor (this is where the third-party libs live)
    `-- goini
        |-- goini.go
        |-- goini_test.go
        |-- LICENSE
        |-- README.md
        `-- testdata
            |-- test_expected.ini
            `-- test.ini

The project structure above has the following benefits.
  1. It can be used to build a library.
  2. It can be used to build an executable.
  3. It is go-gettable.
This is an example of using it in a standard Go workspace.
go-workspace/
`-- src
    `-- awesomego
        |-- foo
        |   `-- foo.go
        |-- main.go
        `-- vendor
            `-- goini
                |-- goini.go
                |-- goini_test.go
                |-- LICENSE
                |-- README.md
                `-- testdata
                    |-- test_expected.ini
                    `-- test.ini
To build it as a library:
GOPATH=`pwd` go install awesomego/foo
To build it as an executable:
GOPATH=`pwd` go install awesomego

Wednesday, August 3, 2016

Compile-Time Enum in Go

Unlike other languages, Go does not support enum. However, it is pretty straightforward to create something that behaves similar to enum. There are a lot of articles on the internet on how to create an enum in Go, which pretty much looks like below.
package main

import (
    "fmt"
)

type myType string

const (
    Foo myType = "foo"
    Bar myType = "bar"
)

func doSomething(t myType) {
    fmt.Println(t)
}

func main() {
    // baz := "baz"
    // This will result in compilation error:
    // "cannot use baz (type string) as type myType in argument to doSomething"
    // doSomething(baz)

    // However, this is allowed.
    doSomething("baz")
}
As you can see in the code above, calling doSomething("baz") does not result in a compilation error. To fix that, we can change the code to look like below.
package main

import (
    "fmt"
)

type myType string

const (
    Foo myType = "foo"
    Bar myType = "bar"
)

func doSomething(t *myType) {
    fmt.Println(*t)
}

func main() {
    // This will now result in a compilation error.
    // doSomething("baz")

    baz := myType("baz")
    doSomething(&baz)
}

Wednesday, July 6, 2016

Compile-time Builder Pattern in Java

Builder pattern is a pattern that is usually used for a language that does not support named parameters. However, the typical builder pattern has a limitation, such at it can't at compile-time check the required parameters. Below are some suggestions how to use a builder pattern that has compile-time check.
  • Option 1
  • public class Foo {
        private String a;
        private String b;
        private String c;
    
        private Foo() {
        }
    
        public static ABuilder newBuilder() {
            return new ABuilder(new Foo());
        }
    
        private static class ABuilder {
            private final Foo foo;
    
            private ABuilder(Foo foo) {
                this.foo = foo;
            }
    
            public BBuilder a(String a) {
                foo.a = a;
                return new BBuilder(foo);
            }
        }
    
        private static class BBuilder {
            private final Foo foo;
    
            private BBuilder(Foo foo) {
                this.foo = foo;
            }
    
            public CBuilder b(String b) {
                foo.b = b;
                return new CBuilder(foo);
            }
        }
    
        private static class CBuilder {
            private final Foo foo;
    
            private CBuilder(Foo foo) {
                this.foo = foo;
            }
    
            public FinalBuilder c(String c) {
                foo.c = c;
                return new FinalBuilder(foo);
            }
        }
    
        private static class FinalBuilder {
            private final Foo foo;
    
            private FinalBuilder(Foo foo) {
                this.foo = foo;
            }
    
            public Foo build() {
                return foo;
            }
        }
    
        public static void main(String[] args) {
            Foo foo = Foo.newBuilder().a("a").b("b").c("c").build();
            System.out.println(foo);
        }
    }
    
  • Option 2
  • public class Bar {
        private final String a;
        private final String b;
        private final String c;
    
        public static class False {}
        public static class True {}
    
        public static class Builder<Has1, Has2, Has3> {
            private String a;
            private String b;
            private String c;
    
            public static Builder<False, False, False> create() {
                return new Builder<>();
            }
    
            public Builder<True, Has2, Has3> a(String a) {
                this.a = a;
                return (Builder<True, Has2, Has3>) this;
            }
    
            public Builder<Has1, True, Has3> b(String b) {
                this.b = b;
                return (Builder<Has1, True, Has3>) this;
            }
    
            public Builder<Has1, Has2, True> c(String c) {
                this.c = c;
                return (Builder<Has1, Has2, True>) this;
            }
        }
    
        public Bar(Builder<True, True, True> builder) {
            a = builder.a;
            b = builder.b;
            c = builder.c;
        }
    
        public static void main(String[] args) {
            Bar bar = new Bar(Builder.create().a("a").b("c").c("a"));
            System.out.println(bar);
        }
    }
    

Thursday, April 21, 2016

How to Create a Command Line Spinner in Go

package main

import "fmt"
import "time"

func main() {
    chars := "|/-\\"
    i := 0
    for {
        i++
        char := chars[i%len(chars)]
        fmt.Printf("\rDownloading: %c", char)
        time.Sleep(100 * time.Millisecond)
    }
}

Monday, August 17, 2015

Parallel Merge Sort using Fork and Join

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

public class MergeSortForkJoin {
    public static class MergeSortTask extends RecursiveAction {
        private static final long serialVersionUID = 1L;
        private final List<Integer> list;
        private final int lo;
        private final int hi;
        
        public MergeSortTask(List<Integer> list, int lo, int hi) {
            this.list = list;
            this.lo = lo;
            this.hi = hi;
        }
        
        @Override
        protected void compute() {
            if (lo >= hi) {
                return;
            } else {
                int mid = (lo + hi) / 2;
                MergeSortTask task1 = new MergeSortTask(list, lo, mid);
                MergeSortTask task2 = new MergeSortTask(list, mid+1, hi);

                invokeAll(task1, task2);

                merge(list, lo, mid, hi);
            }
        }
        
        private void merge(List<Integer> list, int lo, int mid, int hi) {
            List<Integer> tmp = new ArrayList<>();
            for (int i : list) {
                tmp.add(i);
            }
            int left = lo;
            int right = mid + 1;
            int idx = lo;
            while (left <= mid && right <= hi) {
                if (tmp.get(left) <= tmp.get(right)) {
                    Integer element = tmp.get(left);
                    list.set(idx, element);
                    left++;
                    idx++;
                } else {
                    Integer element = tmp.get(right);
                    list.set(idx, element);
                    right++;
                    idx++;
                }
            }
            while (left <= mid) {
                Integer element = tmp.get(left);
                list.set(idx, element);
                idx++;
                left++;
            }
            while (right <= hi) {
                Integer element = tmp.get(right);
                list.set(idx, element);
                idx++;
                right++;
            }
        }
    }
    
    public static void main(String[] args) throws Exception {
        ForkJoinPool pool = new ForkJoinPool();
        List<Integer> list = Arrays.asList(4, 9, 1, 5, 8, 0, 7, 6, 3, 2);
        System.out.println("Unsorted: " + list);
        MergeSortTask task = new MergeSortTask(list, 0, list.size()-1);
        try {
            do {
                pool.execute(task);
            } while (!task.isDone());
        } finally {
            pool.shutdown();
        }
        System.out.println("Sorted:   " + list);
    }
}

Monday, August 10, 2015

How to Organize a Go Project

The official has a good information on how to structure your Go code. In this blog, I am going to explain a little bit more about it. Let's say we want to create a Go project containing a command and a package.
workspace1/
|-- build.sh
`-- src
    `-- mylib
        |-- hello
        |   `-- hello.go (package)
        `-- main.go (command)
hello.go
package hello

import "fmt"

func SayHello() {
    fmt.Println("Hello")
}
main.go
package main

import "mylib/hello"

func main() {
    hello.SayHello()
}
build.sh
#!/bin/bash

export GOPATH=`pwd`
go install mylib/hello
go install mylib
Calling build.sh will create this structure.
workspace1/
|-- bin
|   `-- mylib (executable)
|-- build.sh
|-- pkg
|   `-- linux_amd64
|       `-- mylib
|           `-- hello.a (library)
`-- src
    `-- mylib
        |-- hello
        |   `-- hello.go (package)
        `-- main.go (command)
In order to make mylib project go-gettable, let's make it into a Git project. Take a note that we will be creating a Git project in the mylib directory and not in the workspace1 directory.
1. cd workspace1/src/mylib
2. git init
3. git add .
4. git commit -m "Initial commit"
5. Push this repository to the remote URL
Now let's create another project that uses mylib. This new project is a simple project that uses mylib.
workspace2/
|-- build.sh
`-- src
    `-- myapp
        `-- app
            `-- app.go (command)
1. cd workspace2
2. git init
3. git add submodule [mylib_git_url] src/mydomain/user/mylib (the src/mydomain/user is just a convention, you can also set the path to src/mylib)
After the submodule addition, we will have this structure.
workspace2/
|-- build.sh
`-- src
    |-- myapp
    |   `-- app
    |       `-- app.go (command)
    `-- mydomain
        `-- user
            `-- mylib
                |-- hello
                |   `-- hello.go (package)
                `-- main.go (command)
app.go
package main

import (
    "fmt"
    "mydomain/user/mylib/hello"
)

func main() {
    fmt.Println("Do something")
    hello.SayHello()
}
build.sh
#!/bin/bash

export GOPATH=`pwd`
go install mydomain/user/mylib/hello
go install myapp/app
Calling build.sh will create this structure.
workspace2/
|-- bin
|   `-- app (executable)
|-- build.sh
|-- pkg
|   `-- linux_amd64
|       `-- mydomain
|           `-- user
|               `-- mylib
|                   `-- hello.a (library)
`-- src
    |-- myapp
    |   `-- app
    |       `-- app.go (command)
    `-- mydomain
        `-- user
            `-- mylib
                |-- hello
                |   `-- hello.go (package)
                `-- main.go (command - not used)

Saturday, May 23, 2015

How to Create a Simple REST Server in Go

Below is an example on how to create a simple REST server in Go.
package main

import (
    "encoding/json"
    "log"
    "net/http"
    "strconv"
)

type Hello struct {
    Message string `json:"message"`
}

func HelloServer(w http.ResponseWriter, req *http.Request) {
    log.Println("Received a request from ", req.RemoteAddr)
    w.Header().Set("Content-Type", "application/json")
    if req.Method == "GET" {
        encoder := json.NewEncoder(w)
        hello := Hello{"Hello World"}
        encoder.Encode(hello)
    }
}

func main() {
    port := 8080
    // serve static content
    http.Handle("/", http.FileServer(http.Dir("html")))
    http.HandleFunc("/hello/", HelloServer)
    log.Println("Starting HTTP server at", port)
    err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
    if err != nil {
        log.Fatal("Unable to start the server: ", err)
    }
}