How I Built a Discord Bot in Go

How I Built a Discord Bot in Go

I've always found Discord bots fun to mess with, they're like little automated sidekicks living in your server. But instead of using the usual Node.js setup, I decided to try something different: writing a bot in Go.

GoDiscordBot

I've always found Discord bots fun to mess with—they're like little automated sidekicks living in your server. But instead of using the usual Node.js setup, I decided to try something different: writing a bot in Go. Here's how I did it, what I learned, and how you can build one too.


Why Go?

I was already digging into Go for its performance and concurrency model, and building a bot felt like the perfect excuse to explore network programming and event handling in a real-world way.

Also: goroutines + bots = a match made in dev heaven.


Tools & Libraries

Here's what I used:

  • DiscordGo – The go-to Go library for interacting with Discord's API.
  • Go (v1.20+) – Make sure you've got Go installed and ready.
  • A Discord bot token – You can create one at the Discord Developer Portal.

Step 1: Create Your Bot on Discord

  1. Head over to the Discord Developer Portal.
  2. Click "New Application".
  3. Give it a name.
  4. Under "Bot", click "Add Bot".
  5. Copy the bot token—you'll need this soon (keep it secret!).
  6. Under "OAuth2 → URL Generator", select:
    • Scopes: bot
    • Bot Permissions: Send Messages, Read Messages, Manage Messages, etc.
  7. Copy the generated URL and use it to invite the bot to your server.

Step 2: Setup Your Go Project

Bash
mkdir go-discord-bot
cd go-discord-bot
go mod init github.com/yourusername/go-discord-bot
go get github.com/bwmarrin/discordgo

Create a file named main.go.


Step 3: Write the Basic Bot

Here's a simple bot that replies "Pong!" when you type !ping.

Go
package main
 
import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
 
    "github.com/bwmarrin/discordgo"
)
 
func main() {
    token := "YOUR_BOT_TOKEN_HERE" // or use os.Getenv("DISCORD_TOKEN")
 
    dg, err := discordgo.New("Bot " + token)
    if err != nil {
        fmt.Println("Error creating Discord session,", err)
        return
    }
 
    dg.AddMessageCreateHandler(messageCreate)
 
    err = dg.Open()
    if err != nil {
        fmt.Println("Error opening connection,", err)
        return
    }
 
    fmt.Println("Bot is now running. Press CTRL+C to exit.")
    sc := make(chan os.Signal, 1)
    signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
    <-sc
 
    dg.Close()
}
 
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
    if m.Author.ID == s.State.User.ID {
        return
    }
 
    if m.Content == "!ping" {
        s.ChannelMessageSend(m.ChannelID, "Pong!")
    }
}

Running the Bot

Just run:

Bash
go run main.go

Go back to your Discord server, type !ping, and boom—your bot should reply with Pong!.


Adding More Commands

You can build out a command router, or just use if / switch statements:

Go
switch m.Content {
case "!ping":
    s.ChannelMessageSend(m.ChannelID, "Pong!")
case "!hello":
    s.ChannelMessageSend(m.ChannelID, "Hey there! 👋")
}

Or even better: map commands to functions if you're feeling fancy.


Ideas to Expand It

  • Random jokes or facts from an API
  • Moderation commands like !kick or !purge
  • Role assignment
  • Music playback (advanced, but doable)
  • Persistent storage with a DB (like SQLite or PostgreSQL)

Lessons Learned

  • Go's concurrency is great for handling multiple commands/events.
  • The DiscordGo docs are a bit sparse, but the GitHub issues and examples help.
  • Handling rate limits and reconnects becomes important as your bot scales.
  • It's honestly a blast building tools for a community you're part of.

Final Thoughts

If you're into Go and want a fun weekend project or a dev portfolio piece, writing a Discord bot is 100% worth it. You'll learn a ton about APIs, event-driven programming, and real-time systems—all while building something fun and useful.