How to Build Golang Barcode QR Code Reader with Dynamsoft C++ Barcode SDK

This article aims to help Go developers to build barcode QR code reader applications with Dynamsoft C++ Barcode SDK on Windows and Linux. You will see how to interoperate Golang with C++ code using cgo, as well as how to deploy the application to Docker.


Creating a Go Module for Reading Barcode and QR Code

Dynamsoft C++ Barcode Reader SDK supports Windows(x86, x64), Linux(x64, ARM32, ARM64), and macOS(x64, ARM64). Here we only focus on Windows and Linux.

Initialize a Go Module Project

According to the Go documentation, we create a Go module named goBarcodeQrSDK in the terminal:

mkdir goBarcodeQrSDK
cd goBarcodeQrSDK
go mod init

The command creates a go.mod file which tracks your code’s dependencies.


go 1.19
  1. Create a lib folder.
  2. Copy shared libraries and header files of Dynamsoft C++ Barcode Reader SDK to the lib folder. Change DynamsoftBarcodeReaderx64.dll to DynamsoftBarcodeReader.dll to make the linking work on both Windows and Linux.
  3. In your text editor, create a reader.go file.
  4. Add cgo LDFLAGS and include C++ header files in the reader.go file.

     package goBarcodeQrSDK
     import (
       // #include <stdlib.h>
       // #include <lib/DynamsoftBarcodeReader.h>
       // #include <lib/DynamsoftCommon.h>
       // #include <lib/bridge.c>
       // #cgo LDFLAGS: -L ./lib -lDynamsoftBarcodeReader -Wl,-rpath=./lib

Calling Dynamsoft C++ Barcode Reader Functions in Go

To implement a barcode QR code reader with Dynamsoft Barcode SDK, we need to call the following functions:

  • DBR_InitLicense: Set a valid license key to activate the SDK.

      func InitLicense(license string) (int, string) {
        c_license := C.CString(license)
        errorBuffer := make([]byte, 256)
        ret := C.DBR_InitLicense(c_license, (*C.char)(unsafe.Pointer(&errorBuffer[0])),
        return int(ret), string(errorBuffer)
  • DBR_CreateInstance: Create an instance of the barcode reader.

      type BarcodeReader struct {
        handler unsafe.Pointer
      func CreateBarcodeReader() *BarcodeReader {
        handler := C.DBR_CreateInstance()
        if handler == nil {
          return nil
        return &BarcodeReader{handler: handler}
  • DBR_InitRuntimeSettingsWithFile: Load a parameter template file for customizing the barcode scanning algorithm.

      func (reader *BarcodeReader) LoadTemplateFile(params string) (int, string) {
        errorBuffer := make([]byte, 256)
        ret := C.DBR_InitRuntimeSettingsWithFile(reader.handler, C.CString(params), C.CM_OVERWRITE, (*C.char)(unsafe.Pointer(&errorBuffer[0])),
        return int(ret), string(errorBuffer)
  • DBR_DecodeFile: Read barcode QR code from an image file and return the results.

      func (reader *BarcodeReader) DecodeFile(filePath string) (int, []Barcode) {
        c_filePath := C.CString(filePath)
        template := C.CString("")
        var barcodes = []Barcode{}
        ret := C.DBR_DecodeFile(reader.handler, c_filePath, template)
        if ret != 0 {
          return int(ret), barcodes
        var resultArray *C.TextResultArray
        C.DBR_GetAllTextResults(reader.handler, &resultArray)
        if resultArray.resultsCount > 0 {
          for i := 0; i < int(resultArray.resultsCount); i++ {
            barcode := Barcode{}
            result := C.getTextResultPointer(resultArray,
            format := C.getFormatString(result)
            barcode.Format = C.GoString(format)
            text := C.getText(result)
            barcode.Text = C.GoString(text)
            localization := C.getLocalizationPointer(result)
            barcode.X1 = int(localization.x1)
            barcode.Y1 = int(localization.y1)
            barcode.X2 = int(localization.x2)
            barcode.Y2 = int(localization.y2)
            barcode.X3 = int(localization.x3)
            barcode.Y3 = int(localization.y3)
            barcode.X4 = int(localization.x4)
            barcode.Y4 = int(localization.y4)
            barcodes = append(barcodes, barcode)
        return int(ret), barcodes

    The Barcode struct is defined as follows:

      type Barcode struct {
        Text   string
        Format string
        X1     int
        Y1     int
        X2     int
        Y2     int
        X3     int
        Y3     int
        X4     int
        Y4     int

    To simplify data conversion between C++ and Go, we implement some C++ pointer operations in the bridge.c file.

      #include <stdio.h>
      #include <stdlib.h>
      #include "DynamsoftBarcodeReader.h"
      TextResult *getTextResultPointer(TextResultArray *resultArray, int offset) {
          return resultArray->results[offset];
      LocalizationResult *getLocalizationPointer(TextResult *result) {
          return result->localizationResult;
      const char *getText(TextResult *result) {
          return result->barcodeText;
      const char *getFormatString(TextResult *result) {
          return result->barcodeFormatString;

Before using these Go functions, you need to test them in a _test.go file.

Test the Go Module

We create a goBarcodeQrSDK_test.go file to test the Go module.

package goBarcodeQrSDK

import (

func TestInitLicense(t *testing.T) {
	ret, _ := InitLicense("DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==")
	if ret != 0 {
		t.Fatalf(`initLicense("") = %d`, ret)

func TestCreateBarcodeReader(t *testing.T) {
	obj := CreateBarcodeReader()
	if obj == nil {
		t.Fatalf(`Failed to create instance`)

func TestLoadTemplateFile(t *testing.T) {
	obj := CreateBarcodeReader()
	ret, _ := obj.LoadTemplateFile("template.json")
	if ret != 0 {
		t.Fatalf(`LoadTemplateFile() = %d`, ret)

func TestDecodeFile(t *testing.T) {
	obj := CreateBarcodeReader()
	ret, _ := obj.DecodeFile("test.png")
	if ret != 0 {
		t.Fatalf(`DecodeFile() = %d`, ret)

Run go test.

Go test

If the test is successful, you can use the Go module in your project.

Implementing Golang Barcode QR Code Reader

Create a new module in another directory and add the goBarcodeQrSDK module as a dependency locally.

mkdir example
go mod init
go mod edit -replace  
go mod tidy

The go.mod file should look like this:


go 1.19

replace => ../

require v0.0.0-00010101000000-000000000000

To use a published module, omit the replace directive and use a require directive with a tagged version number at the end.

- replace => ../
+ require v1.0.3

Create a test.go file and add the following code:

package main

import (


func main() {
	filename := "test.png"
	license := "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="
	template := "template.json"
	ret, errMsg := goBarcodeQrSDK.InitLicense(license)
	if ret != 0 {
		fmt.Println(`initLicense(): `, ret)
	obj := goBarcodeQrSDK.CreateBarcodeReader()
	ret, errMsg = obj.LoadTemplateFile(template)
	if ret != 0 {
		fmt.Println(`LoadTemplateFile(): `, ret)
	startTime := time.Now()
	ret, barcodes := obj.DecodeFile(filename)
	elapsed := time.Since(startTime)
	fmt.Println("DecodeFile() time cost: ", elapsed)

	if ret != 0 {
		fmt.Printf(`DecodeFile() = %d`, ret)

	for i := 0; i < len(barcodes); i++ {
		barcode := barcodes[i]

We use Windows and WSL to test the barcode QR code reader for Windows and Linux respectively.

go run .

Link cgo on Windows and Linux

As you can see, there is no error when running on Windows. However, when running on Linux, the dependent shared library cannot be found. Because the rpath is set to the lib directory, to find the shared library, we can build the executable file to the directory where the lib folder is located.

go build -o ../reader
cd ..
./reader test.png

Run cgo on Linux

Deploying Golang Barcode QR Reader to Docker

  1. Create a Dockerfile file in the root directory of the project:

     FROM golang:1.19
     COPY . /usr/src/myapp
     WORKDIR /usr/src/myapp/example
     COPY ../lib/ /usr/lib/x86_64-linux-gnu/
     RUN cp test.png /usr/local/bin/
     RUN cp template.json /usr/local/bin/
     RUN go mod download
     RUN go build -v -o /usr/local/bin/reader
     CMD [ "reader"]
  2. Build the Docker image:

     docker build -t golang-barcode-qr-reader .
  3. Read barcode and QR code from a local image file:

     docker run -it --rm -v <image-folder>:/app golang-barcode-qr-reader reader /app/<image-file> <license-key> <template-file>

    Golang barcode QR code reader

Published Docker Image

docker run -it --rm -v <image-folder>:/app yushulx/golang-barcode-qr-reader:latest reader /app/<image-file> <license-key> <template-file>

Source Code