You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Go语言通过Google Calendar API批量添加事件?批量请求及并发可行吗?

批量添加Google Calendar事件的Go实现方案

一、是否适合批量请求?

Google Calendar API没有专门的批量插入事件接口,但批量场景下,并发请求(结合goroutine)是更高效的方案——比循环逐个调用能大幅提升处理速度。此外也可以利用API的batch端点手动构造批量请求,但官方Go客户端对其支持不够直观,不如并发请求易用。

二、Goroutine并发发送请求的可行性

完全可行,但必须注意两个核心问题:

  • API配额限制:Google Calendar API默认配额为每日10000次请求、每秒100次请求,并发数不能超出这个范围,否则会收到429限流错误。
  • 并发控制:需要用同步原语控制并发数,避免瞬间发起大量请求触发限流或导致服务端拒绝。

三、具体实现代码示例

1. 带并发控制的基础实现

package main

import (
	"context"
	"fmt"
	"sync"
	"google.golang.org/api/calendar/v3"
	"google.golang.org/api/option"
)

func main() {
	// 初始化Calendar服务(假设已完成身份验证,如使用服务账号密钥)
	ctx := context.Background()
	service, err := calendar.NewService(ctx, option.WithCredentialsFile("service-account-key.json"))
	if err != nil {
		fmt.Printf("创建Calendar服务失败: %v\n", err)
		return
	}

	calendarID := "你的日历ID@group.calendar.google.com"
	// 待插入的事件列表
	events := []*calendar.Event{
		{
			Summary:     "测试事件1",
			Description: "并发插入的事件",
			Start: &calendar.EventDateTime{
				DateTime: "2024-10-01T10:00:00+08:00",
				TimeZone: "Asia/Shanghai",
			},
			End: &calendar.EventDateTime{
				DateTime: "2024-10-01T11:00:00+08:00",
				TimeZone: "Asia/Shanghai",
			},
		},
		// 更多事件...
	}

	// 并发控制:限制同时发起的请求数为10
	sem := make(chan struct{}, 10)
	var wg sync.WaitGroup

	for _, event := range events {
		wg.Add(1)
		sem <- struct{}{} // 获取信号量

		// 启动goroutine插入事件
		go func(e *calendar.Event) {
			defer wg.Done()
			defer func() { <-sem }() // 释放信号量

			insertedEvent, err := service.Events.Insert(calendarID, e).Do()
			if err != nil {
				fmt.Printf("插入事件「%s」失败: %v\n", e.Summary, err)
				return
			}
			fmt.Printf("事件插入成功: %s\n", insertedEvent.HtmlLink)
		}(event)
	}

	wg.Wait()
	fmt.Println("所有事件处理完成")
}

2. 限流重试优化

如果遇到429限流错误,建议加入指数退避重试逻辑,避免请求直接失败:

import (
	"github.com/cenkalti/backoff/v4"
	"google.golang.org/api/googleapi"
)

// 在goroutine内替换插入逻辑
operation := func() error {
	_, err := service.Events.Insert(calendarID, e).Do()
	if err != nil {
		// 检查是否为限流错误
		if respErr, ok := err.(*googleapi.Error); ok && respErr.Code == 429 {
			return err // 触发重试
		}
		return backoff.Permanent(err) // 非限流错误,终止重试
	}
	return nil
}

err := backoff.Retry(operation, backoff.NewExponentialBackOff())
if err != nil {
	fmt.Printf("事件「%s」多次重试后仍插入失败: %v\n", e.Summary, err)
}

四、关键注意事项

  • 权限配置:如果使用服务账号,必须将服务账号邮箱添加到目标日历的共享列表中,并赋予编辑权限。
  • 重复插入规避:可以给事件设置ICalUID字段,API会自动识别并跳过重复的事件。
  • 错误日志:务必记录所有失败请求的详细信息,便于后续排查问题。

内容的提问来源于stack exchange,提问作者Sahildeep Kaur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 17:50:24