如何在Golang中借助go-telegram-bot-api实现Telegram内联按钮分页
基于go-telegram-bot-api的内联分页实现
核心逻辑
- 分页参数(当前页码)存储在内联按钮的
callback_data字段中 - 用户点击按钮触发回调时,解析页码后重新渲染对应页的内容和按钮,更新原有消息即可完成翻页
- 自动处理边界状态:第一页隐藏「上一页」按钮,最后一页隐藏「下一页」按钮
完整实现示例
首先引入依赖:
import ( "fmt" "strconv" "strings" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" )
定义分页配置结构体和工具函数:
type PaginationConfig struct { CurrentPage int // 当前页码,从1开始 TotalPages int // 总页数 Data []interface{} // 你的业务数据列表 PerPage int // 每页展示条数 } // 生成分页内联键盘 func generatePaginationKeyboard(pg PaginationConfig) tgbotapi.InlineKeyboardMarkup { var row []tgbotapi.InlineKeyboardButton // 上一页按钮,当前页大于1才显示 if pg.CurrentPage > 1 { prevBtn := tgbotapi.NewInlineKeyboardButtonData("⬅️ 上一页", fmt.Sprintf("page:%d", pg.CurrentPage-1)) row = append(row, prevBtn) } // 页码显示按钮 pageInfoBtn := tgbotapi.NewInlineKeyboardButtonData(fmt.Sprintf("%d/%d", pg.CurrentPage, pg.TotalPages), "page:noop") row = append(row, pageInfoBtn) // 下一页按钮,当前页小于总页数才显示 if pg.CurrentPage < pg.TotalPages { nextBtn := tgbotapi.NewInlineKeyboardButtonData("➡️ 下一页", fmt.Sprintf("page:%d", pg.CurrentPage+1)) row = append(row, nextBtn) } return tgbotapi.NewInlineKeyboardMarkup(row) } // 生成当前页的文本内容,按需修改为你的业务渲染逻辑 func generatePageContent(pg PaginationConfig) string { start := (pg.CurrentPage - 1) * pg.PerPage end := start + pg.PerPage if end > len(pg.Data) { end = len(pg.Data) } currentPageData := pg.Data[start:end] var content strings.Builder content.WriteString(fmt.Sprintf("📋 数据列表(第%d页,共%d页)\n\n", pg.CurrentPage, pg.TotalPages)) for i, item := range currentPageData { // 这里替换为你自己的数据字段渲染逻辑 content.WriteString(fmt.Sprintf("%d. %v\n", start+i+1, item)) } return content.String() }
主逻辑:消息触发+回调处理
func main() { // 初始化bot,替换为你的bot token bot, err := tgbotapi.NewBotAPI("YOUR_BOT_TOKEN") if err != nil { panic(err) } // 示例业务数据,替换为你接口返回的数据 var allData []interface{} for i := 0; i < 100; i++ { allData = append(allData, fmt.Sprintf("测试数据项%d", i+1)) } perPage := 10 totalPages := (len(allData) + perPage - 1) / perPage // 向上取整计算总页数 u := tgbotapi.NewUpdate(0) u.Timeout = 60 updates := bot.GetUpdatesChan(u) for update := range updates { // 处理普通消息,触发分页消息发送 if update.Message != nil && update.Message.Text == "/list" { // 初始化第一页 pg := PaginationConfig{ CurrentPage: 1, TotalPages: totalPages, Data: allData, PerPage: perPage, } msg := tgbotapi.NewMessage(update.Message.Chat.ID, generatePageContent(pg)) msg.ReplyMarkup = generatePaginationKeyboard(pg) bot.Send(msg) continue } // 处理分页按钮回调 if update.CallbackQuery != nil { cbData := update.CallbackQuery.Data // 只处理分页相关的回调 if strings.HasPrefix(cbData, "page:") { pageStr := strings.TrimPrefix(cbData, "page:") // 点击页码展示按钮不做处理 if pageStr == "noop" { // 应答回调避免加载转圈 cbResp := tgbotapi.NewCallback(update.CallbackQuery.ID, "") bot.Send(cbResp) continue } // 解析页码 targetPage, err := strconv.Atoi(pageStr) if err != nil || targetPage < 1 || targetPage > totalPages { cbResp := tgbotapi.NewCallback(update.CallbackQuery.ID, "页码不合法") bot.Send(cbResp) continue } // 生成新的分页配置 pg := PaginationConfig{ CurrentPage: targetPage, TotalPages: totalPages, Data: allData, PerPage: perPage, } // 编辑原有消息,更新内容和按钮 editMsg := tgbotapi.NewEditMessageText( update.CallbackQuery.Message.Chat.ID, update.CallbackQuery.Message.MessageID, generatePageContent(pg), ) editMsg.ReplyMarkup = &tgbotapi.InlineKeyboardMarkup{ InlineKeyboard: generatePaginationKeyboard(pg).InlineKeyboard, } bot.Send(editMsg) // 应答回调 cbResp := tgbotapi.NewCallback(update.CallbackQuery.ID, "") bot.Send(cbResp) } } } }
注意事项
- 若你的业务需要支持多用户不同查询条件的分页,可将查询条件、数据列表存入缓存,生成唯一标识放在
callback_data中,回调时通过唯一标识取出对应数据即可 callback_data字段最大长度为64字节,请勿存入过长内容- 必须对回调进行应答,否则用户端按钮会一直显示加载状态
内容的提问来源于stack exchange,提问作者Souriz
相关产品推荐
相关产品推荐

