

这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段，并于 2023 年 6 月 1 日终止支持。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 AWS CDK 中使用 Go
<a name="work-with-cdk-go"></a>

 Go是 C AWS loud Development Kit (AWS CDK) 完全支持的客户端语言，被认为是稳定的。在 Go 中使用 AWS CDK 使用熟悉的工具。 AWS CDK 的 Go 版本甚至使用 Go 风格的标识符。

与 CDK 支持的其他语言不同，Go 不是面向对象的传统编程语言。Go 使用组合，而其他语言经常利用继承。我们已经尝试尽可能使用惯用的 Go 方法，但是 CDK 在某些地方可能会有所不同。

本主题为中Go使用 AWS CDK 提供了指导。有关 AWS CDK的简单Go项目的演练，请参阅[公告博客文章](https://aws.amazon.com/blogs/developer/getting-started-with-the-aws-cloud-development-kit-and-go/)。

## 开始使用 Go
<a name="go-prerequisites"></a>

要使用 AWS CDK，您必须拥有 AWS 账户和凭证，并已安装 Node.js 和 AWS CDK 工具包。请参阅 [AWS CDK 入门](getting-started.md)。

 AWS CDK 的Go绑定使用标准 [Go 工具链](https://golang.org/dl/)，即 v1.23 或更高版本。您可以使用自己选择的编辑器。

**注意**  
第三方语言弃用：语言版本仅在供应商或社区共享其 EOL（生命周期终止）之前才受支持，如有更改，会另行通知。

## 创建项目
<a name="go-newproject"></a>

您可以通过在空目录`cdk init`中调用来创建新的 AWS CDK 项目。使用 `--language` 选项并指定 `go`：

```
mkdir my-project
cd my-project
cdk init app --language go
```

 `cdk init` 使用项目文件夹的名称来命名项目的各种元素，包括类、子文件夹和文件。文件夹名称中的连字符都将转换为下划线。但是，名称应遵循 Go 标识符的形式；例如，名称不应以数字开头，也不应包含空格。

生成的项目包括对核心 AWS CDK Go 模块的引用。`github.com/aws/aws-cdk-go/awscdk/v2` `go.mod`发出 `go get` 命令以安装此模块和其他所需模块。

## 管理 AWS 构造库模块
<a name="go-managemodules"></a>

在大多数 AWS CDK 文档和示例中，“模块” 一词通常用于指 AWS 构造库模块，每个 AWS 服务一个或多个模块，这与该术语的惯Go用法不同。CDK 构造库在一个Go模块中提供，其中包含单独的构造库模块，这些模块支持在该模块中作为Go包提供的各种 AWS 服务。

某些服务的 AWS 构造库支持位于多个构造库模块（Go包）中。例如，Amazon Route 53 除了有 `awsroute53` 主包之外，还有三个构造库模块，分别名为 `awsroute53patterns`、`awsroute53resolver` 和 `awsroute53targets`。

你在大多数 AWS CDK 应用程序中都需要的 AWS CDK 的核心软件包是以Go代码形式导入的。`github.com/aws/aws-cdk-go/awscdk/v2`Construct Library AWS 中各种服务的软件包位于`github.com/aws/aws-cdk-go/awscdk/v2`。例如，Amazon S3 模块的命名空间为 `github.com/aws/aws-cdk-go/awscdk/v2/awss3`。

```
import (
        "github.com/aws/aws-cdk-go/awscdk/v2/awss3"
        // ...
)
```

为想要在应用程序中使用的服务导入构造库模块（Go 软件包）后，您就可以使用 `awss3.Bucket` 等来访问该模块中的构造。

## 在 Go 中管理依赖项
<a name="work-with-cdk-go-dependencies"></a>

在 Go 中，依赖项版本是在 `go.mod` 中定义的。默认 `go.mod` 与此处显示的类似。

```
module my-package

go 1.16

require (
  github.com/aws/aws-cdk-go/awscdk/v2 v2.16.0
  github.com/aws/constructs-go/constructs/v10 v10.0.5
  github.com/aws/jsii-runtime-go v1.29.0
)
```

包名称（即 Go 语言中所说的模块）由 URL 进行指定，并附加了所需的版本号。Go 的模块系统不支持版本范围。

发出 `go get` 命令以安装所有所需的模块并更新 `go.mod`。要查看依赖项的可用更新列表，请发出 `go list -m -u all` 命令。

## AWS CDK 中的成语 Go
<a name="go-cdk-idioms"></a>

### 字段和方法名称
<a name="go-naming"></a>

字段和方法名称在 CDK 的起源语言中 TypeScript使用驼色大小写 (`likeThis`)。在 Go 中，这些名称遵循 Go 惯例，即采用帕斯卡命名法（`LikeThis`）。

### 清理
<a name="go-cdk-jsii-close"></a>

在您的 `main` 方法中，请使用 `defer jsii.Close()` 来确保 CDK 应用程序自行清理。

### 缺失值和指针转换
<a name="go-missing-values"></a>

在中Go， AWS CDK 对象（例如属性包）中的缺失值用表示。`nil` Go没有可为空的类型；唯一可以包含的类型`nil`是指针。因此，为了让值变得可选，所有 CDK 属性、参数和返回值都是指针，即便对于原始类型也是如此。这同时适用于必需值和可选值，因此，如果必需值后来变为可选值，则无需对类型进行重大更改。

传递字面值或表达式时，请使用以下辅助函数来创建指向这些值的指针。
+  `jsii.String` 
+  `jsii.Number` 
+  `jsii.Bool` 
+  `jsii.Time` 

例如，以字符串而不是指向字符串的指针来接收构造的 `id` 似乎更方便，但为了保持一致性，我们还是建议您在定义自己的构造时以类似方式使用指针。

在处理可选的 AWS CDK 值（包括原始值和复杂类型）时，在对指针执行任何操作`nil`之前，应明确测试指针以确保它们不是。Go 不像其他一些语言有“语法糖”来帮助处理空值或缺失值。但是，属性捆绑包和类似结构中的必需值是保证存在的（否则构造会失败），因此无需对这些值进行 `nil` 检查。

### 构造和 Props
<a name="go-props"></a>

代表一个或多个 AWS 资源及其关联属性的构造在中表示Go为接口。例如，`awss3.Bucket` 是一个接口。每个构造都有一个工厂函数，例如 `awss3.NewBucket`，用于返回实现相应接口的结构。

所有工厂函数都采用三个参数：`scope`在其中定义构造的（其父级在构造树中）`id`、一个`props`，以及构造用来配置其创建的资源的一 key/value 组对。 AWS CDK 的其他地方也使用 “属性包” 模式。

在 Go 中，每个构造的 props 都由特定的结构类型表示。例如，`awss3.Bucket` 采用类型为 `awss3.BucketProps` 的 props 参数。使用结构体字面量来编写 props 参数。

```
var bucket = awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{
    Versioned: jsii.Bool(true),
})
```

### 通用结构
<a name="go-generic-structures"></a>

在某些地方， AWS CDK 使用 JavaScript 数组或非类型化对象作为方法的输入。（例如， AWS CodeBuild请参阅[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html#static-fromwbrobjectvalue)的方法。） 在 Go 中，这些对象分别表示为切片和空接口。

CDK 提供了可变辅助函数，例如 `jsii.Strings`，用于构建包含原始类型的切片。

```
jsii.Strings("One", "Two", "Three")
```

### 使用任何切片
<a name="go-any-slice"></a>

某些构造期望的属性是多种类型的列表（中的联合类型 TypeScript）。在 Go 中，这些是任何（`*[]any`）的切片。`any` 确保编译器在那里允许不同类型的分配。请参阅 ` [AWS CDK Go package](https://pkg.go.dev/github.com/aws/aws-cdk-go/awscdk/v2) ` 的文档，了解允许的类型有哪些。

要使用此类属性，请使用 `jsii` 提供的帮助程序函数创建不同类型的任意切片：
+  `jsii.AnySlice` 
+  `jsii.AnyStrings` 
+  `jsii.AnyNumbers` 

例如：

```
func Arns() *[]*string {
a := "arn:aws:s3:::bucket1"
b := "arn:aws:s3:::bucket2"
return &[]*string{&a, &b}
}

awsiam.NewCfnUser(stack, jsii.String("User"), &awsiam.CfnUserProps{
	ManagedPolicyArns: jsii.AnySlice(Arns())
  // or
	ManagedPolicyArns: jsii.AnyStrings("arn:aws:s3:::bucket1", "arn:aws:s3:::bucket2")
  // or
  ManagedPolicyArns: &[]interface{}{
    jsii.String("arn:aws:s3:::bucket1"),
    jsii.String("arn:aws:s3:::bucket2"),
  }
})
```

这种方法确保 CDK 正确解释您的切片，从而避免在部署或合成堆栈时出现反序列化错误。

### 开发自定义构造
<a name="go-writing-constructs"></a>

在 Go 中，编写新构造通常比扩展现有构造更简单。首先，定义一个新的结构类型，如果需要类似扩展的语义，则匿名嵌入一个或多个现有类型。为您要添加的任何新功能以及保存需要的数据所需的字段编写方法。如果您的构造需要 props 接口，则请定义一个。最后，编写一个工厂函数 `NewMyConstruct()` 来返回构造的实例。

如果您只是在现有构造上更改一些默认值，或者在实例化时添加一个简单的行为，则不需要所有这些管道。相反，写一个工厂函数来调用您正在“扩展”的构造的工厂函数。例如，在其他 CDK 语言中，您可以创建一个 `TypedBucket` 构造，通过覆盖 `s3.Bucket` 类型来强制执行 Amazon S3 存储桶中对象的类型，然后在新类型的初始化程序中添加一个存储桶策略，该策略仅允许向存储桶添加指定的文件扩展名。在 Go 中，可以更容易简单编写一个 `NewTypedBucket` 来返回您已在其中添加了适当存储桶策略的 `s3.Bucket`（使用 `s3.NewBucket` 进行实例化）。不需要新的构造类型，因为标准存储桶构造中已经提供了该功能；新的“构造”只是提供了一种更简单的配置方式。

## 构建、合成和部署
<a name="go-running"></a>

 AWS CDK 会在运行您的应用程序之前自动对其进行编译。但是，手动构建应用程序以检查错误并运行测试可能会很有用。可以在项目的根目录中在命令提示符下发出 `go build` 命令来执行此操作。

在命令提示符下运行 `go test` 命令来运行您编写的所有测试。

## 问题排查
<a name="go-troubleshooting"></a>

如果遇到如下所示的编译器错误，则意味着字符串切片直接传递给需要切片的属性。

```
Cannot use 'jsii.Strings("arn:aws:s3:::bucket1", "arn:aws:s3:::bucket2")' (type *[]*string) as the type *[]interface{}
```

要解决此错误，请将 `jsii.Strings()` 替换为 `jsii.AnyStrings()`。有关更多背景信息和其他解决方案，请参阅此 ` [CDK GitHub issue](https://github.com/aws/aws-cdk/issues/35630) `。