> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# 迁移到 v3

> Go SDK v2 与 v3 之间的变化：单一的包、具体的 *Client、ctx 作为第一个参数、资源组、单一的错误类型、超时和重试。附逐个方法的对照表。

v3 是一个破坏性版本。它使用单一的包、具体的 `*Client`，所有地方都以 `ctx` 作为第一个参数，并引入资源组，同时修复了 v2 中所有已知的缺陷。它涵盖当前 API 的全部 67 个操作。

## 概览

|     | v2                                                    | v3                                                                                      |
| --- | ----------------------------------------------------- | --------------------------------------------------------------------------------------- |
| 模块  | `.../v2`（`rest` + `squarecloud` 两个包）                  | `github.com/squarecloudofc/sdk-api-go/v3`（单一的包）                                         |
| 客户端 | `rest.New(rest.NewClient(key, ...))`（接口）              | `squarecloud.New(key, ...Option)`（`*Client`）                                            |
| 调用  | `api.GetApplicationStatus(id, rest.WithContext(ctx))` | `c.Apps.Status(ctx, id)`                                                                |
| 错误  | 带有 `StatusCode` 的 `*rest.APIError`，网络错误没有类型           | 所有错误都是 `*squarecloud.APIError`，带有 `Status`、`Code`、`Message`、`Method`、`Path`             |
| 超时  | 所有调用都使用固定 30 秒 `Timeout` 的 `http.Client`              | 通过 `ctx` 按调用设置；`WithTimeout`；流不受限制                                                      |
| 重试  | 无                                                     | GET 的网络错误以及 503 `UPLOAD_BUSY`/`ANALYTICS_BUSY`/`DATABASE_UNAVAILABLE`（`WithMaxRetries`） |
| 日志  | `WithLogger`（会泄露机密信息）                                 | 无                                                                                       |
| Go  | 1.24                                                  | 1.22 或更新版本                                                                              |
| 许可证 | AGPL-3.0                                              | MIT                                                                                     |

## 构造和选项

```diff theme={"system"}
-import (
-	"github.com/squarecloudofc/sdk-api-go/v2/rest"
-	"github.com/squarecloudofc/sdk-api-go/v2/squarecloud"
-)
-client := rest.NewClient(token, rest.WithUserAgent(ua), rest.WithLogger(logger))
-api := rest.New(client)
-defer client.Close()
+import "github.com/squarecloudofc/sdk-api-go/v3"
+
+c := squarecloud.New(token, squarecloud.WithUserAgent(ua))
```

```bash theme={"system"}
go get github.com/squarecloudofc/sdk-api-go/v3@v3.0.0
```

| v2                                                    | v3                                                               |
| ----------------------------------------------------- | ---------------------------------------------------------------- |
| `rest` + `squarecloud` 两个包                            | 单一的包 `squarecloud`（模块 `.../v3`）                                  |
| `rest.NewClient(token, opts...)` + `rest.New(client)` | `squarecloud.New(token, opts...)`                                |
| `rest.Rest`（接口）                                       | `*squarecloud.Client`（具体结构体）。要对其进行 mock，请声明你自己的小接口或使用 `httptest` |
| `rest.ConfigOpt`                                      | `squarecloud.Option`                                             |
| `rest.WithHTTPClient(hc)`                             | `squarecloud.WithHTTPClient(hc)`。不要设置 `hc.Timeout`：它会切断实时流和下载    |
| `rest.WithURL(u)`                                     | `squarecloud.WithBaseURL(u)`（仍包含 `/v2`）                          |
| `rest.WithUserAgent(ua)`                              | `squarecloud.WithUserAgent(ua)`                                  |
| `rest.WithLogger(l)`                                  | 已移除：SDK 从不输出日志（v2 会在调试日志中泄露机密信息）。如需追踪，请包装 `hc.Transport`         |
| `client.Close()`、`client.HTTPClient()`                | 已移除：请保留你自己的 `*http.Client` 并对其调用 `CloseIdleConnections`          |
| `rest.APIURL`、`rest.APIVersion`、`rest.Endpoint*`      | 已移除；`squarecloud.DefaultBaseURL` 是一个常量                           |
| （无）                                                   | `squarecloud.WithMaxRetries(n)`（新增；默认 2）                         |
| 固定 30 秒的 `http.Client` 超时                             | `squarecloud.WithTimeout(d)`（新增；默认 30 秒，`d <= 0` 会禁用所有默认截止时间）    |

按请求设置的选项：

| v2                                                                                   | v3                                                                                                                                                                                       |
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rest.WithContext(ctx)`                                                              | `ctx` 是每个方法的第一个参数                                                                                                                                                                        |
| `rest.WithToken(token)`（例如在登录时验证密钥）                                                  | 构建一个临时客户端：`squarecloud.New(token).Account.Me(ctx)`（开销很小，不会保持任何连接）                                                                                                                        |
| commit 上的 `rest.WithQueryParam("path", dir)`                                         | `c.Apps.Commit(ctx, id, r, dir, "")`                                                                                                                                                     |
| 分析上的 `rest.WithQueryParam(filter, v)`                                                | `c.Apps.Network.Analytics(ctx, id, start, end, squarecloud.AnalyticsFilters{...})`，可使用 `Country`、`IP`、`Path`、`Status`、`OS`、`Browser`、`Protocol`、`Referer`、`Provider`、`ContentType`、`Bot` |
| `rest.WithQueryParam("include_4xx", "true")`                                         | `c.Apps.Network.Errors(ctx, id, start, end, true)`                                                                                                                                       |
| 列出状态时的 `rest.WithQueryParam("workspaceId", ws)`                                      | `c.Apps.StatusAll(ctx, ws)`                                                                                                                                                              |
| `rest.WithHeader`、`rest.RequestOpt`、`rest.RequestConfig`、`rest.DefaultRequestConfig` | 已移除                                                                                                                                                                                      |

## 逐个方法对照

`api` 是 v2 的 `rest.Rest`，`c` 是 v3 的 `*squarecloud.Client`。

| v2                                                                                      | v3                                                                                | 备注                                                                                                                                                                      |
| --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `api.SelfUser()`                                                                        | `me, err := c.Account.Me(ctx)`，然后使用 `me.User`                                     | 返回 `Account`                                                                                                                                                            |
| `api.GetApplications()`                                                                 | `c.Account.Me(ctx)`，然后使用 `me.Applications`（`[]AppSummary`）                        |                                                                                                                                                                         |
| `api.GetDatabases()`                                                                    | `c.Account.Me(ctx)`，然后使用 `me.Databases`（`[]DatabaseSummary`）                      |                                                                                                                                                                         |
| `api.UserSnapshots(scope)`                                                              | `c.Account.Snapshots(ctx, scope)`                                                 |                                                                                                                                                                         |
| `api.ServiceStatus()`                                                                   | `c.Service.Status(ctx)`                                                           | 新的模型，参见[类型](#类型)                                                                                                                                                        |
| `api.PostApplications(r)` → `*ApplicationUploaded`                                      | `c.Apps.Create(ctx, r)` → `AppCreated`（值类型）                                       | v2 会将 zip 缓冲到内存中，并将该部分命名为 `upload.zip`；v3 以流的方式传输，并以 `*os.File` 的名称（其基本名称）命名该部分，否则为 `app.zip`。`Subdomain` 已移除：请读取 `Domain`，即完整主机（`my-app.squareweb.app`），非 Web 应用为 `""` |
| `api.GetApplication(id)`                                                                | `c.Apps.Get(ctx, id)`                                                             |                                                                                                                                                                         |
| `api.DeleteApplication(id)`                                                             | `c.Apps.Delete(ctx, id)`                                                          |                                                                                                                                                                         |
| `api.PostApplicationSignal(id, squarecloud.ApplicationSignalStart/Stop/Restart)`        | `c.Apps.Start(ctx, id)` / `c.Apps.Stop(ctx, id)` / `c.Apps.Restart(ctx, id)`      |                                                                                                                                                                         |
| `api.PostApplicationCommit(id, r, rest.WithQueryParam("path", p))`                      | `c.Apps.Commit(ctx, id, r, p, filename)`                                          | v2 总是将该部分命名为 `commit.zip`；v3 使用 `filename`，否则使用 `*os.File` 自身的名称，因此单个非 zip 文件现在会以其自身名称放置，而不会被当作 zip 处理而失败                                                               |
| `api.GetApplicationStatus(id)`                                                          | `c.Apps.Status(ctx, id)`                                                          |                                                                                                                                                                         |
| `api.GetApplicationStatusRaw(id)`                                                       | `c.Apps.StatusRaw(ctx, id)`                                                       |                                                                                                                                                                         |
| `api.GetApplicationListStatus()`                                                        | `c.Apps.StatusAll(ctx, "")`                                                       | 返回 `[]StatusListItem`                                                                                                                                                   |
| `api.GetApplicationLogs(id)` → `ApplicationLogs`                                        | `c.Apps.Logs(ctx, id)` → `string`                                                 |                                                                                                                                                                         |
| `api.GetApplicationMetrics(id)`                                                         | `c.Apps.Metrics(ctx, id)`                                                         | 数据点按 API 发送的顺序排列，最新的在前                                                                                                                                                  |
| `api.ApplicationRealtime(id, rest.WithContext(ctx))`                                    | `c.Apps.Realtime(ctx, id)`                                                        | 返回 `*Realtime`；参见[行为变更](#行为变更)                                                                                                                                          |
| `api.GetApplicationDomains()`                                                           | `c.Apps.Domains(ctx)`                                                             |                                                                                                                                                                         |
| `api.GetLoadBalancers()`                                                                | `c.Apps.LoadBalancers(ctx)`                                                       |                                                                                                                                                                         |
| `api.GetApplicationEnvs(id)`                                                            | `c.Apps.Envs.Get(ctx, id)`                                                        |                                                                                                                                                                         |
| `api.SetApplicationEnvs(id, envs)`                                                      | `c.Apps.Envs.Set(ctx, id, envs)`                                                  |                                                                                                                                                                         |
| `api.ReplaceApplicationEnvs(id, envs)`                                                  | `c.Apps.Envs.Replace(ctx, id, envs)`                                              |                                                                                                                                                                         |
| `api.DeleteApplicationEnvs(id, keys)` → `error`                                         | `c.Apps.Envs.Delete(ctx, id, keys...)` → `(EnvVars, error)`（剩余的变量）                |                                                                                                                                                                         |
| `api.GetApplicationFiles(id, path)` → `[]FileInfo`                                      | `c.Apps.Files.List(ctx, id, path)` → `[]FileEntry`                                | 不存在的目录现在返回 404 `FILE_NOT_FOUND`（以前是空列表）；受保护的路径返回 403 `BLOCKED_PATH`                                                                                                     |
| `api.ReadApplicationFile(id, path)` → `FileContent`                                     | `c.Apps.Files.Read(ctx, id, path)` → `[]byte`                                     | 以 base64 请求并解码；超过 10 MB 的文件返回 413 `FILE_TOO_LARGE`                                                                                                                      |
| `api.PutApplicationFile(id, path, b)` → `(FileWritten, error)`                          | `c.Apps.Files.Write(ctx, id, path, b)` → `error`。去掉所有 `written` 检查：成功即为 `nil` 错误  | 内容始终以 base64 编码发送，因此二进制文件是安全的；空内容会写入一个空文件                                                                                                                               |
| `api.MoveApplicationFile(id, from, to)`                                                 | `c.Apps.Files.Move(ctx, id, path, to)`                                            |                                                                                                                                                                         |
| `api.DeleteApplicationFile(id, path)`                                                   | `c.Apps.Files.Delete(ctx, id, path)`                                              | 现在可以正常工作（在 v2 中总是返回 400）                                                                                                                                                |
| `api.GetApplicationSnapshots(id)`                                                       | `c.Apps.Snapshots.List(ctx, id)`                                                  | 每个 `Snapshot` 现在都携带来自 API 的 `VersionID` 和 `URL`（已签名的下载链接）                                                                                                               |
| `api.CreateApplicationSnapshot(id)`                                                     | `c.Apps.Snapshots.Create(ctx, id)`                                                | 在使用 `.URL` 之前检查 `.Pending`（202）                                                                                                                                         |
| `api.RestoreApplicationSnapshot(id, snapID, verID)`                                     | `c.Apps.Snapshots.Restore(ctx, id, snap.Name, snap.VersionID)`                    | `VersionID` 是 API 发送的字段：不再需要从 `Key` 中解析任何内容。错误请参见 [Snapshots](/zh/sdks/go/snapshots#恢复-snapshot)                                                                        |
| `api.GetApplicationDeployments(id)`                                                     | `c.Apps.Deploys.List(ctx, id)`                                                    |                                                                                                                                                                         |
| `api.GetApplicationCurrentDeployment(id)`                                               | `c.Apps.Deploys.Current(ctx, id)`                                                 |                                                                                                                                                                         |
| `api.PostApplicationDeployWebhook(id, token)` → `GithubWebhook`                         | `c.Apps.Deploys.SetWebhook(ctx, id, token)` → `string`                            |                                                                                                                                                                         |
| `api.LinkApplicationGithubApp(id, repo, branch)` → `GithubAppLink`                      | `c.Apps.Deploys.LinkGithubApp(ctx, id, repo, branch)` → `LinkedRepository`        | 现在可以使用 API 密钥（作用域 `apps:deploy`）；`repository` 包装已移除；未连接 GitHub 的账户返回 403 `GITHUB_NOT_CONNECTED`                                                                         |
| `api.UnlinkApplicationGithubApp(id)`                                                    | `c.Apps.Deploys.UnlinkGithubApp(ctx, id)`                                         | 没有关联时返回 400 `GIT_NOT_CONFIGURED`                                                                                                                                        |
| `api.GetApplicationDNS(id)`                                                             | `c.Apps.Network.DNS(ctx, id)`                                                     |                                                                                                                                                                         |
| `api.SetApplicationCustomDomain(id, d)`                                                 | `c.Apps.Network.SetDomain(ctx, id, d)`                                            |                                                                                                                                                                         |
| `api.GetApplicationAnalytics(id, s, e, opts...)`                                        | `c.Apps.Network.Analytics(ctx, id, s, e, squarecloud.AnalyticsFilters{...})`      | 返回 `*NetworkAnalytics`，没有流量的窗口为 `nil`                                                                                                                                   |
| `api.GetApplicationNetworkErrors(id, s, e, opts...)`                                    | `c.Apps.Network.Errors(ctx, id, s, e, include4xx)`                                | 返回 `*NetworkErrors`，为空时为 `nil`                                                                                                                                          |
| `api.GetApplicationNetworkLogs(id, s, e)`                                               | `c.Apps.Network.Logs(ctx, id, s, e)`                                              |                                                                                                                                                                         |
| `api.GetApplicationNetworkPerformance(id, s, e)`                                        | `c.Apps.Network.Performance(ctx, id, s, e)`                                       | 返回 `*NetworkPerformance`，为空时为 `nil`                                                                                                                                     |
| `api.PurgeApplicationCache(id)`                                                         | `c.Apps.Network.PurgeCache(ctx, id)`                                              |                                                                                                                                                                         |
| `api.CreateDatabase(opts)`                                                              | `c.Databases.Create(ctx, squarecloud.DatabaseCreate{...})`                        |                                                                                                                                                                         |
| `api.GetDatabase(id)`                                                                   | `c.Databases.Get(ctx, id)`                                                        |                                                                                                                                                                         |
| `api.UpdateDatabase(id, opts)`                                                          | `c.Databases.Update(ctx, id, squarecloud.DatabaseUpdate{...})`                    |                                                                                                                                                                         |
| `api.DeleteDatabase(id)`                                                                | `c.Databases.Delete(ctx, id)`                                                     |                                                                                                                                                                         |
| `api.StartDatabase(id)` / `api.StopDatabase(id)`                                        | `c.Databases.Start(ctx, id)` / `c.Databases.Stop(ctx, id)`                        |                                                                                                                                                                         |
| `api.GetDatabaseStatus(id)` / `api.GetDatabaseStatusRaw(id)`                            | `c.Databases.Status(ctx, id)` / `c.Databases.StatusRaw(ctx, id)`                  |                                                                                                                                                                         |
| `api.GetDatabaseListStatus()`                                                           | `c.Databases.StatusAll(ctx)`                                                      | 返回 `[]StatusListItem`                                                                                                                                                   |
| `api.GetDatabaseMetrics(id)`                                                            | `c.Databases.Metrics(ctx, id)`                                                    |                                                                                                                                                                         |
| `api.GetDatabaseCertificate(id)` → `DatabaseCertificate`                                | `c.Databases.Certificate(ctx, id)` → `string`（base64 PEM）                         |                                                                                                                                                                         |
| `api.ResetDatabaseCredentials(id, t)` → `DatabasePasswordReset`                         | `c.Databases.ResetCredentials(ctx, id, t)` → `string`                             | 新密码；重置证书时为 `""`                                                                                                                                                         |
| `api.GetDatabaseSnapshots` / `CreateDatabaseSnapshot` / `RestoreDatabaseSnapshot`       | `c.Databases.Snapshots.List` / `Create` / `Restore`                               | 与应用相同：使用 `snap.Name` 和 `snap.VersionID` 恢复                                                                                                                              |
| `api.GetWorkspaces()`                                                                   | `c.Workspaces.List(ctx)`                                                          |                                                                                                                                                                         |
| `api.GetWorkspace(id)`                                                                  | `c.Workspaces.Get(ctx, id)`                                                       |                                                                                                                                                                         |
| `api.CreateWorkspace(name)`                                                             | `c.Workspaces.Create(ctx, name)`                                                  |                                                                                                                                                                         |
| `api.DeleteWorkspace(id)`                                                               | `c.Workspaces.Delete(ctx, id)`                                                    |                                                                                                                                                                         |
| `api.LeaveWorkspace(id)`                                                                | `c.Workspaces.Leave(ctx, id)`                                                     |                                                                                                                                                                         |
| `api.AddWorkspaceMember(ws, code, group)`                                               | `c.Workspaces.Members.Add(ctx, ws, code, group)`                                  |                                                                                                                                                                         |
| `api.UpdateWorkspaceMember(ws, member, group)`                                          | `c.Workspaces.Members.Update(ctx, ws, member, group)`                             |                                                                                                                                                                         |
| `api.RemoveWorkspaceMember(ws, member)`                                                 | `c.Workspaces.Members.Remove(ctx, ws, member)`                                    |                                                                                                                                                                         |
| `api.GetWorkspaceInviteCode()` → `WorkspaceInviteCode`                                  | `c.Workspaces.Members.InviteCode(ctx)` → `string`                                 |                                                                                                                                                                         |
| `api.AddWorkspaceApplication(ws, app)` / `RemoveWorkspaceApplication`                   | `c.Workspaces.Apps.Add(ctx, ws, app)` / `Remove`                                  |                                                                                                                                                                         |
| 自行下载 snapshot URL（`http.Get`）                                                           | `c.DownloadSnapshot(ctx, url, w)`                                                 | 以流的方式写入任意 `io.Writer`；从不发送密钥                                                                                                                                            |
| `rest.IsRateLimit(err)`                                                                 | `errors.As(err, &apiErr) && apiErr.Status == 429`                                 | 已移除                                                                                                                                                                     |
| `rest.ErrorCode(err)`                                                                   | `errors.As(err, &apiErr)`，然后使用 `apiErr.Code`                                      | 已移除                                                                                                                                                                     |
| `client.Request(...)`、`client.Stream(...)`（`rest.Client`）                               | 上面的类型化方法                                                                          | 已移除：每个操作都有对应的方法                                                                                                                                                         |
| `rest.NewApplications(client)`、`rest.NewDatabases(client)`、`rest.NewWorkspaces(client)` | `squarecloud.New(key)`，然后使用 `c.Apps`、`c.Databases`、`c.Workspaces` 字段              | 已移除                                                                                                                                                                     |
| `rest.Applications`、`rest.Databases`、`rest.Workspaces`（接口）                              | `squarecloud.AppsAPI`、`DatabasesAPI`、`WorkspacesAPI`（这些字段的类型）                     | 已移除；如需 mock，请声明你自己的接口                                                                                                                                                   |
| `rest.Config`、`rest.DefaultConfig()`、`(*rest.Config).Apply(opts)`                       | `squarecloud.New(key, opts...)`，配合 `WithHTTPClient`、`WithBaseURL`、`WithUserAgent` | 已移除（请使用 `Option`；没有 logger）                                                                                                                                             |
| `(*rest.RequestConfig).Apply(opts)`                                                     | 传入 `ctx` 和类型化参数                                                                   | 已移除                                                                                                                                                                     |
| `(*rest.RealtimeStream).Next()` / `Close()`                                             | `(*squarecloud.Realtime).Next()` / `Close()`                                      | 在 `REALTIME_DISCONNECTED` 之后，`Next` 返回 `io.EOF`                                                                                                                         |
| （无）                                                                                     | `c.AI.Chat(ctx, squarecloud.ChatRequest{...})`                                    | 新增                                                                                                                                                                      |

## 类型

| v2（`squarecloud.`）                                                                                     | v3（`squarecloud.`）                                                                                                                                                                                                                 |
| ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `User`（来自 `SelfUser`）                                                                                  | `User`（位于 `Account` 中，即 `Account.Me` 的结果）                                                                                                                                                                                          |
| `UserPlan`、`UserPlanMemory`                                                                            | `Plan`、`PlanMemory`。`Plan.Duration` 是以 Unix **毫秒**表示的到期时间（`*int64`，永不到期时为 `nil`）：请使用 `time.UnixMilli` 而不是 `time.Unix` 进行转换                                                                                                         |
| `UserApplication`、`UserDatabase`（`Type string`）                                                        | `AppSummary`、`DatabaseSummary`（`Type DatabaseType`）                                                                                                                                                                                |
| `Application`                                                                                          | `App`                                                                                                                                                                                                                              |
| `ApplicationUploaded`（`CPU int`）、`ApplicationLanguage`                                                 | `AppCreated`（`CPU float64`）、`AppLanguage`                                                                                                                                                                                          |
| `ApplicationStatus`、`DatabaseStatus`                                                                   | `RuntimeStats`（共用）                                                                                                                                                                                                                 |
| `ApplicationStatusRaw`、`DatabaseStatusRaw`                                                             | `RuntimeStatsRaw`                                                                                                                                                                                                                  |
| `ApplicationStatusNetwork`、`ApplicationStatusNetworkRaw`                                               | `StatsNetwork`、`StatsNetworkRaw`                                                                                                                                                                                                   |
| `ApplicationStatusListItem`、`DatabaseStatusListItem`                                                   | `StatusListItem`                                                                                                                                                                                                                   |
| `ApplicationLogs`                                                                                      | `string`                                                                                                                                                                                                                           |
| `ApplicationSignal*`                                                                                   | 已移除（请使用 `Start`/`Stop`/`Restart`）                                                                                                                                                                                                  |
| `FileInfo`（`Type FileType`、`LastModified int64`）、`FileType*` 常量                                        | `FileEntry`（`Type string`、`LastModified *float64`）：`"file"`/`"directory"`；API 发送带小数的 Unix 毫秒时间，或 `null`                                                                                                                            |
| `FileContent`、`ByteArray`                                                                              | `[]byte`                                                                                                                                                                                                                           |
| `FileWritten`                                                                                          | 已移除（未公开记录的字段）                                                                                                                                                                                                                      |
| `Deployment`（`State DeploymentState`）                                                                  | `DeployEvent`（`State`、`Source`、`Code`、`Message` 均为 `string`）。`Source` 是新增字段，始终为 `"git"`；`"error"` 事件携带 `Code`（例如 `CLONE_FAILED`），有时还携带 `Message`                                                                                   |
| `DeploymentState*`（`DeploymentStateError` = `"error"`）                                                 | `Deploy*` 字符串常量（`DeployPending`、`DeployClone`、`DeployCommit`、`DeployRestarting`、`DeploySuccess`、`DeployError` = `"error"`）                                                                                                         |
| `DeploymentFiles`、`DeploymentCurrent`、`DeploymentGithubApp`                                            | `DeployFiles`、`DeployCurrent`、`DeployRepository`                                                                                                                                                                                   |
| `GithubWebhook`                                                                                        | `string`                                                                                                                                                                                                                           |
| `GithubAppLink`、`GithubAppRepository`                                                                  | 带有 `ID`、`FullName`、`Branch` 的 `LinkedRepository`（直接返回，没有 `Repository` 包装）                                                                                                                                                          |
| `Snapshot`                                                                                             | `Snapshot` + `VersionID`、`URL`、`Runtime`、`Origin`（API 发送的所有字段）                                                                                                                                                                     |
| `SnapshotCreated`                                                                                      | `SnapshotCreated` + `Pending`                                                                                                                                                                                                      |
| 带有 `DatabaseTypeMongo`、`DatabaseTypeMySQL`、`DatabaseTypeRedis`、`DatabaseTypePostgres` 的 `DatabaseType` | 带有 `DatabaseMongo`、`DatabaseMySQL`、`DatabaseRedis`、`DatabasePostgres` 的 `DatabaseType`（类型不变，常量已重命名）                                                                                                                                |
| `DatabaseCreateOptions`、`DatabaseUpdateOptions`                                                        | `DatabaseCreate`、`DatabaseUpdate`                                                                                                                                                                                                  |
| `DatabaseCreated`（`CPU int`、`Certificate string`）                                                      | `DatabaseCreated`（`CPU float64`、`Certificate *string`，API 未发送时为 `nil`）                                                                                                                                                             |
| `DatabaseResetType`、`DatabaseResetPassword`、`DatabaseResetCertificate`                                 | `DatabaseReset`、`ResetPassword`、`ResetCertificate`                                                                                                                                                                                 |
| `DatabaseCertificate`、`DatabasePasswordReset`                                                          | `string`                                                                                                                                                                                                                           |
| `WorkspaceMemberGroup`、`WorkspaceGroup*`                                                               | 输入：`WorkspaceGroup`（`GroupAdmin`、`GroupMaintain`、`GroupManager`、`GroupView`）；`WorkspaceMember.Group` 是 `string`（可能为 `"owner"`）                                                                                                     |
| `WorkspaceMember`（`Name string`）                                                                       | `WorkspaceMember`（`Name *string`，API 发送 `null` 时为 `nil`）。Workspace ID 为 32 或 40 个十六进制字符                                                                                                                                            |
| `WorkspaceInviteCode`                                                                                  | `string`                                                                                                                                                                                                                           |
| `ServiceStatus`（`Status`、`Message`）                                                                    | `ServiceStatus`（`Status`、`Message`、`CheckedAt`、`Stale`、`Services`、`Dependencies`）。`Status` 现在是例如 `"online"` 这样的值；条目为 `ServiceEntry`                                                                                                |
| `rest.RealtimeStream`                                                                                  | `*squarecloud.Realtime`（`Next`、`Close`）                                                                                                                                                                                            |
| `RealtimeEvent`（`Event`、`Data`）                                                                        | `RealtimeEvent`（`Event`、`Data`、`ID`、`Stream`、`Line`、`Status`）                                                                                                                                                                      |
| 分析上的查询选项                                                                                               | `AnalyticsFilters`（没有 `Start`/`End`：它们是参数）                                                                                                                                                                                         |
| `NetworkErrorsSummaryClass`（`Class4xx`、`Class5xx`）                                                     | `NetworkErrorsSummary.ByClass`，一个键为 `"4xx"` 和 `"5xx"` 的 `map[string]int64`                                                                                                                                                         |
| `NetworkErrorsByStatus`、`NetworkErrorsTimeseries`、`NetworkErrorsTopPath`、`NetworkErrorsByMethod`       | `NetworkErrorsStatus`、`NetworkErrorsBucket`、`NetworkErrorsPath`、`NetworkErrorsMethod`                                                                                                                                              |
| `NetworkLatency`、`NetworkPerformance*`                                                                 | `Percentiles`（`P50`/`P95`/`P99` 为 `*float64`，没有请求的窗口为 `nil`）、`PerformanceSummary`、`PerformanceBucket`、`PerformanceRegion`（国家和节点；`P50`/`P95` 为 `*float64`，`City`/`Country` 为 `*string`）、`PerformancePath`（`P95`/`P99` 为 `*float64`） |
| `RealtimeStatus`                                                                                       | `RealtimeStatus.CPULimit` 是核心数（例如 `1`、`0.5`）                                                                                                                                                                                       |
| 分析中的服务提供商值                                                                                             | `"NAME (ASN)"`（例如 `"GOOGLE (15169)"`）；`AnalyticsFilters.Provider` 接受该确切值                                                                                                                                                           |
| `AppDomainType*`                                                                                       | `AppDomain.Type` 是 `string`                                                                                                                                                                                                        |
| `APIResponse[T]`                                                                                       | 已移除（内部类型）                                                                                                                                                                                                                          |
| `int` 类型的大小和计数器（`FileInfo.Size`、`Snapshot.Size`、分析的 `Visits`/`Requests`、网络错误的总计和 map、性能的 `Requests`）   | `int64`                                                                                                                                                                                                                            |

## 错误

`rest.APIError`（`StatusCode`、`Code`、`Message`）变为 `squarecloud.APIError`（`Status`、`Code`、`Message`、`Method`、`Path`）：请将 `StatusCode` 重命名为 `Status`。`rest.ErrorCode(err)` 和 `rest.IsRateLimit(err)` 已被移除：请使用 `errors.As` 并检查 `Code` 或 `Status == 429`。

```go theme={"system"}
// v2
if rest.IsRateLimit(err) { ... }

// v3
var apiErr *squarecloud.APIError
if errors.As(err, &apiErr) && apiErr.Status == 429 {
	fmt.Println(apiErr.Code, apiErr.Message) // KEEP_CALM or RATE_LIMITED
}
```

* 网络失败现在是 `*APIError`，`Status` 为 `0`，`Code` 为 `NETWORK_ERROR` 或 `TIMEOUT`，`Message` 为原因的文本，并且可以解包为原因（`errors.Is(err, context.Canceled)` 能正常工作）。
* 本地检查（`Status` 为 `0`：`INVALID_ID`、`FILE_TOO_LARGE`、`INVALID_API_KEY`）以及不是 JSON 的 2xx 响应体（`UNKNOWN_ERROR`，`Invalid JSON in HTTP <status> response`）也是如此。
* 声明 `"status": "error"` 的 2xx 响应体现在被视为错误（v2 将其报告为成功）。应用和数据库启动/停止时集群的拒绝会以 409 `CONTAINER_ALREADY_STARTED`、`CONTAINER_ALREADY_STOPPED`、`CONTAINER_TEMPORARILY_SUSPENDED`、`CONTAINER_NOT_FOUND`、`CONTAINER_INSUFFICIENT_DISK_SPACE`、`CONTAINER_NETWORK_CONFLICT` 或 `ACTION_FAILED` 返回，且没有消息。SDK 会将“已经……”类的响应作为错误返回：如有需要，请自行将其视为成功。
* 没有代码的响应的 `Code` 为 `UNKNOWN_ERROR`。
* 已过期的 API 密钥与未知密钥一样返回 401 `ACCESS_DENIED`。
* API 公开记录的每个代码都有一个 `Code*` 常量。API 现在在原先发送 `RATE_LIMIT` 和 `RATE_LIMIT_EXCEEDED` 的地方发送 429 `RATE_LIMITED`（`CodeRateLimited`）；`CodeRateLimit` 和 `CodeRateLimitExceeded` 仍然保留，但已弃用。
* 每个 `AI.Chat` 错误都采用 OpenAI 格式，带有小写代码（`access_denied`、`rate_limit_exceeded`、`server_overloaded`……），`Code` 会原样携带这些代码。
* `Error()` 输出 `squarecloud: <METHOD> <path>: HTTP <status> <CODE>: <message>`（v2：`squarecloud: <message> (<CODE>, HTTP <status>)`）。请根据字段进行匹配，而不是依赖文本。

完整参考请参见[错误](/zh/sdks/go/errors)。

## 行为变更

* **空 API 密钥：** `New("")`（或仅含空白字符的密钥）仍然返回一个客户端（它无法返回错误），但除 `Service.Status` 外的每个调用都会在本地以 `INVALID_API_KEY` 失败。
* **Snapshot 202：** v2 返回 `StatusCode` 为 202 的 `*APIError`。v3 返回 `Pending: true` 的 `SnapshotCreated`，错误为 `nil`。
* **实时：** `Next` 现在返回 `RealtimeEvent`。请根据 `ev.Event`（`system`、`status`、`logs`、`error`、`message`）进行分支处理。对于日志，打印 `ev.Line`（`\u0001`/`\u0002` 字节已被去除；`ev.Data` 保持为原始帧），并使用 `ev.Stream` 区分 stdout/stderr。对于状态，请使用 `ev.Status`：在状态事件中永远不为 `nil`，并在各帧和重新连接之间进行浅合并。在 `REALTIME_DISCONNECTED` 之后，`Next` 返回 `io.EOF`。流不再在 30 秒后中断，重新连接会在上一次打开后至少等待 5.5 秒，并且在响应头到达之前，打开阶段受客户端超时的限制。参见[实时](/zh/sdks/go/realtime)。
* **超时：** v2 对所有调用使用固定 30 秒的 `http.Client` 超时。v3 仅在 `ctx` 没有截止时间时才应用默认截止时间：大多数调用使用客户端超时（`WithTimeout`，30 秒）；启动/停止/重启、数据库创建、snapshot 创建/恢复以及 `AI.Chat` 至少为 2 分钟；上传、内容超过 1 MiB 的文件写入以及 snapshot 下载则没有截止时间。`WithTimeout(0)` 会禁用所有这些截止时间。
* **空的网络窗口：** 当窗口内没有流量时，`Analytics`、`Errors` 和 `Performance` 返回 `nil` 指针。
* **请求头：** 每个 API 请求都会发送 `Accept: application/json`（实时则为 `text/event-stream`）。默认的 `User-Agent` 从 `Square GO` 改为 `squarecloud-sdk-go/3.0.0`（`WithUserAgent` 仍然可以覆盖它）。
* **ID：** 每个 ID 现在都会作为单个路径段进行百分号编码（v2 会将其原样拼接到路径中），空的、`.` 或 `..` 的 ID 会在本地以 `INVALID_ID` 失败。
* **文件写入：** v2 总是以字符串发送内容，这会损坏二进制文件，并且无法写入空文件。v3 始终以 base64 编码发送内容，因此每个字节都能完整往返，空内容会写入一个空文件，超过 10 MB 的内容会在本地以 `FILE_TOO_LARGE` 失败。对于无法解码的内容，API 返回 400 `INVALID_CONTENT`。
* **文件读取：** v3 始终以 base64 请求并解码，而不是像 v2 那样读取 JSON 字节数组（API 已弃用该格式）。超过 10 MB 的文件返回 413 `FILE_TOO_LARGE`。
* **文件列表：** 列出不存在的目录会返回 404 `FILE_NOT_FOUND`；以前返回的是空列表。
* **Snapshots：** 列表条目携带来自 API 的 `VersionID` 和 `URL`；不再从 `Key` 中解析任何内容。
* **重试：** 新增。GET 的网络错误、503 `UPLOAD_BUSY`/`ANALYTICS_BUSY` 以及 GET 上的 503 `DATABASE_UNAVAILABLE` 默认重试两次；`WithMaxRetries(0)` 可恢复 v2 的行为。`DATABASE_UNAVAILABLE` 可能在变更操作已经开始之后才到达，因此 SDK 从不在其他方法上重试它；如有需要，请自行重试幂等的变更操作。参见[重试](/zh/sdks/go/errors#重试)。
* **Go 版本：** 最低版本从 Go 1.24 降至 Go 1.22。
