Back to Examples
Go
Integrate GuardCrow into your Go applications using the standard library or popular HTTP clients.
Basic Example
A simple example using the standard net/http package:
main.gogo
package mainimport ("bytes""encoding/json""fmt""net/http""os")type AnalyzeRequest struct {Content string `json:"content"`Metadata map[string]string `json:"metadata,omitempty"`}type AnalyzeResponse struct {Passed bool `json:"passed"`Score int `json:"score"`Sentiment string `json:"sentiment"`Description string `json:"description"`Categories []string `json:"categories"`ProcessingTimeMs int `json:"processingTimeMs"`}func analyzeContent(content string) (*AnalyzeResponse, error) {apiKey := os.Getenv("GUARDCROW_API_KEY")reqBody := AnalyzeRequest{Content: content}jsonBody, err := json.Marshal(reqBody)if err != nil {return nil, err}req, err := http.NewRequest("POST","https://api.guardcrow.com/v1/analyze",bytes.NewBuffer(jsonBody),)if err != nil {return nil, err}req.Header.Set("X-API-Key", apiKey)req.Header.Set("Content-Type", "application/json")client := &http.Client{}resp, err := client.Do(req)if err != nil {return nil, err}defer resp.Body.Close()var result AnalyzeResponseif err := json.NewDecoder(resp.Body).Decode(&result); err != nil {return nil, err}return &result, nil}func main() {result, err := analyzeContent("Hello, this is a test message")if err != nil {fmt.Println("Error:", err)return}fmt.Printf("Passed: %v, Score: %d\n", result.Passed, result.Score)}
Complete Client Package
A production-ready client with retry logic and error handling:
guardcrow/client.gogo
package guardcrowimport ("bytes""context""encoding/json""errors""fmt""io""net/http""strconv""time")var (ErrRateLimited = errors.New("rate limit exceeded")ErrInvalidAPIKey = errors.New("invalid API key")ErrContentTooLong = errors.New("content exceeds maximum length"))type Client struct {apiKey stringbaseURL stringhttpClient *http.ClientmaxRetries int}type ClientOption func(*Client)func WithBaseURL(url string) ClientOption {return func(c *Client) { c.baseURL = url }}func WithHTTPClient(client *http.Client) ClientOption {return func(c *Client) { c.httpClient = client }}func WithMaxRetries(n int) ClientOption {return func(c *Client) { c.maxRetries = n }}func NewClient(apiKey string, opts ...ClientOption) *Client {c := &Client{apiKey: apiKey,baseURL: "https://api.guardcrow.com/v1",httpClient: &http.Client{Timeout: 30 * time.Second},maxRetries: 3,}for _, opt := range opts {opt(c)}return c}type AnalyzeRequest struct {Content string `json:"content"`Metadata map[string]string `json:"metadata,omitempty"`}type AnalyzeResponse struct {Passed bool `json:"passed"`Score int `json:"score"`Sentiment string `json:"sentiment"`Description string `json:"description"`Categories []string `json:"categories"`ProcessingTimeMs int `json:"processingTimeMs"`}type APIError struct {Code string `json:"code"`Message string `json:"message"`Status int `json:"status"`}func (e *APIError) Error() string {return fmt.Sprintf("%s: %s", e.Code, e.Message)}func (c *Client) Analyze(ctx context.Context, req *AnalyzeRequest) (*AnalyzeResponse, error) {var lastErr errorfor attempt := 0; attempt < c.maxRetries; attempt++ {result, err := c.doAnalyze(ctx, req)if err == nil {return result, nil}// Don't retry on certain errorsif errors.Is(err, ErrInvalidAPIKey) || errors.Is(err, ErrContentTooLong) {return nil, err}lastErr = err// Exponential backoffif attempt < c.maxRetries-1 {backoff := time.Duration(1<<attempt) * time.Secondselect {case <-ctx.Done():return nil, ctx.Err()case <-time.After(backoff):}}}return nil, lastErr}func (c *Client) doAnalyze(ctx context.Context, req *AnalyzeRequest) (*AnalyzeResponse, error) {jsonBody, err := json.Marshal(req)if err != nil {return nil, err}httpReq, err := http.NewRequestWithContext(ctx,"POST",c.baseURL+"/analyze",bytes.NewBuffer(jsonBody),)if err != nil {return nil, err}httpReq.Header.Set("X-API-Key", c.apiKey)httpReq.Header.Set("Content-Type", "application/json")resp, err := c.httpClient.Do(httpReq)if err != nil {return nil, err}defer resp.Body.Close()body, err := io.ReadAll(resp.Body)if err != nil {return nil, err}switch resp.StatusCode {case http.StatusOK:var result AnalyzeResponseif err := json.Unmarshal(body, &result); err != nil {return nil, err}return &result, nilcase http.StatusTooManyRequests:resetTime := resp.Header.Get("X-RateLimit-Reset")if resetTime != "" {if ts, err := strconv.ParseInt(resetTime, 10, 64); err == nil {waitDuration := time.Until(time.Unix(ts, 0))time.Sleep(waitDuration)}}return nil, ErrRateLimitedcase http.StatusUnauthorized:return nil, ErrInvalidAPIKeycase http.StatusBadRequest:var errResp struct {Error APIError `json:"error"`}json.Unmarshal(body, &errResp)if errResp.Error.Code == "CONTENT_TOO_LONG" {return nil, ErrContentTooLong}return nil, &errResp.Errordefault:var errResp struct {Error APIError `json:"error"`}if err := json.Unmarshal(body, &errResp); err != nil {return nil, fmt.Errorf("unexpected status: %d", resp.StatusCode)}return nil, &errResp.Error}}func (c *Client) HealthCheck(ctx context.Context) (bool, error) {req, err := http.NewRequestWithContext(ctx, "GET", c.baseURL+"/health", nil)if err != nil {return false, err}resp, err := c.httpClient.Do(req)if err != nil {return false, err}defer resp.Body.Close()return resp.StatusCode == http.StatusOK, nil}
Using the Client
main.gogo
package mainimport ("context""fmt""log""os""time""yourproject/guardcrow")func main() {client := guardcrow.NewClient(os.Getenv("GUARDCROW_API_KEY"),guardcrow.WithMaxRetries(3),)ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)defer cancel()result, err := client.Analyze(ctx, &guardcrow.AnalyzeRequest{Content: "This is a test message to analyze",Metadata: map[string]string{"source": "user-comments","user_id": "user_123",},})if err != nil {log.Fatal("Analysis failed:", err)}fmt.Printf("Passed: %v\n", result.Passed)fmt.Printf("Score: %d\n", result.Score)fmt.Printf("Sentiment: %s\n", result.Sentiment)fmt.Printf("Description: %s\n", result.Description)}
HTTP Middleware
Create middleware to automatically moderate incoming requests:
middleware.gogo
package middlewareimport ("bytes""context""encoding/json""io""net/http""yourproject/guardcrow")type contextKey stringconst ModerationResultKey contextKey = "moderation_result"func ContentModeration(client *guardcrow.Client, contentField string) func(http.Handler) http.Handler {return func(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {// Only moderate POST/PUT/PATCH requestsif r.Method != "POST" && r.Method != "PUT" && r.Method != "PATCH" {next.ServeHTTP(w, r)return}// Read and restore bodybody, err := io.ReadAll(r.Body)if err != nil {http.Error(w, "Failed to read request", http.StatusBadRequest)return}r.Body = io.NopCloser(bytes.NewBuffer(body))// Extract content fieldvar data map[string]interface{}if err := json.Unmarshal(body, &data); err != nil {next.ServeHTTP(w, r)return}content, ok := data[contentField].(string)if !ok || content == "" {next.ServeHTTP(w, r)return}// Analyze contentresult, err := client.Analyze(r.Context(), &guardcrow.AnalyzeRequest{Content: content,})if err != nil {// Don't block on API errorsnext.ServeHTTP(w, r)return}// Block toxic contentif result.Score >= 7 {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusBadRequest)json.NewEncoder(w).Encode(map[string]string{"error": "Content blocked by moderation","reason": result.Description,})return}// Add result to context for downstream handlersctx := context.WithValue(r.Context(), ModerationResultKey, result)next.ServeHTTP(w, r.WithContext(ctx))})}}// Helper to get moderation result from contextfunc GetModerationResult(ctx context.Context) *guardcrow.AnalyzeResponse {result, _ := ctx.Value(ModerationResultKey).(*guardcrow.AnalyzeResponse)return result}
Gin Framework Example
main.gogo
package mainimport ("net/http""os""github.com/gin-gonic/gin""yourproject/guardcrow")var csClient *guardcrow.Clientfunc init() {csClient = guardcrow.NewClient(os.Getenv("GUARDCROW_API_KEY"))}type CommentRequest struct {Content string `json:"content" binding:"required"`UserID string `json:"user_id" binding:"required"`}func moderateMiddleware() gin.HandlerFunc {return func(c *gin.Context) {var req CommentRequestif err := c.ShouldBindJSON(&req); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})c.Abort()return}result, err := csClient.Analyze(c.Request.Context(), &guardcrow.AnalyzeRequest{Content: req.Content,})if err != nil {// Log error but don't blockc.Set("moderation_error", err)c.Next()return}if result.Score >= 7 {c.JSON(http.StatusBadRequest, gin.H{"error": "Content blocked","reason": result.Description,})c.Abort()return}c.Set("moderation_result", result)c.Set("comment_request", req)c.Next()}}func main() {r := gin.Default()r.POST("/comments", moderateMiddleware(), func(c *gin.Context) {req := c.MustGet("comment_request").(CommentRequest)result := c.MustGet("moderation_result").(*guardcrow.AnalyzeResponse)// Save comment with moderation infoc.JSON(http.StatusCreated, gin.H{"message": "Comment created","moderation_score": result.Score,})})r.Run(":8080")}
Environment Setup
Set your API key as an environment variable:
Terminalbash
export GUARDCROW_API_KEY=sk_live_your_api_key_here