Calling IBM MQ from Go applications

Go is a language created at Google and made available as an open-source project. Although originally designed for building reliable large-scale distributed applications, its general-purpose nature and the collection of interface packages provided in the core language and from other projects has helped it become popular for a much broader set of applications.

In this article, I’ll show how Go programs can make use of IBM MQ, permitting Go applications access to the services provided by MQ-enabled applications, with an API that is more natural for Go programmers than some of the elements in MQ’s C API.

How Go links with C

One of the features of Go is that is has a built-in mechanism for working with C APIs. The cgo tooling makes it possible to directly invoke C functions and refer to C datatypes from within a Go program. This means that the C definition of the MQI can be accessed reasonably directly by importing MQ’s header files and referring to the functions, constants and structures defined in them. The cgo processing pulls in the header files and links with the C libraries at build time so that the Go program can then connect to a queue manager.

What has been done

In the mq-golang Github repository you can find source code for a Go package, ibmmq, that encapsulates the C MQI. There is code to wrap the function calls, and to convert commonly-used structures between C and Go formats. A simple test program, mqitest.go, demonstrates how the package is used. The test program can put and get messages, and subscribe to a topic, retrieving publications from a managed queue.

Design

The interface exposed from the ibmmq package is similar to the C MQI, but with adaptations to make it a bit more familiar for Go programmers. For example, datatypes such as MQCHAR48 which might be used to hold the name of a queue within a C structure has been changed to a string in a Go structure. The C MQI byte array fields such as the MQBYTE24 used for message ids are represented by the Go []byte type. During initialisation of a Go structure in the NewMQxxx functions, these arrays are created with the correct length. Go application developers do not need to worry about conversion into and out of the low-level C formats and can use familiar types.

The MQI functions themselves now have return values that are directly assigned. All the verbs actually return at least two responses – a structure containing MQCC/MQRC values, and an error type that can be quickly tested and printed to give a readable form of the MQCC/MQRC codes. Most of the functions are callable only from the relevant datatype, rather like Java methods. The traditional hConn and hObj values are hidden away inside the Go structures and do not need to be directly referenced in your applications.

From the sample mqitest.go program it should be obvious how other MQ programs could readily be converted to use this Go variation of the MQI. This extract from the sample shows how a message is put:

putmqmd := ibmmq.NewMQMD()
pmo := ibmmq.NewMQPMO()

pmo.Options = C.MQPMO_SYNCPOINT|C.MQPMO_NEW_MSG_ID| C.MQPMO_NEW_CORREL_ID

putmqmd.Format = "MQSTR"
msgData := "Hello from Go"

buffer := []byte(msgData)

mqreturn, err = qObject.Put(putmqmd, pmo, buffer)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Put message to", qObject.Name)
}

Anyone familiar with the MQI will recognise the use of structures, the option-setting constants and the references to open objects.

Possible extensions

Not all of the MQI has been handled in this package and some of the missing pieces could be interesting to add later, based on user feedback.

  • Not all of the verbs are exposed, including the message property manipulators.
  • One particular missing verb is the callback MQCB. That might be able to drive Go channels for better asynchronous processing, but wasn’t necessary for demonstrating the core MQ function.
  • There is no handling of message header structures such as the MQDLH or MQRFH2.
  • The cgo directives assume use of a standard installation on a Linux platform; using other platforms or directories would require changes to values like CFLAGS and LDFLAGS.

Feedback

I would welcome feedback, either here or in the GitHub issue tracker, whether bugs or thoughts on the value or possible API variations.

Conclusion

From this, we can see how Go applications can make use of MQ services and exchange messages with any other MQ application. Go developers can use the MQI in a more natural fashion. Also we now know how those other MQ applications can exploit services provided by Go packages through the exchange of messages.

Update (October 2016)

Since its first release, there have been a number of updates to the MQ package, including support for MQCONNX and client connectivity. The example code shown in this blog entry has been modified to match simplifcations to the original API.

The most recent update sent to the GitHub repository includes a lot more information and help for getting started with the package, including assistance with building and running the code on Windows.

Update (November 2019)

Since this post was originally written, there have been substantial extensions to the MQI Go bindings. All of the MQI verbs are now mapped and some made much simpler to use. There are also many sample programs to demonstrate how to use the library. And sample scripts to make it simpler to build programs in containers. Please take a look at the README and CHANGELOG to get more information.

This post was last updated on November 19th, 2019 at 05:51 pm

Leave a Reply

Your email address will not be published. Required fields are marked *