Februari 20, 2016

Multiple Go versions in Linux

Currently, there are trends on software development that tend to release their SDK on regular basis. Rust for example, also Go with 6 month release cycle. This predictable release is good and I personally like it since I can predict on features availability and use them for my software development project. The downside of this approach is there are many versions availablle that install them using OS package manager is proved to be pain in the ass.

Some of developers then create tools to manage multiple versions of the SDK, see GVM (Go Version Manager) and multirust (for Rust) for example. They are good of course but I probably choose not to use them since probably someday they won't be developed (see the latest commit if you want). My approach is simpler but only for Linux with Bash. If you use Windows, you may adopt my approach using SET to setup env variables and put them in batch file (.BAT). Explanation follows.

Directory Setup

I put all of my Go related software inside /opt/software/go-dev-tools. Here's the structure:


Directory Contents

I put Go SDK inside go, all Go related tools inside go-tools, liteide for LiteIDE, and tmp for temporary pkg dir whenever I want to compile and put Go tools inside go-tools.

Inside go-version (go1.2.2, go1.3.3, etc), I extract all of downloaded SDK from Go download page.

Environment Variables

In my $HOME/env dir, I created go directory to manage environment variables for my Go version. They usually have the same env variables, except for version pre 1.5, 1.5 (for vendor experimentation) and  1.6.

Pre 1.5 and > 1.6

$ cat ~/env/go/go1.2.2
GODEVTOOLS_HOME=/opt/software/go-dev-tools

GO_HOME=$GODEVTOOLS_HOME/go/go1.2.2
LITEIDE_HOME=$GODEVTOOLS_HOME/liteide
GOTOOLS=$GODEVTOOLS_HOME/go-tools

export GOROOT=$GO_HOME
export GOOS=linux
export GOARCH=amd64
export GOHOSTOS=linux
export GOHOSTARCH=amd64
export GOBIN=$GOROOT/bin

export PATH=$PATH:$GO_HOME/bin:$LITEIDE_HOME/bin:$GOTOOLS

alias go=colorgo$

1.5

$ cat ~/env/go/go1.5.3
GODEVTOOLS_HOME=/opt/software/go-dev-tools

GO_HOME=$GODEVTOOLS_HOME/go/go1.5.3
LITEIDE_HOME=$GODEVTOOLS_HOME/liteide
GOTOOLS=$GODEVTOOLS_HOME/go-tools

export GOROOT=$GO_HOME
export GOOS=linux
export GOARCH=amd64
export GOHOSTOS=linux
export GOHOSTARCH=amd64
export GOBIN=$GOROOT/bin

export PATH=$PATH:$GO_HOME/bin:$LITEIDE_HOME/bin:$GOTOOLS

alias go=colorgo

export GO15VENDOREXPERIMENT=1
$

Usage 
Open new shell - terminal, and source environment variables:

$ source env/go/go1.2.2
11:25:22-bpdp@archer:~$ go version
go version go1.2.2 linux/amd64
11:25:25-bpdp@archer:~$

Open another new shell - terminal, and source env vars:

$ source env/go/go1.6.0
11:25:59-bpdp@archer:~$ go version
go version go1.6 linux/amd64
11:26:01-bpdp@archer:~$

and so on.

Go Tools

When you see something interesting for your Go project, just go to /opt/software/go-dev-tools/tmp and the Go get them and copy the files inside /opt/software/go-dev-tools/go-tools:

$ cd /opt/software/go-dev-tools/tmp/
$ export GOPATH=`pwd`
$ go get github.com/smartystreets/goconvey
$ mv ../go/go1.6/bin/goconvey ../go-tools/
$ which goconvey
/opt/software/go-dev-tools/go-tools/goconvey
$

I don't know whether my approach is the best, but it proves to be comfortable for me. As always, YMMV. Happy hacking!












Februari 08, 2016

Supervisor Dengan Multiple Workers pada Elixir

Beberapa hari ini saya mencoba otak atik Elixir setelah sekian lama mengamati. Untuk yang sudah terbiasa dengan Erlang, barangkali menyesuaikan diri tidak akan terlalu sulit, sementara bagi yang belum pernah mengenal Erlang, konsep let it crash dari Erlang untuk fault tolerant systems perlu proses pembelajaran yang lumayan.

Konsep supervisor tree untuk proses di Elixir tidak ada hubungannya dengan proses di sistem operasi. Persamaannya hanya pada struktur tree. Pada proses di sistem operasi, tidak ada mekanisme untuk mengelola proses-proses tersebut, sedangkan pada Elixir, proses-proses tersebut dikelola menggunakan proses supervisi: ada proses untuk me-restart secara otomatis proses anak yang mati. Bagian ini mempunyai banyak pilihan, tetapi di tulisan ini saya hanya akan menampilkan mekanisme untuk membuat software menggunakan Elixir dengan banyak proses anak (sering disebut child process, sering juga disebut worker). Saya menulis ini karena tidak ada penjelasan yang jelas untuk materi ini. Pemula biasanya akan merasa kebingungan.

Program yang akan dibuat ini sebenarnya sederhana saja: membuat 3 worker process yang akan melakukan proses penambahan, pembagian, dan perkalian. Kode sumber bisa diperoleh di https://github.com/bpdp/elixir-playground. Pada dasarnya, hal-hal yang perlu diperhatikan pada repo tersebut adalah:
  1. Repo workers saya buat menggunakan mix new workers --sup karena sejak awal dimaksudkan untuk membangun aplikasi menggunakan beberapa worker dengan supervisi.
  2. Tidak ada perubahan pada hasil mix new di atas kecuali pada file-file berikut ini:
    • lib/workers.ex => saya ubah hanya berisi satu callback function (start, sudah ketentuan dari Elixir bahwa callback function bernama start dengan 2 argumen). Di callback function ini saya definisikan beberapa worker yang saya letakkan di file lib/workers/worker1.ex - sampai worker3.ex. Sesuai ketentuan dari Elixir, penamaan file dan nama module harus sesuai: workers/worker1.ex => Workers.Worker1
    • Worker process saya letakkan pada workers/worker1.ex - worker3.ex. Setiap worker menggunakan GenServer yang mengharuskan adanya function start_link dan init.
Untuk menjalankan:

$ mix run
Elixir.Workers.Worker1 started
7
Elixir.Workers.Worker2 started
3.0
Elixir.Workers.Worker3 started
60
Silahkan melihat halaman-halaman manual untuk penjelasan lebih lanjut.