Sending SMS in Go (Golang): API Library for Working with SMS Gateways
In modern web development, sending SMS messages remains a popular feature: two-factor authentication, notifications, marketing campaigns. The Go language (Golang), thanks to its performance and simplicity, is ideal for creating microservices that handle message sending. In this article, we will explore how to connect to an SMS gateway via API using the standard net/http library and popular packages for working with HTTP requests.
Choosing an Approach: Standard Library vs Frameworks
Go provides a powerful standard library that is sufficient for working with any REST API. You don't need to install heavy frameworks to send SMS — the built-in net/http package is enough. However, for convenience, we will also look at using the resty library, which simplifies request formation.
Basic HTTP Request Structure in Go
Any SMS gateway accepts a POST request with a JSON body. Let's look at an example of sending a message through a hypothetical service 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 serialization error: %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 request error: %w", err) } defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("response reading error: %w", err) }
var smsResp SMSResponse if err := json.Unmarshal(body, &smsResp); err != nil { return nil, fmt.Errorf("response parsing error: %w", err) }
return &smsResp, nil}
func main() { resp, err := sendSMS("+79123456789", "Test message", "your-api-key-123") if err != nil { fmt.Printf("Error: %v", err) return } fmt.Printf("Status: %s, Message: %s", resp.Status, resp.Message)}Using the resty Library to Simplify Code
The go-resty/resty/v2 library significantly reduces the amount of boilerplate code. Installation:
go get github.com/go-resty/resty/v2Example of sending SMS with 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("request error: %w", err) }
return resp.Result().(*SMSResponse), nil}
func main() { resp, err := sendSMSResty("+79123456789", "Hello from Go!", "my-secret-key") if err != nil { fmt.Prin