"Life is all about sharing. If we are good at something, pass it on." - Mary Berry

How to add full text search to my static website?

2020-12-30

After building the website, I want to add search function. There are some ways to do it:

So, is there any search engine written in Go?

Bleve has more star and be maintained more often than riot, I would like to give it a try first.

Backend

Looking at the documentation, there are three steps to add search to your website:

Read More...


How to perform integration testing in Go?

2020-09-29

Integration testing can be triggered by using Drone downstream plugin:

 1steps:
 2- name: trigger
 3  image: plugins/downstream:linux-amd64
 4  settings:
 5    params:
 6    - COMMIT_BRANCH=${DRONE_COMMIT_BRANCH}
 7    repositories:
 8    - repo/integration-test@${DRONE_COMMIT_BRANCH}
 9    server: https://drone.example.com
10    token:
11      from_secret: drone_token

It can be separated with unit tests by using build tags:

1// +build integration
2
3package webserver_test

Then we can write code to perform integration test as usual.

Read More...


Save draft mail in Zimbra web client using ChromeDP

2020-07-03

As an engineer, I want to automate everything as much as possible. This CLI tool is created to save a draft mail in Zimbra web client.

Read config file:

 1func initConfig() {
 2	if cfgFile != "" {
 3		// Use config file from the flag.
 4		viper.SetConfigFile(cfgFile)
 5	} else {
 6		// Find home directory.
 7		home, err := homedir.Dir()
 8		if err != nil {
 9			fmt.Println(err)
10			os.Exit(1)
11		}
12
13		// Search config in home directory with name ".zwc" (without extension).
14		viper.AddConfigPath(home)
15		viper.SetConfigName(".zwc")
16	}
17
18	viper.AutomaticEnv() // read in environment variables that match
19
20	// If a config file is found, read it in.
21	if err := viper.ReadInConfig(); err != nil {
22		log.Fatal(err)
23	}
24
25	fmt.Println("Using config file:", viper.ConfigFileUsed())
26}

Read More...


Google Calendar CLI

2020-04-13

Our company allows us to work from home some days a week. To do that, we have to create an event in Google Calendar.

I created this tool to run it from CLI.

First, take a look at this quickstart.

Create initical code by running:

1$ cobra init
2
3$ tree -L 2
4.
5├── LICENSE
6├── cmd
7│   └── root.go
8├── main.go

Create event command:

 1$ cobra add event
 2$ cobra add insert -p 'eventCmd'
 3
 4$ tree -L 2
 5.
 6├── LICENSE
 7├── cmd
 8│   ├── event.go
 9│   ├── event_insert.go
10│   └── root.go
11├── main.go

Read More...


go/packages.Load: no packages found

2019-10-22

I have a mono-repo, structure like this:

1repo
2├── service1
3├── service2
4├── go.mod

I often open the root folder from the command line by using code .. After that I open a file in service1, and cannot go to definition. Here’s the logs from gopls:

1[Info  - 5:49:28 AM] 2019/10/22 05:49:28 20.675656ms for GOROOT=/usr/local/Cellar/go/1.13/libexec GOPATH=/Users/quanta/go GO111MODULE=auto PWD=/Users/quanta/go/src/github.com/owner/repo go "list" "-e" "-json" "-compiled=true" "-test=true" "-export=false" "-deps=true" "-find=false" "--" "/Users/quanta/go/src/github.com/owner/repo/a/b/c", stderr: <<go: directory a/b/c is outside main module
2>>
3
4[Error - 5:49:32 AM] Request textDocument/definition failed.
5  Message: go/packages.Load: no packages found for /Users/quanta/go/src/github.com/owner/repo/a/b/c/file.go
6  Code: 0 

Read More...


database/sql: never ignore errors

2019-10-16

I’m reading Building RESTful Web Services with Go. And in chapter 4, there is an example to play around with SQLite:

 1db, err := sql.Open("sqlite3", "./books.db")
 2if err != nil {
 3	log.Fatal(err)
 4}
 5
 6statement, err := db.Prepare("CREATE TABLE IF NOT EXISTS books (id INTERGER PRIMARY KEY, isbn INTEGER, author VARCHAR(64), name VARCHAR(64) NULL)")
 7if err != nil {
 8	log.Fatal(err)
 9} else {
10	log.Println("Created table books successfully")
11}
12statement.Exec()
13
14statement, err = db.Prepare("INSERT INTO books (name, author, isbn) VALUES (?, ?, ?)")
15if err != nil {
16	log.Fatal(err)
17}
18statement.Exec("Life is a joke", "The Javna brothers", 123456789)
19log.Println("Inserted first book into db")
20rows, err := db.Query("SELECT id, name, author FROM books")
21var tempBook Book
22for rows.Next() {
23	rows.Scan(&tempBook.id, &tempBook.name, &tempBook.author)
24	log.Printf("ID: %d, Book: %s, Author: %s\n", tempBook.id, tempBook.name, tempBook.author)
25}

Read More...


How do I build this blog?

2019-10-11

Raspberry Pi 4

Recently, I decided to find a new job as a Golang developer. So, I updated my resume, sent to my friends to ask for review. Then I submitted it enclosed herewith a cover letter to recruiters. Some didn’t reply, and the other replied with a message like this “You are so good, but I’m so sorry…”.

What is the reason?

As you can see in my resume, I started my career as a .NET developer, then my passionate on Linux and open source lead me to a different direction: system administrator. I dedicated myself to this role for a significant period before transitioning back to work as a Golang developer 2 years ago.

Read More...


Auto reload your Go webserver with Gulp

2019-09-20

When you developp a webserver with Go, you must compile each time you do an update in your code. Well.. this is redundant. With Gulp you can automatize this task… Indeed, when a go file is modified, a task compile the application in the “bin” folder (“gopath/bin”) then another launch the executable (the webserver).

https://medium.com/@etiennerouzeaud/autoreload-your-go-webserver-with-gulp-ee5e231d133d

 1const gulp     = require('gulp'),
 2      util     = require('gulp-util'),
 3      notifier = require('node-notifier'),
 4      child    = require('child_process'),
 5      os       = require('os'),
 6      path     = require('path');
 7
 8var server = 'null'
 9
10function build() {
11    var build = child.spawn('go', ['install']);
12
13    build.stdout.on('data', (data) => {
14        console.log(`stdout: ${data}`);
15    });
16
17    build.stderr.on('data', (data) => {
18        console.error(`stderr: ${data}`);
19    });
20
21    return build;
22}
23
24function spawn(done) {
25    if (server && server != 'null') {
26        server.kill();
27    }
28
29    var path_folder = process.cwd().split(path.sep)
30    var length = path_folder.length
31    var app = path_folder[length - parseInt(1)];
32
33    if (os.platform() == 'win32') {
34        server = child.spawn(app + '.exe')
35    } else {
36        server = child.spawn(app)
37    }
38
39    server.stdout.on('data', (data) => {
40        console.log(`stdout: ${data}`);
41    });
42
43    server.stderr.on('data', (data) => {
44        console.log(`stderr: ${data}`);
45    });
46
47    done();
48}
49
50const serve = gulp.series(build, spawn)
51function watch(done) {
52    gulp.watch(['*.go', '**/*.go'], serve);
53    done();
54}
55
56exports.serve = serve
57exports.watch = watch
58exports.default = gulp.parallel(serve, watch)

Read More...