Setting up the client
The client is the central object. Everything you do with gogram goes through it. Create one, hold it for the lifetime of the program, share it across goroutines.
Constructing a client
The minimal construction needs three things: an api id, an api hash, and somewhere to put the session. Anything else has a sensible default.
client, err := telegram.NewClient(telegram.ClientConfig{
AppID: 12345,
AppHash: "abcdef0123456789abcdef0123456789",
Session: "session.dat",
})
if err != nil {
log.Fatal(err)
}client, err := telegram.NewClient(telegram.ClientConfig{
AppID: 12345,
AppHash: "abcdef0123456789abcdef0123456789",
Session: "session.dat",
})
if err != nil {
log.Fatal(err)
}NewClient does not touch the network. It validates the config, initialises the in-memory MTProto sender, and loads the session file if one exists at the given path. If you set NoPreconnect: false (the default), it will also dial the configured data centre immediately, so by the time NewClient returns the connection is usually open.
The builder pattern
If you prefer fluent chains, the builder produces the same client:
client, err := telegram.NewBuilder(12345, "abcdef...").
WithSession("session.dat").
WithDataCenter(2).
WithLogLevel(telegram.LogInfo).
Build()client, err := telegram.NewBuilder(12345, "abcdef...").
WithSession("session.dat").
WithDataCenter(2).
WithLogLevel(telegram.LogInfo).
Build()Every ClientConfig field has a matching With* method on the builder. Pick whichever you like; the result is identical.
Connecting
Connectopens the underlying transport, performs the MTProto obfuscation handshake, and either loads the existing auth key from your session or runs a fresh Diffie–Hellman to make a new one. The first call takes ~3 round-trips to the chosen DC; subsequent calls (after a reconnect) are instant because the auth key is reused.
Lifecycle methods
client.Connect() // open the wire, do or load the auth-key handshake client.LoginBot(tok) // sign in (or no-op if already authenticated) client.Idle() // block forever, run dispatcher client.Stop() // shut down the dispatcher client.Disconnect() // close the connection client.Terminate() // full shutdown, releases all resources
client.Connect() // open the wire, do or load the auth-key handshake
client.LoginBot(tok) // sign in (or no-op if already authenticated)
client.Idle() // block forever, run dispatcher
client.Stop() // shut down the dispatcher
client.Disconnect() // close the connection
client.Terminate() // full shutdown, releases all resources- Connect
- Open the transport, complete the handshake. Idempotent — safe to call repeatedly.
- LoginBot / Login
- Authenticate. No-op if the session is already authenticated and still valid.
- Idle
- Block the current goroutine until the client is stopped. Use this in
mainso the process does not exit while the dispatcher runs in the background. - Stop
- Cancel
Idleand shut down handler dispatch. The connection stays open. - Disconnect
- Close the underlying transport but keep the auth key in memory. A subsequent
Connectresumes cleanly. - Terminate
- Full shutdown. Disconnects, stops every goroutine the client started, releases caches. The client is not reusable afterwards.
Concurrency
Every method on Client is safe to call from any goroutine. RPC calls are multiplexed onto the single MTProto channel and the responses are demultiplexed back to the right caller. Internally there is a per-DC sender pool with mutexes around the wire reads; you do not need to add your own locking.
// safe from any goroutine
go func() {
for msg := range incoming {
client.SendMessage(msg.PeerID, msg.Text)
}
}()// safe from any goroutine
go func() {
for msg := range incoming {
client.SendMessage(msg.PeerID, msg.Text)
}
}()The exception is the dispatcher. Update handlers run on a worker pool with a configurable size; if you do CPU-heavy or blocking work inside a handler you may want to fan it out to your own goroutines so the dispatcher can move on.
