Skip to content

Commit dbdf3b2

Browse files
committed
Convert samples to use defer instead of just suggesting it
1 parent 46f64a2 commit dbdf3b2

File tree

10 files changed

+224
-200
lines changed

10 files changed

+224
-200
lines changed

samples/README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Where needed for the sample programs:
1313

1414
* the default queue manager is "QM1"
1515
* the default queue is "DEV.QUEUE.1"
16-
* the default topic is "GO.TEST.TOPIC"
16+
* the default topic is "DEV.BASE.TOPIC"
1717

1818
## Description of sample programs
1919
Current samples in this directory include
@@ -25,10 +25,11 @@ Current samples in this directory include
2525
* amqsconn.go: How to programmatically connect as an MQ client to a remote queue manager.
2626
Allow use of a userid/password for authentication. There are no default values for this sample.
2727
* amqsprop.go: Set and extract message properties
28-
* amqsinq.go : Demonstrate the new InqMap API for inquiring object attributes
28+
* amqsinq.go : Demonstrate the new InqMap API for inquiring about object attributes
29+
* amqsset.go : Demonstrate how to set attributes of an MQ object using the MQSET verb
2930

3031
Some trivial scripts run the sample programs in matching pairs:
31-
* putget.sh : Run amqsput and then use the generated MsgId to get the same message
32+
* putget.sh : Run amqsput and then use the generated MsgId to get the same message with amqsget
3233
* pubsub.sh : Start amqssub and then run the amqspub program immediately
3334

3435
The `mqitest` sample program in its own subdirectory is a more general demonstration
@@ -55,9 +56,9 @@ there is something waiting to receive the publications when they are made. The
5556

5657
## More information
5758
Comments in the programs explain what they are doing. For more detailed information about the
58-
MQ API, the functions, structures and constants, see the
59-
[MQ Knowledge Center](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.ref.dev.doc/q089590_.htm)
59+
MQ API, the functions, structures, and constants, see the
60+
[MQ Knowledge Center](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.ref.dev.doc/q089590_.htm).
6061

61-
You can also find general MQ application development advice [here](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.dev.doc/q022830_.htm)
62+
You can also find general MQ application development advice [here](https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.dev.doc/q022830_.htm).
6263
Information about development for procedural programming languages such as C in that
63-
site is most relevant for the interface exported by this Go package.
64+
documentation is most relevant for the interface exported by this Go package.

samples/amqsget.go

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,17 @@ var qMgrObject ibmmq.MQObject
4848
var qObject ibmmq.MQObject
4949

5050
func main() {
51+
os.Exit(mainWithRc())
52+
}
53+
54+
// The real main function is here to set a return code.
55+
func mainWithRc() int {
5156
var msgId string
5257

5358
// The default queue manager and queue to be used. These can be overridden on command line.
5459
qMgrName := "QM1"
5560
qName := "DEV.QUEUE.1"
5661

57-
qMgrConnected := false
58-
qOpened := false
59-
6062
fmt.Println("Sample AMQSGET.GO start")
6163

6264
// Get the queue and queue manager names from command line for overriding
@@ -82,8 +84,8 @@ func main() {
8284
if err != nil {
8385
fmt.Println(err)
8486
} else {
85-
qMgrConnected = true
8687
fmt.Printf("Connected to queue manager %s\n", qMgrName)
88+
defer disc(qMgrObject)
8789
}
8890

8991
// Open of the queue
@@ -93,7 +95,7 @@ func main() {
9395

9496
// We have to say how we are going to use this queue. In this case, to GET
9597
// messages. That is done in the openOptions parameter.
96-
openOptions := ibmmq.MQOO_INPUT_EXCLUSIVE + ibmmq.MQOO_FAIL_IF_QUIESCING
98+
openOptions := ibmmq.MQOO_INPUT_EXCLUSIVE
9799

98100
// Opening a QUEUE (rather than a Topic or other object type) and give the name
99101
mqod.ObjectType = ibmmq.MQOT_Q
@@ -103,8 +105,8 @@ func main() {
103105
if err != nil {
104106
fmt.Println(err)
105107
} else {
106-
qOpened = true
107108
fmt.Println("Opened queue", qObject.Name)
109+
defer close(qObject)
108110
}
109111
}
110112

@@ -119,9 +121,8 @@ func main() {
119121

120122
// The default options are OK, but it's always
121123
// a good idea to be explicit about transactional boundaries as
122-
// not all platforms behave the same way. It's also good practice to
123-
// set the FAIL_IF_QUIESCING flag on all verbs.
124-
gmo.Options = ibmmq.MQGMO_NO_SYNCPOINT | ibmmq.MQGMO_FAIL_IF_QUIESCING
124+
// not all platforms behave the same way.
125+
gmo.Options = ibmmq.MQGMO_NO_SYNCPOINT
125126

126127
// Set options to wait for a maximum of 3 seconds for any new message to arrive
127128
gmo.Options |= ibmmq.MQGMO_WAIT
@@ -162,32 +163,33 @@ func main() {
162163
}
163164
}
164165

165-
// The usual tidy up at the end of a program is for queues to be closed,
166-
// queue manager connections to be disconnected etc.
167-
// In a larger Go program, we might move this to a defer() section to ensure
168-
// it gets done regardless of other flows through the program.
169-
170-
// Close the queue if it was opened
171-
if qOpened {
172-
err = qObject.Close(0)
173-
if err != nil {
174-
fmt.Println(err)
175-
} else {
176-
fmt.Println("Closed queue")
177-
}
166+
// Exit with any return code extracted from the failing MQI call.
167+
// Deferred disconnect will happen after the return
168+
mqret := 0
169+
if err != nil {
170+
mqret = int((err.(*ibmmq.MQReturn)).MQCC)
178171
}
172+
return mqret
173+
}
179174

180-
// Disconnect from the queue manager
181-
if qMgrConnected {
182-
err = qMgrObject.Disc()
183-
fmt.Printf("Disconnected from queue manager %s\n", qMgrName)
175+
// Disconnect from the queue manager
176+
func disc(qMgrObject ibmmq.MQQueueManager) error {
177+
err := qMgrObject.Disc()
178+
if err == nil {
179+
fmt.Printf("Disconnected from queue manager %s\n", qMgrObject.Name)
180+
} else {
181+
fmt.Println(err)
184182
}
183+
return err
184+
}
185185

186-
// Exit with any return code extracted from the failing MQI call.
186+
// Close the queue if it was opened
187+
func close(object ibmmq.MQObject) error {
188+
err := object.Close(0)
187189
if err == nil {
188-
os.Exit(0)
190+
fmt.Println("Closed queue")
189191
} else {
190-
mqret := err.(*ibmmq.MQReturn)
191-
os.Exit((int)(mqret.MQCC))
192+
fmt.Println(err)
192193
}
194+
return err
193195
}

samples/amqsinq.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ var qMgrObject ibmmq.MQObject
3939
var object ibmmq.MQObject
4040

4141
/*
42-
* This is an example of how to call MQINQ with the new "map" format for
42+
* This is an example of how to call MQINQ with a "map" format for
4343
* responses
4444
*/
4545
func inquire(obj ibmmq.MQObject, selectors []int32) {
@@ -60,15 +60,19 @@ func inquire(obj ibmmq.MQObject, selectors []int32) {
6060
}
6161
}
6262

63+
// Main function that simply calls a subfunction to ensure defer routines are called before os.Exit happens
6364
func main() {
65+
os.Exit(mainWithRc())
66+
}
67+
68+
// The real main function is here to set a return code.
69+
func mainWithRc() int {
6470
var selectors []int32
6571
// The default queue manager, a queue and a namelist to be used. These can be overridden on command line.
6672
qMgrName := "QM1"
6773
qName := "DEV.QUEUE.1"
6874
nlName := "SYSTEM.DEFAULT.NAMELIST"
6975

70-
qMgrConnected := false
71-
7276
fmt.Println("Sample AMQSINQ.GO start")
7377

7478
// Get the object names from command line for overriding
@@ -91,8 +95,8 @@ func main() {
9195
if err != nil {
9296
fmt.Println(err)
9397
} else {
94-
qMgrConnected = true
9598
fmt.Printf("Connected to queue manager %s\n", qMgrName)
99+
defer disc(qMgrObject)
96100
}
97101

98102
// Open an object
@@ -101,7 +105,7 @@ func main() {
101105
mqod := ibmmq.NewMQOD()
102106

103107
// We have to say how we are going to use this object.
104-
openOptions := ibmmq.MQOO_FAIL_IF_QUIESCING + ibmmq.MQOO_INQUIRE
108+
openOptions := ibmmq.MQOO_INQUIRE
105109
mqod.ObjectType = ibmmq.MQOT_Q_MGR
106110
// Do not need the qmgr name when opening it
107111

@@ -124,7 +128,7 @@ func main() {
124128
mqod := ibmmq.NewMQOD()
125129

126130
// We have to say how we are going to use this object.
127-
openOptions := ibmmq.MQOO_FAIL_IF_QUIESCING + ibmmq.MQOO_INQUIRE
131+
openOptions := ibmmq.MQOO_INQUIRE
128132
mqod.ObjectType = ibmmq.MQOT_Q
129133
mqod.ObjectName = qName
130134

@@ -149,7 +153,7 @@ func main() {
149153
mqod := ibmmq.NewMQOD()
150154

151155
// We have to say how we are going to use this object.
152-
openOptions := ibmmq.MQOO_FAIL_IF_QUIESCING + ibmmq.MQOO_INQUIRE
156+
openOptions := ibmmq.MQOO_INQUIRE
153157
mqod.ObjectType = ibmmq.MQOT_NAMELIST
154158
mqod.ObjectName = nlName
155159

@@ -166,17 +170,22 @@ func main() {
166170
}
167171
}
168172

169-
// Disconnect from the queue manager
170-
if qMgrConnected {
171-
err = qMgrObject.Disc()
172-
fmt.Printf("Disconnected from queue manager %s\n", qMgrName)
173+
// Exit with any return code extracted from the failing MQI call.
174+
// Deferred disconnect will happen after the return
175+
mqret := 0
176+
if err != nil {
177+
mqret = int((err.(*ibmmq.MQReturn)).MQCC)
173178
}
179+
return mqret
180+
}
174181

175-
// Exit with any return code extracted from the failing MQI call.
182+
// Disconnect from the queue manager
183+
func disc(qMgrObject ibmmq.MQQueueManager) error {
184+
err := qMgrObject.Disc()
176185
if err == nil {
177-
os.Exit(0)
186+
fmt.Printf("Disconnected from queue manager %s\n", qMgrObject.Name)
178187
} else {
179-
mqret := err.(*ibmmq.MQReturn)
180-
os.Exit((int)(mqret.MQCC))
188+
fmt.Println(err)
181189
}
190+
return err
182191
}

samples/amqsprop.go

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,17 @@ func printProperties(getMsgHandle ibmmq.MQMessageHandle) {
176176
}
177177

178178
func main() {
179+
os.Exit(mainWithRc())
180+
}
181+
182+
// The real main function is here to set a return code.
183+
func mainWithRc() int {
179184
var putmqmd *ibmmq.MQMD
180185

181186
// The default queue manager and queue to be used. These can be overridden on command line.
182187
qMgrName := "QM1"
183188
qName := "DEV.QUEUE.1"
184189

185-
qMgrConnected := false
186-
qOpened := false
187-
188190
fmt.Println("Sample AMQSPROP.GO start")
189191

190192
// Get the queue and queue manager names from command line for overriding
@@ -205,8 +207,8 @@ func main() {
205207
if err != nil {
206208
fmt.Println(err)
207209
} else {
208-
qMgrConnected = true
209210
fmt.Printf("Connected to queue manager %s\n", qMgrName)
211+
defer disc(qMgrObject)
210212
}
211213

212214
// Open of the queue
@@ -216,7 +218,7 @@ func main() {
216218

217219
// We have to say how we are going to use this queue. In this case, to PUT and GET
218220
// messages. That is done in the openOptions parameter.
219-
openOptions := ibmmq.MQOO_OUTPUT + ibmmq.MQOO_FAIL_IF_QUIESCING + ibmmq.MQOO_INPUT_AS_Q_DEF
221+
openOptions := ibmmq.MQOO_OUTPUT | ibmmq.MQOO_INPUT_AS_Q_DEF
220222

221223
// Opening a QUEUE (rather than a Topic or other object type) and give the name
222224
mqod.ObjectType = ibmmq.MQOT_Q
@@ -226,8 +228,8 @@ func main() {
226228
if err != nil {
227229
fmt.Println(err)
228230
} else {
229-
qOpened = true
230231
fmt.Println("Opened queue", qObject.Name)
232+
defer close(qObject)
231233
}
232234
}
233235

@@ -259,7 +261,7 @@ func main() {
259261
putmqmd = ibmmq.NewMQMD()
260262
pmo := ibmmq.NewMQPMO()
261263

262-
pmo.Options = ibmmq.MQPMO_NO_SYNCPOINT | ibmmq.MQPMO_FAIL_IF_QUIESCING
264+
pmo.Options = ibmmq.MQPMO_NO_SYNCPOINT
263265

264266
// Set the handle that holds the properties
265267
pmo.OriginalMsgHandle = putMsgHandle
@@ -281,7 +283,7 @@ func main() {
281283
getmqmd := ibmmq.NewMQMD()
282284
gmo := ibmmq.NewMQGMO()
283285

284-
gmo.Options = ibmmq.MQGMO_NO_SYNCPOINT | ibmmq.MQGMO_FAIL_IF_QUIESCING
286+
gmo.Options = ibmmq.MQGMO_NO_SYNCPOINT
285287

286288
// Set options to not wait - we know the message is there since we just put it
287289
gmo.Options |= ibmmq.MQGMO_NO_WAIT
@@ -312,37 +314,33 @@ func main() {
312314
}
313315
}
314316

315-
// The usual tidy up at the end of a program is for queues to be closed,
316-
// queue manager connections to be disconnected etc.
317-
// In a larger Go program, we might move this to a defer() section to ensure
318-
// it gets done regardless of other flows through the program.
319-
320-
// Close the queue if it was opened
321-
if qOpened {
322-
err = qObject.Close(0)
323-
if err != nil {
324-
fmt.Println(err)
325-
} else {
326-
fmt.Println("Closed queue")
327-
}
328-
329-
// Delete any created message handles
330-
dmho := ibmmq.NewMQDMHO()
331-
getMsgHandle.DltMH(dmho)
332-
putMsgHandle.DltMH(dmho)
317+
// Exit with any return code extracted from the failing MQI call.
318+
// Deferred disconnect will happen after the return
319+
mqret := 0
320+
if err != nil {
321+
mqret = int((err.(*ibmmq.MQReturn)).MQCC)
333322
}
323+
return mqret
324+
}
334325

335-
// Disconnect from the queue manager
336-
if qMgrConnected {
337-
err = qMgrObject.Disc()
338-
fmt.Printf("Disconnected from queue manager %s\n", qMgrName)
326+
// Disconnect from the queue manager
327+
func disc(qMgrObject ibmmq.MQQueueManager) error {
328+
err := qMgrObject.Disc()
329+
if err == nil {
330+
fmt.Printf("Disconnected from queue manager %s\n", qMgrObject.Name)
331+
} else {
332+
fmt.Println(err)
339333
}
334+
return err
335+
}
340336

341-
// Exit with any return code extracted from the failing MQI call.
337+
// Close the queue if it was opened
338+
func close(object ibmmq.MQObject) error {
339+
err := object.Close(0)
342340
if err == nil {
343-
os.Exit(0)
341+
fmt.Println("Closed queue")
344342
} else {
345-
mqret := err.(*ibmmq.MQReturn)
346-
os.Exit((int)(mqret.MQCC))
343+
fmt.Println(err)
347344
}
345+
return err
348346
}

0 commit comments

Comments
 (0)