在 Go (Golang) 中发送短信:用于短信网关的 API 库
在现代 Web 开发中,发送短信功能仍然很受欢迎:双因素认证、通知、营销推广。Go 语言 (Golang) 凭借其高性能和简洁性,非常适合构建用于发送消息的微服务。在本文中,我们将介绍如何使用标准库 net/http 和流行的 HTTP 请求处理包,通过 API 连接到短信网关。
方法选择:标准库 vs 框架
Go 提供了强大的标准库,足以处理任何 REST API。发送短信无需安装重量级框架——内置的 net/http 包就足够了。不过,为了方便起见,我们还将介绍如何使用 resty 库,它可以简化请求的构建。
Go 中 HTTP 请求的基本结构
任何短信网关都接受带有 JSON 主体的 POST 请求。我们来看一个通过假设服务 sms-provider.com 发送消息的示例:
package main
import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" "time")
type SMSRequest struct { Phone string `json:"phone"` Message string `json:"message"` APIKey string `json:"api_key"`}
type SMSResponse struct { Status string `json:"status"` Message string `json:"message"`}
func sendSMS(phone, message, apiKey string) (*SMSResponse, error) { url := "https://api.sms-provider.com/v1/send"
reqBody := SMSRequest{ Phone: phone, Message: message, APIKey: apiKey, }
jsonData, err := json.Marshal(reqBody) if err != nil { return nil, fmt.Errorf("JSON 序列化错误: %w", err) }
client := &http.Client{Timeout: 10 * time.Second} resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonData)) if err != nil { return nil, fmt.Errorf("HTTP 请求错误: %w", err) } defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("读取响应错误: %w", err) }
var smsResp SMSResponse if err := json.Unmarshal(body, &smsResp); err != nil { return nil, fmt.Errorf("解析响应错误: %w", err) }
return &smsResp, nil}
func main() { resp, err := sendSMS("+79123456789", "测试消息", "your-api-key-123") if err != nil { fmt.Printf("错误: %v", err) return } fmt.Printf("状态: %s, 消息: %s", resp.Status, resp.Message)}使用 resty 库简化代码
go-resty/resty/v2 库可以显著减少样板代码的数量。安装:
go get github.com/go-resty/resty/v2使用 resty 发送短信的示例:
package main
import ( "fmt" "github.com/go-resty/resty/v2")
type SMSResponse struct { Status string `json:"status"` Message string `json:"message"`}
func sendSMSResty(phone, message, apiKey string) (*SMSResponse, error) { client := resty.New() resp, err := client.R(). SetHeader("Content-Type", "application/json"). SetBody(map[string]interface{}{ "phone": phone, "message": message, "api_key": apiKey, }). SetResult(&SMSResponse{}). Post("https://api.sms-provider.com/v1/send")
if err != nil { return nil, fmt.Errorf("请求错误: %w", err) }
return resp.Result().(*SMSResponse), nil}
func main() { resp, err := sendSMSResty("+79123456789", "来自 Go 的问候!", "my-secret-key") if err != nil { fmt.Prin