Use sync.WaitGroup in Golang

sync.WaitGroup provides a goroutine synchronization mechanism in Golang, and is used for waiting for a collection of goroutines to finish.

The sync.WaitGroup structure is like this:

type WaitGroup struct {
    m       Mutex
    counter int32
    waiters int32
    sema    *uint32
}

There is a counter member which indicates how many goroutines need to be waited are living now.

sync.WaitGroup also provides 3 methods: Add, Done and Wait. Add method is used to identify how many goroutines need to be waited. When a goroutine exits, it must call Done. The main goroutine blocks on Wait, Once the counter becomes 0, the Wait will return, and main goroutine can continue to run.

Let’s see an example:

package main

import (
    "sync"
    "time"
    "fmt"
)

func sleepFun(sec time.Duration, wg *sync.WaitGroup) {
    defer wg.Done()
    time.Sleep(sec * time.Second)
    fmt.Println("goroutine exit")
}

func main() {
    var wg sync.WaitGroup

    wg.Add(2)
    go sleepFun(1, &wg)
    go sleepFun(3, &wg)
    wg.Wait()
    fmt.Println("Main goroutine exit")

}

Because the main goroutine need to wait 2 goroutines, so the argument for wg.Add is 2. The execution result is like this:

goroutine exit
goroutine exit
Main goroutine exit

Please notice, the Add must go ahead of Done. For detailed inforamtion, you can refer this link: Example for sync.WaitGroup correct?.

P.S., the full code is here.

Build Luajit notice

When uploading Luajit (for example, v2.0.4) from Windows to Linux, you may get the following compile error:

In file included from lj_ffrecord.c:859:0:
lj_recdef.h:224:1: error: ‘recff_rawlen’ undeclared here (not in a function)
 recff_rawlen,
 ^
Makefile:645: recipe for target 'lj_ffrecord.o' failed

The root cause is in src/host/buildvm_lib.c:

void emit_lib(BuildCtx *ctx)
{

    ......
    int ok = 1;
    if (!strcmp(buf, "#if LJ_52\n"))
      ok = LJ_52;
    else if (!strcmp(buf, "#if LJ_HASJIT\n"))
      ok = LJ_HASJIT;
    else if (!strcmp(buf, "#if LJ_HASFFI\n"))
      ok = LJ_HASFFI;
    ......

}

Because in Windows, the EOL(End-of-Line) should be “\r\n“, so the !strcmp(buf, "#if LJ_52\n") will return false (!strcmp(buf, "#if LJ_52\r\n") will return true). The modify method is using the dos2unix tool to convert the whole folder:

# cd LuaJIT-2.0.4
# find . -type f -print0 | xargs -0 dos2unix

Then compile will be OK.

Reference:
(1) The EOL difference in Windows and UNIX may generate compile error;
(2) How can I run dos2unix on an entire directory?.

Set proxy when executing “go get” command

In Windows, if you have configured proxy for connecting Internet, then executing “go get” command may get error, like this:

C:\Users\xiaona>go get -v gopkg.in/fatih/pool.v2
Fetching https://gopkg.in/fatih/pool.v2?go-get=1
https fetch failed.
Fetching http://gopkg.in/fatih/pool.v2?go-get=1
import "gopkg.in/fatih/pool.v2": http/https fetch: Get http://gopkg.in/fatih/poo
l.v2?go-get=1: dial tcp 107.178.216.236:80: ConnectEx tcp: A connection attempt
failed because the connected party did not properly respond after a period of ti
me, or established connection failed because connected host has failed to respon
d.
package gopkg.in/fatih/pool.v2: unrecognized import path "gopkg.in/fatih/pool.v2
"

The solution is set “http_proxy” and/or “https_proxy” environment variables according to your reality need:

C:\Users\xiaona>set https_proxy=https://web-proxy.corp.xx.com:8080/

C:\Users\xiaona>set http_proxy=https://web-proxy.corp.xx.com:8080/

C:\Users\xiaona>go get -v gopkg.in/fatih/pool.v2
Fetching https://gopkg.in/fatih/pool.v2?go-get=1
Parsing meta tags from https://gopkg.in/fatih/pool.v2?go-get=1 (status code 200)

get "gopkg.in/fatih/pool.v2": found meta tag main.metaImport{Prefix:"gopkg.in/fa
tih/pool.v2", VCS:"git", RepoRoot:"https://gopkg.in/fatih/pool.v2"} at https://g
opkg.in/fatih/pool.v2?go-get=1
gopkg.in/fatih/pool.v2 (download)
gopkg.in/fatih/pool.v2 

All is OK now!

Fix compile error: “fatal error: ‘libelf.h’ file not found”

Recently, when I try to build an open source project, I meet the following compile error:

fatal error: 'libelf.h' file not found
#include <libelf.h>
     ^
1 error generated.

The solution is installing elfutils-libelf-devel package:

sudo yum install elfutils-libelf-devel

Or:

sudo dnf install elfutils-libelf-devel

(You can also read this post on itechlounge.net)