# speedpix-go **Repository Path**: mirrors_aliyun/speedpix-go ## Basic Information - **Project Name**: speedpix-go - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-06-17 - **Last Updated**: 2025-11-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SpeedPix Go SDK 🚀 智作工坊 SpeedPix API 的 Go 客户端库,为 AI 图像生成工作流提供简洁易用的接口。 ## 📚 关于智作工坊 智作工坊(AIGC Service Lab)是阿里云教育推出的 AIGC 生成服务,主要为泛教育、设计业务企业提供高效的 AIGC(人工智能生成内容)PAAS 服务。 ### 🎯 核心功能 - **文生图**:根据文本描述生成高质量图像 - **图生图**:基于输入图像进行风格转换或内容变换 - **文转视频**:将文本描述转换为动态视频内容 - **图转视频**:将静态图像转换为动态视频 ### 🔧 技术支持 - 支持**通义万相**以及开源的 **Stable Diffusion** 模型 - 提供 **WEB UI** 和 **ComfyUI** 两种模式 - 集成阿里云严格的**内容安全检测服务** - 支持自定义界面部署和权限管理 ### 📖 详细文档 - [智作工坊产品文档](https://help.aliyun.com/document_detail/2804197.html) - [产品概述](https://help.aliyun.com/document_detail/2804199.html) - [智作工坊控制台](https://eduplatform-sp.console.aliyun.com/) --- ## 📋 目录 - [✨ 主要特性](#-主要特性) - [📦 安装](#-安装) - [⚡ 快速开始](#-快速开始) - [📖 使用示例](#-使用示例) - [基础用法](#基础用法) - [创建和等待](#创建和等待) - [🔒 类型安全支持](#-类型安全支持新特性) - [🔄 后台处理](#-后台处理) - [📁 文件上传](#-文件上传) - [📄 文件对象作为输入](#-文件对象作为输入) - [📥 处理文件输出](#-处理文件输出) - [🔧 增强的文件类型支持](#-增强的文件类型支持新特性) - [⚙️ 配置选项](#️-配置选项) - [💡 使用技巧和最佳实践](#-使用技巧和最佳实践) - [🎯 选择合适的工作流方式](#-选择合适的工作流方式) - [🏷️ 推荐的命名和组织](#️-推荐的命名和组织) - [🔧 性能优化建议](#-性能优化建议) - [📊 监控和日志](#-监控和日志) - [🛡️ 错误处理和重试策略](#️-错误处理和重试策略) - [⚠️ 错误处理](#️-错误处理) - [❓ 常见问题](#-常见问题) - [📚 示例](#-示例) - [🛠️ 开发](#️-开发) - [📄 许可证](#-许可证) - [🤝 贡献](#-贡献) ## ✨ 主要特性 - 🎯 **简洁易用**:类似 Replicate 的 API 设计,快速上手 - 🔄 **自动文件处理**:支持本地文件路径自动上传 - 📝 **类型安全**:支持 Go 泛型的类型安全输出 - 🎨 **丰富的文件类型**:图片、视频、音频、文档的智能类型检测 - ⚡ **异步处理**:支持后台任务和轮询等待 - 🛠️ **灵活配置**:多种配置方式,环境变量和代码配置 - 🚀 **开箱即用**:endpoint 和 aliasId 均有合理默认值 ## 🔧 重要说明 ### 📌 默认值设置 - **endpoint**:可选参数,默认值为 `https://openai.edu-aliyun.com` - **aliasId**:可选参数,默认值为 `"main"` ### 🚀 最简使用方式 ```go // 仅需提供必需的认证信息,其他参数均有默认值 client, err := speedpix.NewClient( speedpix.WithAppKey("your-app-key"), speedpix.WithAppSecret("your-app-secret"), // endpoint 自动使用默认值 https://openai.edu-aliyun.com ) output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{"prompt": "test"}, // aliasId 自动使用默认值 "main" }) ``` ## 📦 安装 ```bash go get github.com/aliyun/speedpix-go ``` ## ⚡ 快速开始 ### 1. 基础配置 **方式一:最简配置(推荐)** ```go package main import ( "context" "fmt" "log" "github.com/aliyun/speedpix-go" ) func main() { // 最简方式创建客户端 - 只需提供必需的认证信息 // endpoint 默认为 https://openai.edu-aliyun.com client, err := speedpix.NewClient( speedpix.WithAppKey("your-app-key"), speedpix.WithAppSecret("your-app-secret"), // WithEndpoint 可选,不提供时使用默认值 ) if err != nil { log.Fatal(err) } ctx := context.Background() // 运行工作流 - aliasId 默认为 "main" output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, // AliasID 可选,不提供时默认为 "main" }) if err != nil { log.Fatal(err) } fmt.Println("结果:", output) } ``` **方式二:完整配置** ```go // 如需自定义 endpoint 和 aliasId client, err := speedpix.NewClient( speedpix.WithEndpoint("https://custom-endpoint.com"), // 自定义端点 speedpix.WithAppKey("your-app-key"), speedpix.WithAppSecret("your-app-secret"), ) output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", AliasID: speedpix.StringPtr("custom-alias"), // 自定义别名 Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, }) ``` **方式三:环境变量配置** 设置环境变量: ```bash # 可选:不设置时自动使用默认值 https://openai.edu-aliyun.com export SPEEDPIX_ENDPOINT=your-custom-endpoint.com # 必需:认证信息 export SPEEDPIX_APP_KEY=your-app-key export SPEEDPIX_APP_SECRET=your-app-secret ``` 然后创建客户端: ```go // 从环境变量读取配置,endpoint 可选 client, err := speedpix.NewClient(speedpix.WithAllFromEnv()) // 运行时 aliasId 仍会默认为 "main" output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{"prompt": "test"}, // AliasID 不提供时自动使用 "main" }) ``` ## 🚀 资源配置 ### 共享算力 vs 独享资源 智作工坊支持两种资源类型: - **共享算力**:默认使用,成本较低,适合一般业务场景 - **独享资源**:推荐对延迟和成功率敏感的业务使用,提供更稳定的性能保障 ### 配置方式 默认情况下,如果不指定 `ResourceConfigID`,系统会使用共享算力资源。如果您对延迟和成功率有较高要求,推荐配置独享资源。 ```go // 使用共享算力(默认) output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, // ResourceConfigID 不指定时自动使用共享算力 }) // 使用独享资源 output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", ResourceConfigID: "your-dedicated-resource-id", // 指定独享资源ID Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, }) // 在创建预测时指定独享资源 prediction, err := client.Predictions.Create(ctx, speedpix.CreatePredictionOptions{ WorkflowID: "your-workflow-id", ResourceConfigID: "your-dedicated-resource-id", Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, }) ``` ### 相关文档 - [独享资源管理](https://help.aliyun.com/document_detail/2834512.html) - [资源配置参数说明](https://help.aliyun.com/document_detail/2844596.html) --- ## 📖 使用示例 ### API 方法选择 **使用 `Run()` 方法**:适用于简单场景,自动等待完成并返回结果 **使用 `Predictions.Create()` + `Wait()`**:适用于需要异步处理或更精细控制的场景 ### 基础用法 ```go // 直接运行 - 等待完成(AliasID 自动默认为 "main") output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, // AliasID 可选,不提供时默认为 "main" }) // 如需指定特定的别名 output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", AliasID: speedpix.StringPtr("custom-alias"), Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, }) ``` ### 创建和等待 ```go // 创建预测任务但不等待(AliasID 自动默认为 "main") prediction, err := client.Predictions.Create(ctx, speedpix.CreatePredictionOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, // AliasID 可选,不提供时默认为 "main" }) if err != nil { log.Fatal(err) } // 等待完成 prediction, err = prediction.Wait(ctx) if err != nil { log.Fatal(err) } fmt.Println("输出:", prediction.Output) ``` ### 🔒 类型安全支持(新特性!) 为了提供类型安全和更好的 IDE 支持,SDK 支持 Go 泛型的类型安全输出: ```go // 定义输出结构 type ImageResult struct { Image *speedpix.ImageFile `json:"images"` // 单个 ImageFile,不是数组 Info string `json:"info"` } // 类型安全的直接运行 result, err := speedpix.RunTyped[ImageResult](ctx, client, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "prompt": "一个美丽的风景", }, }) if err != nil { log.Fatal(err) } // 类型安全访问 - 无需类型断言! fmt.Printf("生成了 %d 张图片\n", len(result.Images)) if result != nil && result.Image != nil { fmt.Printf("信息: %s\n", result.Image.URL) result.Image.Save("output_image.png") // 保存图片文件 fmt.Printf("图片已保存为 output_image.png\n") } // 或使用预定义类型 imageOutput, err := speedpix.RunTyped[speedpix.ImageOutput](ctx, client, options) ``` ```go // 类型安全的预测工作流 prediction, err := speedpix.CreateTypedPrediction[ImageResult](ctx, client, speedpix.CreatePredictionOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "prompt": "一个宁静的风景", }, }) completed, err := prediction.Wait(ctx) if completed.Output != nil { // 直接访问类型化字段 fmt.Printf("图片: %v\n", completed.Output.Images) } ``` 可用的预定义类型: - `speedpix.ImageOutput` - 图像生成工作流 - `speedpix.TextOutput` - 文本生成工作流 - `speedpix.MultiModalOutput` - 图像和文本组合 - `speedpix.VideoOutput` - 视频生成工作流 - `speedpix.AudioOutput` - 音频生成工作流 - `speedpix.CustomResult` - 灵活的基于 map 的结果 ### 🔄 后台处理 ```go // 启动但不等待完成 - 使用 Create 方法 prediction, err := client.Predictions.Create(ctx, speedpix.CreatePredictionOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "prompt": "一个复杂的场景", }, }) if err != nil { log.Fatal(err) } fmt.Printf("任务 ID: %s\n", prediction.ID) // 执行其他工作... // 稍后等待完成 prediction, err = prediction.Wait(ctx, speedpix.WaitOptions{ PollingInterval: 2 * time.Second, }) if err != nil { log.Fatal(err) } ``` ### 📁 文件上传 ```go // 上传文件 file, err := client.Files.Create(ctx, "/path/to/image.jpg") if err != nil { log.Fatal(err) } // 在工作流中使用上传的文件 output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "image": file.AccessURL, "prompt": "转换这张图片", }, }) ``` ### 📄 文件对象作为输入 SDK 自动处理输入中的文件对象: ```go // 使用文件路径(将自动上传) output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "image": "/path/to/image.jpg", // 自动上传 }, }) // 使用 io.Reader file, err := os.Open("/path/to/image.jpg") if err != nil { log.Fatal(err) } defer file.Close() output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "image": file, // 自动上传 }, }) ``` ### 📥 处理文件输出 SDK 自动将 URL 输出转换为 `FileOutput` 对象: ```go output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{ "prompt": "生成一张图片", }, }) // 如果输出包含 URL,它们会被转换为 FileOutput 对象 if fileOutput, ok := output.(*speedpix.FileOutput); ok { // 保存到本地文件 err := fileOutput.Save("generated_image.png") if err != nil { log.Fatal(err) } // 或读取内容 content, err := fileOutput.Read() if err != nil { log.Fatal(err) } // 获取 URL fmt.Println("URL:", fileOutput.String()) } ``` ### 🔧 增强的文件类型支持(新特性!) SDK 现在提供具有丰富元数据和类型特定功能的增强文件类型: ```go // 基于 URL 的自动类型检测 prediction, err := speedpix.CreateTypedPrediction[*speedpix.ImageOutput]( client, "stability-ai/stable-diffusion-xl-base-1.0", speedpix.Input{"prompt": "一个美丽的日落"}, ) result, err := prediction.Wait(ctx) if err == nil && result.Output != nil { for i, img := range result.Output.Images { // img 现在是具有丰富元数据的 *ImageFile fmt.Printf("图片 %d: %dx%d %s (%.2f 宽高比)\n", i+1, img.Width, img.Height, img.Format, img.GetAspectRatio()) // 类型特定的辅助方法 fmt.Printf("是正方形: %t, 是竖向: %t\n", img.IsSquare(), img.IsPortrait()) // 访问元数据 if generator, ok := img.Metadata["generator"]; ok { fmt.Printf("生成器: %s\n", generator) } // 保存文件 filename := fmt.Sprintf("image_%d.%s", i+1, img.Format) if err := img.Save(filename); err == nil { fmt.Printf("已保存为: %s\n", filename) } } } ``` #### 可用的文件类型 - **`*ImageFile`** - 图片,包含宽度、高度、格式、DPI、色彩空间 - **`*VideoFile`** - 视频,包含时长、分辨率、编解码器、帧率、音频信息 - **`*AudioFile`** - 音频,包含时长、采样率、比特率、声道信息 - **`*DocumentFile`** - 文档,包含页数、语言、作者、创建日期 #### 创建文件对象 ```go // 使用元数据创建 img := speedpix.CreateImageFile("https://example.com/image.png", map[string]string{ "width": "1024", "height": "768", "format": "png", }) // 或使用流畅的 API video := speedpix.NewVideoFile("https://example.com/video.mp4"). WithDuration(30 * time.Second). WithDimensions(1920, 1080). WithFormat("mp4"). WithCodec("h264"). WithFrameRate(30.0). WithAudio(true, "aac") // 类型特定的辅助方法 fmt.Printf("视频是高清: %t\n", video.IsHD()) fmt.Printf("视频是 4K: %t\n", video.Is4K()) fmt.Printf("分辨率: %s\n", video.GetResolutionString()) ``` #### 自动类型检测 URL 会根据扩展名自动转换为适当的文件类型: ```go // 这些 URL 会自动变成类型化的文件对象 urls := []string{ "https://example.com/image.jpg", // -> *ImageFile "https://example.com/video.mp4", // -> *VideoFile "https://example.com/audio.mp3", // -> *AudioFile "https://example.com/doc.pdf", // -> *DocumentFile "https://example.com/unknown.xyz", // -> *FileOutput (通用) } ``` 所有文件类型都继承自 `FileOutput` 并提供: - `Save(path)` - 下载并保存文件 - `Read()` - 获取文件内容的字节 - `String()` - 获取 URL - 加上类型特定的元数据和辅助方法 ## ⚙️ 配置选项 ### 客户端选项 ```go // 完整配置示例 client, err := speedpix.NewClient( speedpix.WithEndpoint("your-endpoint.com"), // 可选,默认: https://openai.edu-aliyun.com speedpix.WithAppKey("your-app-key"), // 必需 speedpix.WithAppSecret("your-app-secret"), // 必需 speedpix.WithTimeout(60*time.Second), speedpix.WithUserAgent("my-app/1.0.0"), speedpix.WithHTTPClient(customHTTPClient), ) // 最简配置示例(推荐) client, err := speedpix.NewClient( speedpix.WithAppKey("your-app-key"), speedpix.WithAppSecret("your-app-secret"), // WithEndpoint 可选,默认使用 https://openai.edu-aliyun.com ) ``` ### 运行选项 ```go output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{"prompt": "..."}, VersionID: speedpix.StringPtr("v1.0"), // 可选版本 AliasID: speedpix.StringPtr("custom"), // 可选别名(默认: "main") RandomiseSeeds: speedpix.BoolPtr(true), // 可选种子随机化 ReturnTempFiles: speedpix.BoolPtr(false), // 可选临时文件 ResourceConfigID: "config-id", // 资源配置 PollingInterval: 2 * time.Second, // 等待时的轮询间隔 }) // 注意:AliasID 是可选的,如果不提供将默认使用 "main" output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "your-workflow-id", Input: map[string]interface{}{"prompt": "..."}, // AliasID 不提供时自动使用 "main" }) ``` ## 💡 使用技巧和最佳实践 ### 🎯 选择合适的工作流方式 ```go // 适用于简单任务 - 直接运行并等待 output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "simple-task", Input: map[string]interface{}{"prompt": "一个简单的图片"}, }) // 适用于复杂任务 - 异步处理 prediction, err := client.Predictions.Create(ctx, speedpix.CreatePredictionOptions{ WorkflowID: "complex-task", Input: map[string]interface{}{"prompt": "一个复杂的场景"}, }) // 稍后检查状态或等待完成 ``` ### 🏷️ 推荐的命名和组织 ```go // 使用有意义的变量名 const ( TextToImageWorkflow = "stable-diffusion-xl" ImageUpscaleWorkflow = "real-esrgan" ImageToVideoWorkflow = "stable-video-diffusion" ) // 组织输入参数 type ImageGenerationInput struct { Prompt string `json:"prompt"` NegativePrompt string `json:"negative_prompt,omitempty"` Width int `json:"width,omitempty"` Height int `json:"height,omitempty"` Seed int `json:"seed,omitempty"` Steps int `json:"num_inference_steps,omitempty"` GuidanceScale float64 `json:"guidance_scale,omitempty"` } func generateImage(client *speedpix.Client, input ImageGenerationInput) (*speedpix.ImageOutput, error) { return speedpix.RunTyped[*speedpix.ImageOutput](context.Background(), client, speedpix.RunOptions{ WorkflowID: TextToImageWorkflow, Input: input, }) } ``` ### 🔧 性能优化建议 ```go // 1. 重用客户端实例 var globalClient *speedpix.Client func init() { var err error globalClient, err = speedpix.NewClient(speedpix.WithAllFromEnv()) if err != nil { log.Fatal(err) } } // 2. 使用上下文超时控制 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() // 3. 批量处理多个任务 var predictions []*speedpix.Prediction for _, input := range inputs { pred, err := client.Predictions.Create(ctx, speedpix.CreatePredictionOptions{ WorkflowID: "batch-task", Input: input, }) if err == nil { predictions = append(predictions, pred) } } // 等待所有任务完成 for _, pred := range predictions { pred.Wait(ctx) } // 4. 文件上传优化 - 预上传大文件 func preprocessLargeFiles(client *speedpix.Client, inputs map[string]interface{}) error { for key, value := range inputs { if filePath, ok := value.(string); ok { if info, err := os.Stat(filePath); err == nil && info.Size() > 10*1024*1024 { // 大于10MB // 预上传文件 file, err := client.Files.Create(context.Background(), filePath) if err != nil { return err } inputs[key] = file.AccessURL } } } return nil } ``` ### 📊 监控和日志 ```go // 添加任务监控 func runWithMonitoring(client *speedpix.Client, options speedpix.RunOptions) (interface{}, error) { start := time.Now() log.Printf("开始运行工作流: %s", options.WorkflowID) output, err := client.Run(context.Background(), options) duration := time.Since(start) if err != nil { log.Printf("工作流失败: %s, 耗时: %v, 错误: %v", options.WorkflowID, duration, err) return nil, err } log.Printf("工作流完成: %s, 耗时: %v", options.WorkflowID, duration) return output, nil } ``` ### 🛡️ 错误处理和重试策略 ```go func processWithRetry(ctx context.Context, client *speedpix.Client, options speedpix.RunOptions) (interface{}, error) { maxRetries := 3 backoffDuration := time.Second for i := 0; i < maxRetries; i++ { output, err := client.Run(ctx, options) if err == nil { return output, nil } // 检查是否是可重试的错误 var predErr *speedpix.PredictionError if errors.As(err, &predErr) { if predErr.Prediction != nil && predErr.Prediction.Status == "failed" { // 任务失败,不重试 return nil, fmt.Errorf("任务失败,不可重试: %w", err) } } // 检查上下文是否已取消 if ctx.Err() != nil { return nil, ctx.Err() } // 指数退避 if i < maxRetries-1 { time.Sleep(backoffDuration) backoffDuration *= 2 } } return nil, fmt.Errorf("达到最大重试次数 (%d): %w", maxRetries, err) } // 批量处理中的错误恢复 func processBatchWithErrorRecovery(client *speedpix.Client, inputs []map[string]interface{}) []Result { results := make([]Result, len(inputs)) for i, input := range inputs { result, err := processWithRetry(context.Background(), client, speedpix.RunOptions{ WorkflowID: "batch-workflow", Input: input, }) if err != nil { log.Printf("任务 %d 失败: %v", i, err) results[i] = Result{Error: err} } else { results[i] = Result{Output: result} } } return results } type Result struct { Output interface{} Error error } ``` ## ❓ 常见问题 ### Q: 如何处理大文件上传? A: 对于大文件(超过10MB),建议预先上传: ```go // 预上传大文件 file, err := client.Files.Create(ctx, "/path/to/large-file.mp4") if err != nil { log.Fatal(err) } // 在工作流中使用上传的文件 URL output, err := client.Run(ctx, speedpix.RunOptions{ WorkflowID: "video-processing", Input: map[string]interface{}{ "video": file.AccessURL, }, }) ``` ### Q: 如何设置请求超时? A: 可以通过上下文或客户端配置设置超时: ```go // 方式一:使用上下文超时 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) defer cancel() output, err := client.Run(ctx, options) // 方式二:配置客户端默认超时 client, err := speedpix.NewClient( speedpix.WithTimeout(5*time.Minute), speedpix.WithAllFromEnv(), ) ``` ### Q: 如何获取任务进度? A: 可以通过轮询检查任务状态: ```go prediction, err := client.Predictions.Create(ctx, options) if err != nil { log.Fatal(err) } // 定期检查状态 ticker := time.NewTicker(2 * time.Second) defer ticker.Stop() for { select { case <-ticker.C: updated, err := client.Predictions.Get(ctx, prediction.ID) if err != nil { log.Printf("获取状态失败: %v", err) continue } fmt.Printf("状态: %s\n", updated.Status) if updated.Status == "succeeded" || updated.Status == "failed" { return updated, nil } case <-ctx.Done(): return nil, ctx.Err() } } ``` ### Q: 支持哪些文件格式? A: SDK 支持以下文件格式: - **图像**: JPG, PNG, GIF, WebP, BMP, TIFF - **视频**: MP4, AVI, MOV, WebM, MKV - **音频**: MP3, WAV, FLAC, AAC, OGG - **文档**: PDF, TXT, DOC, DOCX ### Q: 如何处理并发请求? A: 使用 goroutine 和同步原语: ```go func processConcurrent(client *speedpix.Client, inputs []map[string]interface{}) []Result { results := make([]Result, len(inputs)) var wg sync.WaitGroup semaphore := make(chan struct{}, 5) // 限制并发数为5 for i, input := range inputs { wg.Add(1) go func(index int, input map[string]interface{}) { defer wg.Done() semaphore <- struct{}{} // 获取许可 defer func() { <-semaphore }() // 释放许可 output, err := client.Run(context.Background(), speedpix.RunOptions{ WorkflowID: "concurrent-task", Input: input, }) results[index] = Result{Output: output, Error: err} }(i, input) } wg.Wait() return results } ``` ## ⚠️ 错误处理 SDK 提供特定的错误类型: ```go output, err := client.Run(ctx, options) if err != nil { var predErr *speedpix.PredictionError if errors.As(err, &predErr) { fmt.Printf("预测失败: %v\n", predErr) if predErr.Prediction != nil { fmt.Printf("预测 ID: %s\n", predErr.Prediction.ID) fmt.Printf("状态: %s\n", predErr.Prediction.Status) } } else { fmt.Printf("API 错误: %v\n", err) } } ``` ## 📚 示例 查看 `examples/` 目录获取完整的工作示例: - `examples/quick-start/` - 基础使用示例 - `examples/typed-usage/` - 类型安全使用示例 - `examples/file-types-demo/` - 文件类型演示 - `examples/real-world-usage/` - 实际使用场景 ## 🛠️ 开发 ### 运行测试 ```bash go test ./... ``` ### 构建 ```bash go build ./... ``` ### 发布新版本 ```bash # 1. 确保所有测试通过 make test-release # 或 go test ./... && go mod tidy && go vet ./... # 2. 创建版本标签 git tag v1.0.0 git push origin v1.0.0 # 3. 用户即可安装新版本 go get github.com/aliyun/speedpix-go@v1.0.0 ``` 更多发布选项请查看 [发布指南](PUBLISHING_GUIDE.md)。 ## 📄 许可证 本项目采用 MIT 许可证 - 查看 LICENSE 文件了解详情。 ## 🤝 贡献 欢迎贡献!请随时提交 Pull Request。 [发布指南](doc/PUBLISHING_GUIDE.md)