Tag Archives: Go

Reading MariaDB/MySQL binary log files in Go

While looking into a replication-related issue, I came across an interesting problem where I wanted to get the name of the largest event in a very large binary log file. So, I thought of putting Vaquita’s binary log API to a test. Here’s a simple program to read a binary log file and print the largest event and its size.

In this case, having RawEvents is sufficient as we are not interested in the actual content of the events.
Wiki : https://github.com/vaquita/mysql/wiki/Replication-Binary-Logs

Edit: Updated the above program to account for a recent change done to RawEvent(), which now returns error.

Go projects in MySQL/MariaDB ecosystem

Please let me know if you come across a MySQL/MariaDB Go project not listed here.

enum types in Go?

Well, there is none! So, let’s say one needs to implement an API with a parameter that accepts only a limited set of values. So that its invocation with invalid values can be detected at compile time. In C/C++, this could have been accomplished by defining an enum type of all valid entities and using the same enum type to declare the formal parameter. So, how to achieve this in Go? There is a pretty simple way: define a new “unexported” type and “exported” constants of this new type for all valid values. The “type” is not exported to forbid the API users from defining or adding new values and use of exported constants is thus enforced.

Here is a simple example to demonstrate this:

A good example: http://stackoverflow.com/questions/14236263/when-should-a-type-be-a-struct-containing-another-type-and-when-should-it-just

Preprocessing Go programs

Preprocessor macros can be considered integral part of C/C++ programs. From inclusion of header files to controlling the build type (Debug-vs-NonDebug or Linux-vs-Win), macros play a very important role. For example, there are many advantages of having a debug build. Adding asserts, trace points and printing useful information helps developers gain insights of a (faulty) program. On the other hand, the program can easily be build without all these ‘extra’ debug-related-code (aka release build) by using a macro-processor along with other build tools.

So I thought, how about using this macro-processor to process a Go program? Now the question arises – Isn’t cpp (the macro-processor installed on my machine) general enough to be used to process Go programs? The following text from the manual page doesn’t seem to agree:

“The C preprocessor is intended to be used only with C, C++, and Objective-C source code. In the past, it has been abused as a general text processor. It will choke on input which does not obey C’s lexical rules. For example, apostrophes will be interpreted as the beginning of character constants, and cause errors. Also, you cannot rely on it preserving characteristics of the input which are not significant to C-family languages. If a Makefile is preprocessed, all the hard tabs will be removed, and the Makefile will not work.”

Nevertheless, I am giving it a shot.

So, here is a small Go program that contains a macro :

/* @file : demo.go.p */
package main

import "fmt"

func main() {

        fmt.Println("hello!")
        fmt.Println("This is a sample program to demonstrate the use of",
                    "preprocessor in a Go program..")
#ifdef EXTRA
        fmt.Println("And this is the extra text printed only when EXTRA",
                    "is defined.")
#endif
}

Now, lets try to build/run this program with/without the EXTRA macro defined.

# with EXTRA undefined
$ cpp  -P -o demo.go demo.go.p | go run demo.go
hello!
This is a sample program to demonstrate the use of preprocessor in a Go program..

# with EXTRA defined
$ cpp -DEXTRA -P -o demo.go demo.go.p | go run demo.go
hello!
This is a sample program to demonstrate the use of preprocessor in a Go program..
And this is the extra text printed only when EXTRA is defined.

I am not sure if this idea is non-refutable, but so far it has managed to convince me.

Ajax with Golang

Lately, I thought of trying my hands on the classic Ajax alongside Go language. The requirement is to write a simple web server which sends ‘current timestamp’ to the requester every second. I have written a small program to do exactly the same. The Ajax part is taken care by jquery.

In order to see it in action, one needs to run it “go run tick-tock.go”. When the program is running, it essentially becomes a tiny web server listening to requests at port ‘9999’.

Now all you need to do is fire up a browser and raise a request to the tick-tock server: http://localhost:9999/time

Go is awesome. Isn’t it?

A barebone logger for Go

While working on a Go library, I was looking for an elegant solution for logging. After following many discussions on the forum, I came up with the following barebone which I think is decent performant and clean. Check it out!

package main

import (
        "flag"
        "log"
)

type Logger struct {
        log_func func(string, ...interface{})
}

func do_log(fmt string, args ...interface{}) {
        log.Printf(fmt, args...)
}

func do_not_log(fmt string, args ...interface{}) {
        // Do nothing..
}

func (logger *Logger) init_logger(enable_log bool) {
        if enable_log == true {
                logger.log_func = do_log
        } else {
                logger.log_func = do_not_log
        }
}

func main() {
        logger := new(Logger)

        // command line option
        enable_log := flag.Bool("enable_log", false, "Enable logging")
        flag.Parse()

        logger.init_logger(*enable_log)

        logger.log_func("%s", "log me!")
        logger.log_func("%s", "log me again..!")
}

Output:

$ ./logger
$ ./logger –enable_log
2013/01/28 11:41:19 log me!
2013/01/28 11:41:19 log me again..!
$

Go sorting, an example

I was recently trying to figure out a way to sort entries stored in a map using Golang. And then, I came across the “sort” package. It provides a Sort() function which can used to sort slices and user-defined collections.

func Sort(data Interface)

All you need is to define the functions listed under the Interface type.

Here is an example to demonstrate the same :

package main

import (
        "fmt"
        "sort"
)

type keys []int

/* Definitions for all 'Interface' functions. */
func (k keys) Len() int           { return len(k) }
func (k keys) Less(i, j int) bool { return k[i] < k[j] }
func (k keys) Swap(i, j int)      { k[i], k[j] = k[j], k[i] }

func main() {
        var (
                k keys
                i int
        )

        var varMap = map[int][]string{
                3: []string{"Harry"},
                1: []string{"Tom"},
                2: []string{"Dick"}}

        k = make(keys, 3)

        for key, _ := range varMap {
                k[i] = key
                i++
        }

        sort.Sort(k)

        for i = 0; i < len(k); i++ {
                fmt.Println(k[i], " : ", varMap[k[i]])
        }
}

Output :
>  go run sort.go 
1  :  [Tom]
2  :  [Dick]
3  :  [Harry]

Multiline statements in Golang

As Golang (unlike C, C++, Java, etc.) frees a programmer from using semi-colon ‘;’ to terminate a statement, one might find it problematic to write a miltiline statement in Go.

Lets start with a quote :

“Like C, Go’s formal grammar uses semicolons to terminate statements; unlike C,those semicolons do not appear in the source. Instead the lexer uses a simple rule to insert semicolons automatically as it scans, so the input text is mostly free of them. “

So, based on my experience so far, here is a trick that I would suggest, one can break a line after “an operator”.

        result := a +
                b +
                c
---
func add(a int,
        b int,
        c int) (result int) {
        result = a + b + c
        return
}

Now coming to strings, they can we written in two ways.

1) Interpreted string literal :

        str := "Lorem ipsum dolor sit amet, consectetur adipisicing" +
               " elit, sed do eiusmod tempor\nincididunt ut labore " +
               " et dolore magna aliqua. Ut enim ad minim veniam," +
               " quis nostrud\nexercitation ullamco laboris ..."

2) Raw string literal :
For multiline strings, back quote ‘`’ can also be used with a couple of restrictions :
a) Any character is legal except back quote.
b) Escape sequences won’t be interpreted.

        str := `Lorem ipsum dolor sit amet, consectetur adipisicing 
                elit, sed do eiusmod tempor incididunt ut labore et
                dolore magna aliqua. Ut enim ad minim veniam, quis
                nostrud exercitation ullamco laboris ...`

go go go…

Let’s go

Its been quite some time that I have been using Go, a power-packed programming language with a lot of unconventional constructs. Off the top of my head, I think of the following :

1. The magic behind swap a, b = b, a

func main() {
  a := 1
  b := 2
  c := 3
  d := 4

  d, c, b, a = a, b, c, d
  fmt.Println(a, b, c, d)
}

2. Returning multiple values

func main() {
  a, b, c, d := fn()
  fmt.Println(a, b, c, d)
}

func fn() (a int, b int, c int, d int) {
  return 1, 2, 3, 4
}

3. And, how about this..

func main() {
  串 := "世界您好!"
  fmt.Println(串)
}

Explore more here.