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 (

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

    go sleepFun(1, &wg)
    go sleepFun(3, &wg)
    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?.

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)
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.

(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
https fetch failed.
import "": http/https fetch: Get
l.v2?go-get=1: dial tcp 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
package unrecognized import path "

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

C:\Users\xiaona>set https_proxy=

C:\Users\xiaona>set http_proxy=

C:\Users\xiaona>go get -v
Parsing meta tags from (status code 200)

get "": found meta tag main.metaImport{Prefix:"
tih/pool.v2", VCS:"git", RepoRoot:""} at https://g (download) 

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


sudo dnf install elfutils-libelf-devel

(You can also read this post on