Getting started¶
By the end of this you will have a NATS server running inside your program, a client connected to it without touching the network, and a message going from one to the other.
Nothing needs installing. No broker, no container, no port.
Install¶
The whole thing¶
package main
import (
"context"
"fmt"
"log/slog"
"time"
"github.com/nats-io/nats.go"
gonats "gitlab.com/phpboyscout/go/nats"
"gitlab.com/phpboyscout/go/nats/client"
"gitlab.com/phpboyscout/go/nats/server"
)
func main() {
ctx := context.Background()
log := slog.Default()
// A server with no listener at all — not even loopback.
srv, err := server.New(ctx, gonats.ServerSettings{InProcessOnly: true})
if err != nil {
panic(err)
}
if err := server.Start(log, srv)(ctx); err != nil {
panic(err)
}
defer server.Stop(log, srv)(ctx)
// A client that reaches it through memory rather than a socket.
cli, err := client.Connect(ctx, gonats.ClientSettings{Name: "tutorial"}, nil,
client.InProcess(srv))
if err != nil {
panic(err)
}
defer cli.Close()
got := make(chan string, 1)
if _, err := cli.Subscribe("greetings", func(m *nats.Msg) {
got <- string(m.Data)
}); err != nil {
panic(err)
}
if err := cli.Conn().Publish("greetings", []byte("hello")); err != nil {
panic(err)
}
select {
case msg := <-got:
fmt.Println("received:", msg)
case <-time.After(time.Second):
fmt.Println("nothing arrived")
}
}
Run it and you get received: hello.
What just happened¶
server.New built a real NATS server — the same one you would deploy standalone — and
InProcessOnly told it not to open a listener. server.Start ran it and waited for it to accept
connections, so a server that never becomes ready fails here rather than at your first publish.
client.InProcess(srv) is the interesting part. Instead of dialling an address, the client took an
in-memory connection from the server. There is no TCP involved, not even a loopback hop.
cli.Subscribe did one thing beyond the underlying library: it bounded the subscription's queue.
Left alone, NATS allows 500,000 pending messages per subscription, which is a limit in the sense
that the heat death of the universe is a deadline.
Next¶
- Embed a server — with
go/controlsmanaging its lifecycle, which is how a real service does it. - Connect to a cluster — the same code, a different address.
- What this module does not do.