Пример использования pub-sub. Golang

Publisher

package main
 
import (
	"log"
	"strconv"
	"time"
 
	nats "github.com/nats-io/nats.go"
)
 
func main() {
	nc, err := nats.Connect("nats://127.0.0.1:4222", nats.UserInfo("maksim", "pass"))
	if err != nil {
		log.Fatal(err)
	}
 
	defer nc.Close()
 
	i := 0
	for {
		i++
		err := nc.Publish("demo.subject", []byte(strconv.Itoa(i)))
		if err != nil {
			log.Fatal(err)
		}
		time.Sleep(time.Second * 1)
	}
}
 

Subscriber

package main
 
import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"
 
	nats "github.com/nats-io/nats.go"
)
 
func main() {
	nc, err := nats.Connect("nats://127.0.0.1:4222", nats.UserInfo("maksim", "pass"))
	if err != nil {
		log.Fatal(err)
	}
 
	s, err := nc.SubscribeSync("demo.subject")
	if err != nil {
		log.Fatal(err)
	}
	defer s.Drain()
 
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
 
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
 
	go func() {
		sig := <-sigChan
		log.Printf("Received signal: %v, initiating graceful shutdown...", sig)
		cancel()
	}()
 
	for {
		select {
		case <-ctx.Done():
			log.Println("Graceful shutdown: finishing current message and exiting.")
			return
		default:
			msg, err := s.NextMsg(time.Second * 1)
			if err == nil && msg != nil {
				fmt.Println(msg)
			}
		}
	}
}
 

Если использовать nc.QueueSubscribeSync("demo.subject", "queue-1") то подписчики образуют группу и каждое конкретное сообщение получит только один из них.