Wednesday, August 3, 2022

Golang is blissful and painful at the same time.

Coming from python background, when started to learn Golang, I found these are the things are painful.

* Golang deletes a item in a slice, map or array

* Golang detecting a item exists in a slice, map or array

* Golang managing error handling, keep repeating writing the boilerplate code e.g. if error != nil statement.

* Golang does not comes with [list|tuple,dictionary]-comprehension techniques. Every operation has to be on the boilerplate codes on native for loop.

* Golang does not comes with inheritance but it does come with concept of composition. 

* Golang manages string, runes in a some complicated way.

 

On the contrary, Golang does showcasing it real power in certain area when solving problem.

* Golang go-routine and channels. Way impressive and powerful than many programming.

* Golang duck typing - interface concept, aka, if a animal walk like a duck, sound like a duck, then the animal is most likely a duck! 

* Golang is able to compile as a single binary for several platforms. wow! this is the most selling feature in the microservice environment.

* Golang testing framework is robust!

* Golang is performant!


Golang is well-received by community, and a lot of good engines are developed on top of Golang, it proves that Golang able to cope with large scale of technologies. Moreover, Golang is easy to learn, it makes the adoption of Golang in a lot of projects becoming even more seamless. With that said, even with all the pains listed above, the benefit is clearly outweigh the pains. 

Hopefully, Golang development team will have put those in mind in the upcoming release to solve the simple problems. That's would make a lot of developers even love Golang. Go! Golang.

Monday, July 25, 2022

Golang handling os.signal with goroutines

Learning goroutines and practising with `os.Signal`

This is the small snippet of golang codes that showing how goroutines work perfectly.

package main


import (

"fmt"

"os"

"os/signal"

"syscall"

"time"

)


func signalHandler(signal os.Signal) {

switch signal {

case syscall.SIGHUP:

fmt.Println("Signal:", signal.String())

case syscall.SIGINT:

fmt.Println("Signal:", signal.String())

case syscall.SIGTERM:

fmt.Println("Signal:", signal.String())

case syscall.SIGQUIT:

fmt.Println("Signal:", signal.String())

default:

fmt.Println("Unhandled/unknown signal")

}

}


func keepDoingStuffs() {

for {

fmt.Printf("Starting job...")

time.Sleep(time.Second * 5)

fmt.Println("completed.")

}

}


func printNumbers() {

for {

time.Sleep(time.Second * 1)

fmt.Printf(".")

}

}


func trapTimeout(done chan bool) {

for {

select {

case <-time.After(time.Second * 20):

fmt.Println("Timeout.")

done <- true

case <-done:

return

}

}

}


func trapSignal(done chan bool) {

sigc := make(chan os.Signal, 1)

defer close(sigc)

signal.Notify(sigc, syscall.SIGINT, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGQUIT)

for {

select {

case s := <-sigc:

signalHandler(s)

done <- true

case <-done:

return

}

}

}


func main() {

done := make(chan bool)

defer close(done)


go trapSignal(done)

go trapTimeout(done)

go keepDoingStuffs()

go printNumbers()


if <-done {

fmt.Println("Exit gracefully.")

return

}

}


Monday, May 23, 2022

Part 1: Compiling elasticsearch from source

I recently came across some complication where I need to change some of the codes in the elasticsearch and compile them into the binary tar.gz, build a docker image and consume it. It is rarely out there in term of documentation, so I decide to share my findings here.


1. Getting the source codes from elasticsearch. I believe this should be easy, and no explanation needed here.

https://github.com/elastic/elasticsearch

For example, I am looking for the latest 8.2 release, so I will checkout the 8.2 branch from now.

2. Install the right Java version. Here, from the builddoc, it says JAVA17 is needed. So, get ready your gear with Java 17, and set a JAVA_HOME pointing to the right version.

❯ update-alternatives --config java 

There are 3 choices for the alternative java (providing /usr/bin/java). Selection Path Priority Status ------------------------------------------------------------ 

* 0 /usr/lib/jvm/java-17-openjdk-amd64/bin/java 1711 auto mode 

1 /usr/lib/jvm/java-11-openjdk-amd64/bin/java 1111 manual mode 

2 /usr/lib/jvm/java-17-openjdk-amd64/bin/java 1711 manual mode

manual mode Press to keep the current choice[*], or type selection number: ^C

3. Fun begins now, from the source codes itself, you can see a gradlew build tool is provided. Digging more onto it, you will discover to build a linux version of binary, you need to run a command like this.

./gradlew :distribution:archives:linux-tar:assemble 

Then end result will be like this,

❯ ./gradlew :distribution:archives:linux-tar:assemble 

Starting a Gradle Daemon (subsequent builds will be faster) ======================================= 

Elasticsearch Build Hamster says Hello! 

Gradle Version : 7.4.2 

OS Info : Linux 5.13.0-41-generic (amd64) 

JDK Version : 17.0.3 (Private Build) 

JAVA_HOME : /usr/lib/jvm/java-17-openjdk-amd64 

Random Testing Seed : D75C9C369C262E41 In FIPS 140 mode : false ======================================= 

> Task :server:compileJava 

Note: Some input files use or override a deprecated API. 

Note: Recompile with -Xlint:deprecation for details. 

Note: Some input files use or override a deprecated API that is marked for removal. 

Note: Recompile with -Xlint:removal for details. 

 BUILD SUCCESSFUL in 2m 18s 499 actionable tasks: 6 executed, 493 up-to-date 


4. Horray! Now you have your build success. You can get the binary tar.gz at here.

❯ ls -al distribution/archives/linux-tar/build/distributions/elasticsearch-8.2.1-SNAPSHOT-linux-x86_64.tar.gz