// Parent context cancels connecting/reconnecting altogether.
ctx, cancel := context.WithCancel(context.Background())
connectTimeout: 10 * time.Second,
connectTimeWait: 1 * time.Second,
nats.SetCustomDialer(cd),
nats.ReconnectWait(2 * time.Second),
nats.ReconnectHandler(func(c *nats.Conn) {
log.Println("Reconnected to", c.ConnectedUrl())
nats.DisconnectHandler(func(c *nats.Conn) {
log.Println("Disconnected from NATS")
nats.ClosedHandler(func(c *nats.Conn) {
log.Println("NATS connection is closed.")
nc, err = nats.Connect("127.0.0.1:4222", opts...)
WaitForEstablishedConnection:
// Wait for context to be canceled either by timeout
// or because of establishing a connection...
break WaitForEstablishedConnection
if nc == nil || !nc.IsConnected() {
log.Println("Connection not ready")
time.Sleep(200 * time.Millisecond)
break WaitForEstablishedConnection
if err := nc.Publish("hello", []byte("world")); err != nil {
time.Sleep(1 * time.Second)
log.Println("Published message")
time.Sleep(1 * time.Second)
// Disconnect and flush pending messages
if err := nc.Drain(); err != nil {
log.Println("Disconnected")