Go + Server酱:任务完成/出错,微信立刻知道

效果:在 Go 程序中调用 Server酱 API,任务完成、异常告警等消息实时推送到你的微信。

前置条件

方式一:官方 SDK(推荐)

安装:

go get github.com/easychen/serverchan-sdk-golang

调用(来自官方 README):

package main

import (
    "fmt"
    "github.com/easychen/serverchan-sdk-golang"
)

func main() {
    sendkey := "your-sendkey"
    title := "Test Message"
    desp := "This is a test message"

    resp, err := serverchan_sdk.ScSend(sendkey, title, desp, nil)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Response:", resp)
    }
}

SDK 按 SendKey 前缀自动识别 Server酱Turbo(SCT 开头)与 Server酱³(sctp 开头),无需关心端点差异。

方式二:官方示例直调实现

以下代码来自官方示例仓库 serverchan-demogolang/main.go),同样自动识别两种 SendKey,可直接复制使用:

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strings"
)

func main() {
	data, err := ioutil.ReadFile("../.env")
	if err != nil {
		fmt.Println(err)
		return
	}

	env := string(data)
	m, err := parseEnv(env)
	if err != nil {
		fmt.Println(err)
		return
	}

	key := m["SENDKEY"]

	ret := scSend("主人服务器宕机了 via go", "第一行\n\n第二行", key)
	fmt.Println(ret)
}

func parseEnv(env string) (map[string]string, error) {
	m := make(map[string]string)
	lines := strings.Split(env, "\n")
	for _, line := range lines {
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		parts := strings.Split(line, "=")
		if len(parts) != 2 {
			return nil, fmt.Errorf("Invalid .env format")
		}
		key := strings.TrimSpace(parts[0])
		value := strings.TrimSpace(parts[1])
		m[key] = value
	}
	return m, nil
}

func scSend(text string, desp string, key string) string {
	data := url.Values{}
	data.Set("text", text)
	data.Set("desp", desp)

	// 根据 sendkey 是否以 "sctp" 开头决定 API 的 URL
	var apiUrl string
	if strings.HasPrefix(key, "sctp") {
		// 使用正则表达式提取数字部分
		re := regexp.MustCompile(`sctp(\d+)t`)
		matches := re.FindStringSubmatch(key)
		if len(matches) > 1 {
			num := matches[1]
			apiUrl = fmt.Sprintf("https://%s.push.ft07.com/send/%s.send", num, key)
		} else {
			return "Invalid sendkey format for sctp"
		}
	} else {
		apiUrl = fmt.Sprintf("https://sctapi.ftqq.com/%s.send", key)
	}

	client := &http.Client{}
	req, err := http.NewRequest("POST", apiUrl, strings.NewReader(data.Encode()))
	if err != nil {
		return err.Error()
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	resp, err := client.Do(req)
	if err != nil {
		return err.Error()
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err.Error()
	}

	return string(body)
}

运行方式:

go run main.go

官方示例从仓库根目录的 .env 文件读取 SENDKEY;集成到你的项目时,可改为读取环境变量 SERVERCHAN_SENDKEY 或你的配置系统。

常见问题

免费额度够用吗?

免费版每天 5 条。程序类通知建议在任务结束时合并推送一条摘要;量大可订阅会员目前特价最低 3 元/月,一天最多可发 1000 条(价格详情)。

消息没收到怎么办?

先检查返回 JSON 的 code 是否为 0,再按 常见问题与排查 逐项检查。

有频率限制吗?

每分钟最多 50 条,注意不要在循环里逐条推送,先聚合再发送。

相关集成

懒人方案:把这段话复制给你的 AI 助手

把下面这段文字原样粘贴给 Claude Code、Cursor 或任何 AI 编程助手,它就会替你完成 Server酱 的接入:

请帮我把 Server酱 微信通知接入到我当前的项目/工具中:
1. API:POST https://sctapi.ftqq.com/{SendKey}.send,参数 title(必填,不能含换行)、desp(正文,支持 Markdown,可选);成功时返回 JSON 的 code 为 0。
2. 如果我的 SendKey 以 sctp 开头,则改用 https://{uid}.push.ft07.com/send/{SendKey}.send,uid 是 SendKey 中 sctp 与 t 之间的数字。
3. SendKey 从环境变量 SERVERCHAN_SENDKEY 读取;如果没有,提醒我到 https://sct.ftqq.com 免费获取(每天 5 条额度)。
4. 安全要求:不要把 SendKey 硬编码进代码、不要打印到日志、不要提交到 git。
5. 频率约定:任务结束发 1 条结果摘要即可,批量任务合并成一条,不要每步都推。
请根据我当前的项目和场景直接写好代码/配置并验证。