I’m building a Discord bot using Go that needs to query a MySQL database when users send commands. The problem I’m facing is with the handler function that processes user messages.
This means I can’t pass my database connection as a parameter to the handler. I’ve considered two approaches but both seem problematic:
Making the database connection global (I really want to avoid this)
Creating a new database connection inside each handler call (this would be inefficient)
I’ve looked into using repository patterns but haven’t found a clean solution. What’s the best way to make my database connection available to the message handler without using global variables?
Another approach that works well is using closures to capture the database connection. Create a function that returns your handler with the database connection already bound to it.
This keeps your code functional instead of object-oriented if that’s what you prefer. I’ve used both approaches and they work equally well - just depends on your coding style.
Dependency injection works great for this. Just make a simple container to hold your db connection and inject it into your handlers. Something like type Container struct { DB *sql.DB } then pass it around. Way cleaner than closures and much easier to test.
I hit this exact problem building my Discord bot last year. The cleanest fix was creating a struct that holds your database connection and implements methods matching the handler signature.
type BotHandler struct {
db *sql.DB
repository *UserRepository
}
func (b *BotHandler) MessageHandler(session *discordgo.Session, message *discordgo.MessageCreate) {
// Now you can access b.db and b.repository here
user, err := b.repository.GetUser(message.Author.ID)
// handle your logic
}
func StartBot() {
session, err := discordgo.New("Bot " + Token)
handleError(err)
mysql, dbErr := SetupDatabase()
handleError(dbErr)
handler := &BotHandler{
db: mysql,
repository: NewUserRepository(mysql),
}
session.AddHandler(handler.MessageHandler)
// rest of your code
}
This keeps everything encapsulated without globals and maintains a single database connection throughout your bot’s lifecycle. Been using this in production for over a year with zero issues.