

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

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

# 使用 AWS CDK 库
<a name="work-with"></a>

导入并使用 AWS 云开发工具包 (AWS CDK) 库，以使用[支持的编程语言](languages.md)来定义您的 AWS 云基础设施。

## 导入 AWS CDK 库
<a name="work-with-library"></a>

通常通过 [AWS CDK 库](libraries.md) 的 TypeScript 包名称 `aws-cdk-lib` 来引用该库。实际的包名称因语言而异。以下是如何安装和导入 CDK 库的示例：

**Example**  


|  |  | 
| --- |--- |
|   **安装**   |   `npm install aws-cdk-lib`   | 
|   **导入**：  |   `import * as cdk from 'aws-cdk-lib';`   | 


|  |  | 
| --- |--- |
|   **安装**   |   `npm install aws-cdk-lib`   | 
|   **导入**：  |   `const cdk = require('aws-cdk-lib');`   | 


|  |  | 
| --- |--- |
|   **安装**   |   `python -m pip install aws-cdk-lib`   | 
|   **导入**：  |   `import aws_cdk as cdk`   | 


|  |  | 
| --- |--- |
|   **在 `pom.xml` 中，添加**   |   `Group software.amazon.awscdk; artifact aws-cdk-lib`   | 
|   **导入**：  |   `import software.amazon.awscdk.App;`   | 


|  |  | 
| --- |--- |
|   **安装**   |   `dotnet add package Amazon.CDK.Lib`   | 
|   **导入**：  |   `using Amazon.CDK;`   | 


|  |  | 
| --- |--- |
|   **安装**   |   `go get github.com/aws/aws-cdk-go/awscdk/v2`   | 
|   **导入**：  |  <pre>import (<br />  "github.com/aws/aws-cdk-go/awscdk/v2"<br />)</pre>  | 

`construct` 基类和支持代码位于 `constructs` 库中。实验性构造（其中 API 仍在完善中）作为单独的模块进行分发。

## 使用 AWS CDK API 参考
<a name="work-with-library-reference"></a>

采用 AWS CDK 进行开发时，请使用 [AWS CDK API 参考](libraries.md#libraries-reference)。

每个模块的参考资料分为以下几个部分。
+  *概述*：使用 AWS CDK 中的服务需要了解的介绍性材料，包括概念和示例。
+  *构造*：表示一个或多个具体 AWS 资源的库类。这些是“精选”（L2）资源或模式（L3 资源），可提供具有合理默认值的高级别接口。
+  *类*：非构造类，可提供模块中构造所使用的功能。
+  *结构*：数据结构（属性捆绑包），可定义复合值结构，例如属性（构造的 `props` 参数）和选项。
+  *接口*：所有名称以“I”为开头的接口，可定义相应构造或其他类的绝对最低功能。CDK 使用构造接口来表示在您的 AWS CDK 应用程序之外定义并由 `Bucket.fromBucketArn()` 等方法引用的 AWS 资源。
+  *枚举*：用于指定某些构造参数的命名值的集合。使用枚举值可允许 CDK 在合成过程中检查这些值的有效性。
+  *CloudFormation 资源*：名称以“Cfn”开头的这些 L1 构造，正好代表了 CloudFormation 规范中定义的资源。这些资源随每个 CDK 版本根据该规范自动生成。每个 L2 或 L3 构造都封装了一个或多个 CloudFormation 资源。
+  *CloudFormation 属性类型*：定义每个 CloudFormation 资源属性的命名值的集合。

## 接口与构造类的比较
<a name="work-with-library-interfaces"></a>

AWS CDK 以特定的方式使用接口，即使您熟悉作为编程概念的接口，这种方式也可能并不明显。

AWS CDK 支持通过 `Bucket.fromBucketArn()` 等方法来使用 CDK 应用程序之外定义的资源。无法对外部资源进行修改，并且可能不具有使用 `Bucket` 类等工具在您的 CDK 应用程序中定义的资源提供的所有功能。因此，接口代表了 CDK 中针对给定 AWS 资源类型（*包括外部资源*）可用的最低功能。

所以在 CDK 应用程序中实例化资源时，应始终使用具体的类，例如 `Bucket`。在您自己的构造之一中指定要接受的参数类型时，如果您已准备好处理外部资源（即无需对其进行更改），请使用 `IBucket` 等接口类型。如果需要 CDK 定义的构造，请指定可以使用的最通用的类型。

有些接口是与特定类（而不是构造）相关的属性或选项捆绑包的最低版本。当进行子类化以接受要传递给父类的参数时，此类接口会很有用。如果您需要一个或多个其他属性，则需要从该接口或更具体的类型来实现或派生。

**注意**  
AWS CDK 支持的某些编程语言不具备接口功能。在这些语言中，接口只是普通的类。您可以通过其名称来进行识别，这些名称遵循首字母为“I”后跟其他构造名称的模式（例如 `IBucket`）。适用于相同的规则。

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

使用包管理工具来管理 AWS CDK 应用程序或库的依赖项。这些工具通常与编程语言一起使用。

通常，AWS CDK 支持该语言的标准或官方包管理工具（如有）。否则，AWS CDK 将支持该语言中最常用或最广泛支持的管理工具。您也可以使用其他工具，特别是如果与支持的工具配合使用。但是，官方对其他工具的支持有限。

AWS CDK 支持以下包管理器：


| 语言 | 支持的包管理工具 | 
| --- | --- | 
|  TypeScript/JavaScript  |  NPM（节点包管理器）或 Yarn  | 
|  Python  |  PIP（Python 的包安装程序）  | 
|  Java  |  Maven  | 
|  C\$1  |  NuGet  | 
|  Go（转到）  |  Go 模块  | 

使用 AWS CDK CLI `cdk init` 命令创建新项目时，会自动指定 CDK 核心库和稳定构造的依赖项。

有关管理受支持编程语言依赖项的更多信息，请参阅以下内容：
+  [在 TypeScript 中管理依赖项](work-with-cdk-typescript.md#work-with-cdk-typescript-dependencies)。
+  [在 JavaScript 中管理依赖项](work-with-cdk-javascript.md#work-with-cdk-javascript-dependencies)。
+  [在 Python 中管理依赖项](work-with-cdk-python.md#work-with-cdk-python-dependencies)。
+  [在 Java 中管理依赖项](work-with-cdk-java.md#work-with-cdk-java-dependencies)。
+  [在 C\$1 中管理依赖项](work-with-cdk-csharp.md#work-with-cdk-csharp-dependencies)。
+  [在 Go 中管理依赖项](work-with-cdk-go.md#work-with-cdk-go-dependencies)。

## 将 TypeScript 中的 AWS CDK 与其他语言进行比较
<a name="work-with-cdk-compare"></a>

TypeScript 是支持开发 AWS CDK 应用程序所支持的第一种语言。因此，大量示例 CDK 代码都使用 TypeScript 进行编写。如果您正在使用另一种语言进行开发，那么请将 AWS CDK 代码在 TypeScript 中的实现方式与您选择语言中的实现方式进行比较，这可能会很有用。这有助于您在整个文档中使用示例。

## 导入模块
<a name="work-with-cdk-compare-import"></a>

**Example**  
TypeScript 支持导入整个命名空间，也支持从某个命名空间中导入单个对象。每个命名空间都包含用于给定 AWS 服务的构造和其他类。  

```
// Import main CDK library as cdk
import * as cdk from 'aws-cdk-lib';   // ES6 import preferred in TS
const cdk = require('aws-cdk-lib');   // Node.js require() preferred in JS

// Import specific core CDK classes
import { Stack, App } from 'aws-cdk-lib';
const { Stack, App } = require('aws-cdk-lib');

// Import AWS S3 namespace as s3 into current namespace
import { aws_s3 as s3 } from 'aws-cdk-lib';   // TypeScript
const s3 = require('aws-cdk-lib/aws-s3');     // JavaScript

// Having imported cdk already as above, this is also valid
const s3 = cdk.aws_s3;

// Now use s3 to access the S3 types
const bucket = s3.Bucket(...);

// Selective import of s3.Bucket
import { Bucket } from 'aws-cdk-lib/aws-s3';        // TypeScript
const { Bucket } = require('aws-cdk-lib/aws-s3');   // JavaScript

// Now use Bucket to instantiate an S3 bucket
const bucket = Bucket(...);
```
与 TypeScript 一样，Python 也支持具有命名空间的模块导入和选择性导入。Python 中的命名空间类似于 **aws\$1cdk.** *xxx*，其中 *xxx* 表示 AWS 服务名称，例如 **s3** 代表 Amazon S3。（这些示例中使用了 Amazon S3。）  

```
# Import main CDK library as cdk
import aws_cdk as cdk

# Selective import of specific core classes
from aws_cdk import Stack, App

# Import entire module as s3 into current namespace
import aws_cdk.aws_s3 as s3

# s3 can now be used to access classes it contains
bucket = s3.Bucket(...)

# Selective import of s3.Bucket into current namespace
from aws_cdk.s3 import Bucket

# Bucket can now be used to instantiate a bucket
bucket = Bucket(...)
```
Java 的导入方式与 TypeScript 有所不同。每个 import 语句要么从给定包中导入单个类名，要么导入该包中定义的所有类（使用 `\*`）。可以使用类本身的类名（如果已导入该类），也可以使用包含其包的*限定*类名来访问类。  
库的命名类似于 AWS 构造库的 `software.amazon.awscdk.services.xxx`（其中 `software.amazon.awscdk` 为主库）。AWS CDK 软件包的 Maven 组 ID 为 `software.amazon.awscdk`。  

```
// Make certain core classes available
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.App;

// Make all Amazon S3 construct library classes available
import software.amazon.awscdk.services.s3.*;

// Make only Bucket and EventType classes available
import software.amazon.awscdk.services.s3.Bucket;
import software.amazon.awscdk.services.s3.EventType;

// An imported class may now be accessed using the simple class name (assuming that name
// does not conflict with another class)
Bucket bucket = Bucket.Builder.create(...).build();

// We can always use the qualified name of a class (including its package) even without an
// import directive
software.amazon.awscdk.services.s3.Bucket bucket =
    software.amazon.awscdk.services.s3.Bucket.Builder.create(...)
        .build();

// Java 10 or later can use var keyword to avoid typing the type twice
var bucket =
    software.amazon.awscdk.services.s3.Bucket.Builder.create(...)
        .build();
```
在 C\$1 中，您可以使用 `using` 指令导入类型。有两种方式可供选择。一种是使用纯名称来访问指定命名空间中的所有类型。另一种则是可以使用别名来引用命名空间本身。  
软件包的命名类似于 AWS 构造库软件包的 `Amazon.CDK.AWS.xxx`。（其中 `Amazon.CDK` 为核心模块。）  

```
// Make CDK base classes available under cdk
using cdk = Amazon.CDK;

// Make all Amazon S3 construct library classes available
using Amazon.CDK.AWS.S3;

// Now we can access any S3 type using its name
var bucket = new Bucket(...);

// Import the S3 namespace under an alias
using s3 = Amazon.CDK.AWS.S3;

// Now we can access an S3 type through the namespace alias
var bucket = new s3.Bucket(...);

// We can always use the qualified name of a type (including its namespace) even without a
// using directive
var bucket = new Amazon.CDK.AWS.S3.Bucket(...);
```
每个 AWS 构造库模块都作为 Go 包提供。  

```
import (
    "github.com/aws/aws-cdk-go/awscdk/v2"           // CDK core package
    "github.com/aws/aws-cdk-go/awscdk/v2/awss3"     // AWS S3 construct library module
)

// now instantiate a bucket
bucket := awss3.NewBucket(...)

// use aliases for brevity/clarity
import (
    cdk "github.com/aws/aws-cdk-go/awscdk/v2"           // CDK core package
    s3  "github.com/aws/aws-cdk-go/awscdk/v2/awss3"     // AWS S3 construct library module
)

bucket := s3.NewBucket(...)
```

## 实例化构造
<a name="work-with-cdk-compare-class"></a>

 AWS CDK 构造类在所有支持的语言中都具有相同的名称。大多数语言都使用 `new` 关键字来实例化类（Python 和 Go 则不使用）。此外，在大多数语言中，关键字`this` 是指当前实例。（按照惯例，Python 使用 `self`。） 您应该将对当前实例的引用作为 `scope` 参数传递给您创建的每个构造。

AWS CDK 构造的第三个参数是 `props`，这是一个包含构建构造所需属性的对象。此参数可能是可选的，但是当需要时，支持的语言会以惯用方式进行处理。属性的名称也符合该语言的标准命名模式。

**Example**  

```
// Instantiate default Bucket
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket');

// Instantiate Bucket with bucketName and versioned properties
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', {
  bucketName: 'amzn-s3-demo-bucket',
   versioned: true,
});

// Instantiate Bucket with websiteRedirect, which has its own sub-properties
const bucket = new s3.Bucket(this, 'amzn-s3-demo-bucket', {
  websiteRedirect: {host: 'aws.amazon.com'}});
```
Python 在实例化类时不使用 `new` 关键字。使用关键字参数来表示属性参数，这些关键字参数使用 `snake_case` 来命名。  
如果 props 值本身就是属性捆绑包，则由以该属性命名的类表示，该类接受子属性的关键字参数。  
在 Python 中，当前实例作为第一个参数传递给方法，按照惯例命名为 `self`。  

```
# Instantiate default Bucket
bucket = s3.Bucket(self, "amzn-s3-demo-bucket")

# Instantiate Bucket with bucket_name and versioned properties
bucket = s3.Bucket(self, "amzn-s3-demo-bucket", bucket_name="amzn-s3-demo-bucket", versioned=true)

# Instantiate Bucket with website_redirect, which has its own sub-properties
bucket = s3.Bucket(self, "amzn-s3-demo-bucket", website_redirect=s3.WebsiteRedirect(
            host_name="aws.amazon.com"))
```
在 Java 中，props 参数由一个名为 `XxxxProps` 的类表示（例如，`BucketProps` 表示 `Bucket` 构造的 props）。您可以使用生成器模式来构建 props 参数。  
每个 `XxxxProps` 类都有一个生成器。每个构造都还具有一个便捷生成器，可以一步构建 props 和构造，如以下示例所示。  
Props 与 TypeScript 中相同，均使用 `camelCase`。  

```
// Instantiate default Bucket
Bucket bucket = Bucket(self, "amzn-s3-demo-bucket");

// Instantiate Bucket with bucketName and versioned properties
Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket")
                      .bucketName("amzn-s3-demo-bucket").versioned(true)
                      .build();

# Instantiate Bucket with websiteRedirect, which has its own sub-properties
Bucket bucket = Bucket.Builder.create(self, "amzn-s3-demo-bucket")
                      .websiteRedirect(new websiteRedirect.Builder()
                          .hostName("aws.amazon.com").build())
                      .build();
```
在 C\$1 中，使用对象初始化程序将 props 指定给名为 `XxxxProps` 的类（例如，`BucketProps` 表示 `Bucket` 构造的 props）。  
Props 命名与 TypeScript 类似，唯一的不同是使用 `PascalCase`。  
在实例化构造时使用 `var` 关键字很方便，因此无需键入类名两次。但是，您的本地代码风格指南可能会有所不同。  

```
// Instantiate default Bucket
var bucket = Bucket(self, "amzn-s3-demo-bucket");

// Instantiate Bucket with BucketName and Versioned properties
var bucket =  Bucket(self, "amzn-s3-demo-bucket", new BucketProps {
                      BucketName = "amzn-s3-demo-bucket",
                      Versioned  = true});

// Instantiate Bucket with WebsiteRedirect, which has its own sub-properties
var bucket = Bucket(self, "amzn-s3-demo-bucket", new BucketProps {
                      WebsiteRedirect = new WebsiteRedirect {
                              HostName = "aws.amazon.com"
                      }});
```
要在 Go 中创建构造，请调用函数 `NewXxxxxx`，其中 `Xxxxxxx` 为构造的名称。构造的属性被定义为结构。  
在 Go 中，所有构造参数都是指针，包括数字、布尔值和字符串等值。使用 `jsii.String` 等便捷函数来创建这些指针。  

```
	// Instantiate default Bucket
	bucket := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), nil)

	// Instantiate Bucket with BucketName and Versioned properties
	bucket1 := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{
		BucketName: jsii.String("amzn-s3-demo-bucket"),
		Versioned:  jsii.Bool(true),
	})

	// Instantiate Bucket with WebsiteRedirect, which has its own sub-properties
	bucket2 := awss3.NewBucket(stack, jsii.String("amzn-s3-demo-bucket"), &awss3.BucketProps{
		WebsiteRedirect: &awss3.RedirectTarget{
			HostName: jsii.String("aws.amazon.com"),
		}})
```

## 访问成员
<a name="work-with-cdk-compare-members"></a>

通常会引用构造和其他 AWS CDK 类的特性或属性，并将这些值用作构建其他构造的输入等。前面所述方法的命名差异也适用于此处。此外，无法在 Java 中直接访问成员。相反，会提供一个 getter 方法。

**Example**  
名称为 `camelCase`。  

```
bucket.bucketArn
```
名称为 `snake_case`。  

```
bucket.bucket_arn
```
为每个属性提供了一个 getter 方法；这些名称为 `camelCase`。  

```
bucket.getBucketArn()
```
名称为 `PascalCase`。  

```
bucket.BucketArn
```
名称为 `PascalCase`。  

```
bucket.BucketArn
```

## 枚举常量
<a name="work-with-cdk-compare-enums"></a>

枚举常量的作用域仅限于某个类，并且在所有语言中都具有带下划线的大写名称（有时称为 `SCREAMING_SNAKE_CASE`）。由于类名在除 Go 之外的所有支持的语言中也使用相同的大小写，所以这些语言中的限定枚举名称也相同。

```
s3.BucketEncryption.KMS_MANAGED
```

在 Go 中，枚举常量是指模块命名空间的属性，编写方式如下。

```
awss3.BucketEncryption_KMS_MANAGED
```

## 对象接口
<a name="work-with-cdk-compare-object"></a>

AWS CDK 使用 TypeScript 对象接口来表示某个类实现了一组预期的方法和属性。您可以识别对象接口，因为其名称以 `I` 开头。具体类使用 `implements` 关键字来指示其实现的接口。

**Example**  
JavaScript 不具备接口功能。您可以忽略 `implements` 关键字及其后的类名。

```
import { IAspect, IConstruct } from 'aws-cdk-lib';

class MyAspect implements IAspect {
  public visit(node: IConstruct) {
    console.log('Visited', node.node.path);
  }
}
```
Python 不具备接口功能。但是，对于 AWS CDK 来说，您可以通过 `@jsii.implements(interface)` 来装饰您的类，以此指示接口实现。  

```
from aws_cdk import IAspect, IConstruct
import jsii

@jsii.implements(IAspect)
class MyAspect():
  def visit(self, node: IConstruct) -> None:
    print("Visited", node.node.path)
```

```
import software.amazon.awscdk.IAspect;
import software.amazon.awscdk.IConstruct;

public class MyAspect implements IAspect {
    public void visit(IConstruct node) {
        System.out.format("Visited %s", node.getNode().getPath());
    }
}
```

```
using Amazon.CDK;

public class MyAspect : IAspect
{
    public void Visit(IConstruct node)
    {
        System.Console.WriteLine($"Visited ${node.Node.Path}");
    }
}
```
Go 结构无需明确声明其实现的接口。Go 编译器根据结构上可用的方法和属性来确定实现。例如，在以下代码中，`MyAspect` 实现 `IAspect` 接口，因为其提供了一种采用构造的 `Visit` 方法。  

```
type MyAspect struct {
}

func (a MyAspect) Visit(node constructs.IConstruct) {
	fmt.Println("Visited", *node.Node().Path())
}
```

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

TypeScript 是一种 AWS 云开发工具包 (AWS CDK) 完全支持且视为稳定的客户端语言。在 TypeScript 中使用 AWS CDK 采用了熟悉的工具，包括 Microsoft 的 TypeScript 编译器 (`tsc`)、[Node.js](https://nodejs.org/) 和节点包管理器 (`npm`)。如果您愿意，也可以使用 [Yarn](https://yarnpkg.com/)，不过本指南中的示例使用的是 NPM。通过 NPM 存储库 [npmjs.org](https://www.npmjs.com/) 来分发构成 AWS 构造库的模块。

您可以使用任何编辑器或 IDE。许多 AWS CDK 开发人员都使用 [Visual Studio Code](https://code.visualstudio.com/)（或其开源等效版本 [VSCodium](https://vscodium.com/)），该编辑器可为 TypeScript 提供卓越支持。

## 开始使用 TypeScript
<a name="typescript-prerequisites"></a>

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

您还需要 TypeScript 本身（版本 3.8 或更高版本）。如果您还没有 TypeScript，可使用 `npm` 进行安装。

```
$ npm install -g typescript
```

**注意**  
如果遇到权限错误，且在系统上拥有管理员访问权限，请尝试 `sudo npm install -g typescript`。

通过定期的 `npm update -g typescript` 让 TypeScript 保持为最新版本。

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

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

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

```
$ mkdir my-project
$ cd my-project
$ cdk init app --language typescript
```

创建项目还会安装 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html) 模块及其依赖项。

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

## 使用本地 `tsc` 和 `cdk`
<a name="typescript-local"></a>

在大多数情况下，本指南假设您已全局安装 TypeScript 和 CDK Toolkit (`npm install -g typescript aws-cdk`)，并且提供的命令示例（例如 `cdk synth`）也遵循此假设。这种方法可以很容易让两个组件保持为最新版本，并且由于两者都采取了严格的向后兼容性方法，所以始终使用最新版本通常风险很小。

有些团队更喜欢在每个项目中指定所有依赖项，包括 TypeScript 编译器和 CDK Toolkit 等工具。通过这种做法，您可以将这些组件固定到特定版本，并确保团队中的所有开发人员（以及您的 CI/CD 环境）都正好使用这些版本。这从根源上消除了可能发生的变更，有助于使构建和部署更加一致且可重复。

CDK 在 TypeScript 项目模板的 `package.json` 中包含了 TypeScript 和 CDK 工具包的依赖项，因此，如果您想使用这种方法，无需对项目进行任何更改。您所需要做的就是使用稍微不同的命令来构建应用程序以及发出 `cdk` 命令。


| 操作 | 使用全局工具 | 使用本地工具 | 
| --- | --- | --- | 
|   **初始化项目**   |   `cdk init --language typescript`   |   `npx aws-cdk init --language typescript`   | 
|   **构建**   |   `tsc`   |   `npm run build`   | 
|   **运行 CDK Toolkit 命令**   |   `cdk …​`   |   `npm run cdk …​` 或者`npx aws-cdk …​`   | 

 `npx aws-cdk` 运行当前项目中本地安装的 CDK Toolkit 版本（如果存在），如有则回退到全局安装。如果不存在全局安装，则 `npx` 会下载 CDK Toolkit 的临时副本并运行该副本。您可以使用 `@` 语法（`npx aws-cdk@2.0 --version` 打印 `2.0.0`）来指定 CDK Toolkit 的任意版本。

**提示**  
设置别名，以便您可以在安装本地 CDK Toolkit 时使用 `cdk` 命令。  

```
$ alias cdk="npx aws-cdk"
```

```
doskey cdk=npx aws-cdk $*
```

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

使用节点软件包管理器 (`npm`) 来安装和更新供您应用程序使用的 AWS 构造库模块以及您需要的其他软件包。（如果您愿意，可以用 `yarn` 代替 `npm`。）`npm` 还会自动安装这些模块的依赖项。

大多数 AWS CDK 构造都位于名为 `aws-cdk-lib` 的 CDK 主包中，这是 `cdk init` 创建的新项目中的默认依赖项。“实验性”AWS 构造库模块（其中更高级别的构造仍在开发中）的命名类似于 `@aws-cdk/<SERVICE-NAME>-alpha`。服务名称带有 *aws-* 前缀。如果您不确定某个模块的名称，请[在 NPM 上进行搜索](https://www.npmjs.com/search?q=%40aws-cdk)。

**注意**  
[CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) 也显示了包名称。

例如，以下命令用于安装 AWS CodeStar 的实验模块。

```
$ npm install @aws-cdk/aws-codestar-alpha
```

某些服务的构造库支持位于多个命名空间中。例如，除 `aws-route53` 之外，还有另外三个 Amazon Route 53 命名空间，分别是 `aws-route53-targets`、`aws-route53-patterns` 和 `aws-route53resolver`。

您项目的依赖项在 `package.json` 中进行维护。您可以编辑此文件，将部分或全部依赖项锁定到特定版本，或者允许在特定条件下将其更新到较新版本。根据您在 `package.json` 中指定的规则，将项目的 NPM 依赖项更新到允许的最新版本：

```
$ npm update
```

在 TypeScript 中，您可以将模块导入到代码中，其名称与使用 NPM 安装模块时使用的名称相同。在应用程序中导入 AWS CDK 类和 AWS 构造库模块时，我们建议采用以下做法。遵循这些准则将有助于让您的代码与其他 AWS CDK 应用程序保持一致并更易于理解。
+ 请使用 ES6 风格的 `import` 指令，而非 `require()`。
+ 通常，从 `aws-cdk-lib` 中导入单个类。

  ```
  import { App, Stack } from 'aws-cdk-lib';
  ```
+ 如果您需要 `aws-cdk-lib` 中的许多类，则可以使用 `cdk` 的命名空间别名，而不是导入单个类。避免同时执行这两项操作。

  ```
  import * as cdk from 'aws-cdk-lib';
  ```
+ 通常，使用短命名空间别名来导入 AWS 服务构造。

  ```
  import { aws_s3 as s3 } from 'aws-cdk-lib';
  ```

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

在 TypeScript CDK 项目中，在项目主目录的 `package.json` 文件中指定依赖项。核心 AWS CDK 模块位于名为 `aws-cdk-lib` 的单个 `NPM` 程序包中。

当您使用 `npm install` 来安装包时，NPM 会在 `package.json` 中记录该包。

如果您愿意，可以用 Yarn 代替 NPM。但是，CDK 不支持 Yarn 的即插即用模式，该模式是 Yarn 2 中的默认模式。将以下内容添加到项目的 `.yarnrc.yml` 文件以关闭此功能。

```
nodeLinker: node-modules
```

### CDK 应用程序
<a name="work-with-cdk-typescript-dependencies-apps"></a>

以下是 `cdk init --language typescript` 命令生成的示例 `package.json` 文件：

```
{
  "name": "my-package",
  "version": "0.1.0",
  "bin": {
    "my-package": "bin/my-package.js"
  },
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk"
  },
  "devDependencies": {
    "@types/jest": "^26.0.10",
    "@types/node": "10.17.27",
    "jest": "^26.4.2",
    "ts-jest": "^26.2.0",
    "aws-cdk": "2.16.0",
    "ts-node": "^9.0.0",
    "typescript": "~3.9.7"
  },
  "dependencies": {
    "aws-cdk-lib": "2.16.0",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.16"
  }
}
```

对于可部署的 CDK 应用程序，必须在 `package.json` 的 `dependencies` 部分中指定 `aws-cdk-lib`。您可以使用脱字符（^）版本号说明符来表示您将接受比指定版本更高的版本，前提是它们位于同一个主版本内。

对于实验性构造，请为 alpha 构造库模块指定确切版本，这些模块的 API 可能会发生更改。请勿使用 ^ 或 \$1，因为这些模块的更高版本可能会导致 API 发生更改，从而导致您的应用程序中断。

在 `package.json` 的 `devDependencies` 部分中指定测试应用程序所需的库和工具版本（例如，`jest` 测试框架）。或者使用 ^ 来指定可接受更高版本的兼容版本。

### 第三方构造库
<a name="work-with-cdk-typescript-dependencies-libraries"></a>

如果您正在开发构造库，请结合 `peerDependencies` 和 `devDependencies` 部分来指定其依赖项，如以下示例 `package.json` 文件所示。

```
{
  "name": "my-package",
  "version": "0.0.1",
  "peerDependencies": {
    "aws-cdk-lib": "^2.14.0",
    "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha",
    "constructs": "^10.0.0"
  },
  "devDependencies": {
    "aws-cdk-lib": "2.14.0",
    "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha",
    "constructs": "10.0.0",
    "jsii": "^1.50.0",
    "aws-cdk": "^2.14.0"
  }
}
```

在 `peerDependencies` 中，使用脱字符（^）来指定您的库所使用的 `aws-cdk-lib` 的最低版本。这样可以最大限度地提高您的库与一系列 CDK 版本的兼容性。为 alpha 构造库模块指定确切版本，这些模块的 API 可能会发生更改。使用 `peerDependencies` 可以确保 `node_modules` 树中所有 CDK 库副本只有一个副本。

在 `devDependencies` 中，指定测试所需的工具和库，也可以使用 ^ 来表示可以接受更高版本的兼容版本。确切指定（不带 ^ 或 \$1）您宣称您的库与之兼容的 `aws-cdk-lib` 和其他 CDK 软件包的最低版本。这种做法可确保您的测试是针对这些版本运行的。这样，如果您无意中使用了仅较新版本中具备的功能，则您的测试可以将其捕捉到。

**警告**  
 只有 NPM 7 及更高版本才能自动安装 `peerDependencies`。如果您使用的是 NPM 6 或更早版本，或者使用的是 Yarn，则必须在 `devDependencies` 中包含依赖项的依赖项。否则，将不会进行安装，并且您将收到有关对等依赖项未解决的警告。

### 安装和更新依赖项
<a name="work-with-cdk-typescript-dependencies-install"></a>

运行以下命令来安装项目的依赖项。

**Example**  

```
# Install the latest version of everything that matches the ranges in 'package.json'
npm install

# Install the same exact dependency versions as recorded in 'package-lock.json'
npm ci
```

```
# Install the latest version of everything that matches the ranges in 'package.json'
$ yarn upgrade

# Install the same exact dependency versions as recorded in 'yarn.lock'
$ yarn install --frozen-lockfile
```

要更新已安装的模块，可以使用前面的 `npm install` 和 `yarn upgrade` 命令。任一命令都会将 `node_modules` 中的软件包更新为可满足 `package.json` 中规则的最新版本。但是，它们不会更新 `package.json` 本身，您可能需要执行此操作来设置新的最低版本。如果您将包托管在 GitHub 上，则可以配置 [Dependabot 版本更新](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates) 来自动更新 `package.json`。或者，可以使用 [npm-check-updates](https://www.npmjs.com/package/npm-check-updates)。

**重要**  
根据设计，当您安装或更新依赖项时，NPM 和 Yarn 会选择可满足 `package.json` 中指定要求的每个包的最新版本。这些版本始终存在损坏风险（无论是无意还是有意）。更新项目的依赖项后，请彻底进行测试。

## TypeScript 中的 AWS CDK 习语
<a name="typescript-cdk-idioms"></a>

### Props
<a name="typescript-props"></a>

所有 AWS 构造库类都使用三个参数进行实例化：在其中定义构造的 *scope*（构造树中的父级）、*id* 和 *props*。*props* 参数是键/值对捆绑包，构造使用这些键/值对来配置其创建的 AWS 资源。其他类和方法也使用“属性捆绑包”模式作为参数。

在 TypeScript 中，`props` 的形状是使用一个接口定义的，该接口可显示必需参数和可选参数及其类型。为每种 `props` 参数定义一个此类接口，通常特定于单个构造或方法。例如，[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) 构造（在 `aws-cdk-lib/aws-s3` 模块中）指定符合 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html) 接口的 `props` 参数。

如果属性本身就是一个对象，例如 `BucketProps` 的 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html#websiteredirect](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html#websiteredirect) 属性，则该对象将拥有自己的接口，其形状必须符合该接口，在本例中为 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.RedirectTarget.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.RedirectTarget.html)。

如果正在子类化一个 AWS 构造库类（或重写采用类似 props 参数的方法），则可以从现有接口继承来创建一个新接口，该新接口可指定您的代码所需的任何新 props。在调用父类或基方法时，通常可以传递收到的整个 props 参数，因为对象中提供但未在接口中指定的所有属性都将被忽略。

AWS CDK 的未来版本可能会碰巧添加一个新属性，其名称与您用于自己属性的名称相同。将收到的值沿继承链向上传递可能会导致意外行为。更安全的做法是传递您收到的 props 卷影副本，同时移除属性或将其设置为 `undefined`。例如：

```
super(scope, name, {...props, encryptionKeys: undefined});
```

或者，为您的属性命名，以便清楚地表明它们属于您的构造。这样，其就不太可能在未来的 AWS CDK 版本中与属性发生冲突。如果有很多属性，请使用一个适当命名的对象来存放它们。

### 缺失值
<a name="typescript-missing-values"></a>

对象中的缺失值（例如 props）在 TypeScript 中的值为 `undefined`。该语言的 3.7 版本引入了简化处理这些值的运算符，这样在达到未定义的值时就能更容易指定默认值和“短路”链接。有关这些功能的更多信息，请参阅 [TypeScript 3.7 发行说明](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html)，特别是前两个功能“可选链接”和“Null 值合并”。

## 构建和运行 CDK 应用程序
<a name="typescript-running"></a>

通常，构建和运行应用程序时，您应位于项目的根目录中。

Node.js 无法直接运行 TypeScript；相反，使用 TypeScript 编译器 `tsc` 将您的应用程序转换到 JavaScript。然后执行生成的 JavaScript 代码。

每当需要运行您的应用程序时，AWS CDK 都会自动执行此操作。但是，手动编译以检查错误并运行测试可能会很有用。要手动编译您的 TypeScript 应用程序，请发出 `npm run build` 命令。您也可以发出 `npm run watch` 命令进入监视模式，在这种模式下，每当您保存对源文件的更改时，TypeScript 编译器都会自动重建您的应用程序。

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

JavaScript 是 AWS CDK 完全支持的客户端语言，被认为是稳定的。在中使用 C AWS loud Development Kit (AWS CDK) JavaScript 使用熟悉的工具，包括 [Node.js](https://nodejs.org/) 和 Node Package Manager (`npm`)。如果您愿意，也可以使用 [Yarn](https://yarnpkg.com/)，不过本指南中的示例使用的是 NPM。[构成 AWS 构造库的模块通过 NPM 存储库 npmjs.org 分发。](https://www.npmjs.com/)

您可以使用任何编辑器或 IDE。许多 AWS CDK 开发者使用 [Visual Studio Code（或其开源代码](https://code.visualstudio.com/)等效物 [VSCodium](https://vscodium.com/)），该代码有很好的支持。 JavaScript

## 开始使用 JavaScript
<a name="javascript-prerequisites"></a>

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

JavaScript AWS 除此之外，CDK 应用程序不需要其他先决条件。

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

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

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

```
$ mkdir my-project
$ cd my-project
$ cdk init app --language javascript
```

创建项目还会安装 [aws-cdk-lib](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html) 模块及其依赖项。

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

## 使用本地 `cdk`
<a name="javascript-local"></a>

在大多数情况下，本指南假设您已全局安装 CDK Toolkit（`npm install -g aws-cdk`），并且提供的命令示例（例如 `cdk synth`）也遵循此假设。这种方法可以很容易让 CDK Toolkit 保持为最新版本，而且由于 CDK 采取了严格的向后兼容性方法，所以始终使用最新版本通常风险很小。

有些团队更喜欢在每个项目中指定所有依赖项，包括 CDK Toolkit 等工具。这种做法允许您将此类组件固定到特定版本，并确保您的团队（和您的 CI/CD 环境）中的所有开发人员都完全使用这些版本。这从根源上消除了可能发生的变更，有助于使构建和部署更加一致且可重复。

CDK 在 JavaScript 项目模板中包含对 CDK Toolkit 的依赖关系`package.json`，因此，如果您想使用这种方法，则无需对项目进行任何更改。您所需要做的就是使用稍微不同的命令来构建应用程序以及发出 `cdk` 命令。


| 操作 | 使用全局工具 | 使用本地工具 | 
| --- | --- | --- | 
|   **初始化项目**   |   `cdk init --language javascript`   |   `npx aws-cdk init --language javascript`   | 
|   **运行 CDK 工具包命令**   |   `cdk …​`   |   `npm run cdk …​` 或 `npx aws-cdk …​`   | 

 `npx aws-cdk` 运行当前项目中本地安装的 CDK Toolkit 版本（如果存在），如有则回退到全局安装。如果不存在全局安装，则 `npx` 会下载 CDK Toolkit 的临时副本并运行该副本。您可以使用 `@` 语法（`npx aws-cdk@1.120 --version` 打印 `1.120.0`）来指定 CDK Toolkit 的任意版本。

**提示**  
设置别名，以便您可以在安装本地 CDK Toolkit 时使用 `cdk` 命令。  

```
$ alias cdk="npx aws-cdk"
```

```
doskey cdk=npx aws-cdk $*
```

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

使用 Node Package Manager (`npm`) 安装和更新 C AWS onstruct Library 模块以供您的应用程序使用，以及您需要的其他软件包。（如果您愿意，可以用 `yarn` 代替 `npm`。）`npm` 还会自动安装这些模块的依赖项。

大多数 AWS CDK 构造都位于名为 CDK 的主包中`aws-cdk-lib`，这是由创建的新项目中的默认依赖项。`cdk init`“实验性” AWS 构造库模块（其中更高级别的构造仍在开发中）被命名为。`aws-cdk-lib/<SERVICE-NAME>-alpha`服务名称带有 *aws-* 前缀。如果您不确定某个模块的名称，请[在 NPM 上进行搜索](https://www.npmjs.com/search?q=%40aws-cdk)。

**注意**  
[CDK API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html) 也显示了包名称。

例如，以下命令安装的实验模块 AWS CodeStar。

```
npm install @aws-cdk/aws-codestar-alpha
```

某些服务的构造库支持位于多个命名空间中。例如，除 `aws-route53` 之外，还有另外三个 Amazon Route 53 命名空间，分别是 `aws-route53-targets`、`aws-route53-patterns` 和 `aws-route53resolver`。

您项目的依赖项在 `package.json` 中进行维护。您可以编辑此文件，将部分或全部依赖项锁定到特定版本，或者允许在特定条件下将其更新到较新版本。根据您在 `package.json` 中指定的规则，将项目的 NPM 依赖项更新到允许的最新版本：

```
npm update
```

在中 JavaScript，您可以将模块导入到代码中，其名称与使用 NPM 安装模块时使用的名称相同。在应用程序中导入 AWS CDK 类和 AWS 构造库模块时，我们建议采用以下做法。遵循这些准则将有助于使您的代码与其他 AWS CDK 应用程序保持一致，并且更易于理解。
+ 使用`require()`而不是 ES6样式`import`指令。Node.js 的旧版本不支持 ES6 导入，因此使用较旧的语法更具兼容性。（如果你真的想使用 ES6 导入，请使用 [esm](https://www.npmjs.com/package/esm) 来确保你的项目与所有支持的 Node.js 版本兼容。）
+ 通常，从 `aws-cdk-lib` 中导入单个类。

  ```
  const { App, Stack } = require('aws-cdk-lib');
  ```
+ 如果您需要 `aws-cdk-lib` 中的许多类，则可以使用 `cdk` 的命名空间别名，而不是导入单个类。避免同时执行这两项操作。

  ```
  const cdk = require('aws-cdk-lib');
  ```
+ 通常，使用短命名空间别名导入 AWS 构造库。

  ```
  const { s3 } = require('aws-cdk-lib/aws-s3');
  ```

## 在中管理依赖关系 JavaScript
<a name="work-with-cdk-javascript-dependencies"></a>

在 JavaScript CDK 项目中，依赖关系是在项目主目录`package.json`的文件中指定的。核心 AWS CDK 模块位于名`aws-cdk-lib`为的单个`NPM`包中。

当您使用 `npm install` 来安装包时，NPM 会在 `package.json` 中记录该包。

如果您愿意，可以用 Yarn 代替 NPM。但是，CDK 不支持 Yarn plug-and-play 模式，这是 Yarn 2 中的默认模式。将以下内容添加到项目的 `.yarnrc.yml` 文件以关闭此功能。

```
nodeLinker: node-modules
```

### CDK 应用程序
<a name="work-with-cdk-javascript-dependencies-apps"></a>

以下是 `cdk init --language typescript` 命令生成的示例 `package.json` 文件。为生成的文件 JavaScript 类似，只是没有 TypeScript相关的条目。

```
{
  "name": "my-package",
  "version": "0.1.0",
  "bin": {
    "my-package": "bin/my-package.js"
  },
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "test": "jest",
    "cdk": "cdk"
  },
  "devDependencies": {
    "@types/jest": "^26.0.10",
    "@types/node": "10.17.27",
    "jest": "^26.4.2",
    "ts-jest": "^26.2.0",
    "aws-cdk": "2.16.0",
    "ts-node": "^9.0.0",
    "typescript": "~3.9.7"
  },
  "dependencies": {
    "aws-cdk-lib": "2.16.0",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.16"
  }
}
```

对于可部署的 CDK 应用程序，必须在 `package.json` 的 `dependencies` 部分中指定 `aws-cdk-lib`。您可以使用脱字符（^）版本号说明符来表示您将接受比指定版本更高的版本，前提是它们位于同一个主版本内。

对于实验构造，请为 alpha 构造库模块指定确切的版本，这些版本可能会 APIs 发生变化。请勿使用 ^ 或 \$1，因为这些模块的更高版本可能会导致 API 发生更改，从而导致您的应用程序中断。

在 `package.json` 的 `devDependencies` 部分中指定测试应用程序所需的库和工具版本（例如，`jest` 测试框架）。或者使用 ^ 来指定可接受更高版本的兼容版本。

### 第三方构造库
<a name="work-with-cdk-javascript-dependencies-libraries"></a>

如果您正在开发构造库，请结合 `peerDependencies` 和 `devDependencies` 部分来指定其依赖项，如以下示例 `package.json` 文件所示。

```
{
  "name": "my-package",
  "version": "0.0.1",
  "peerDependencies": {
    "aws-cdk-lib": "^2.14.0",
    "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha",
    "constructs": "^10.0.0"
  },
  "devDependencies": {
    "aws-cdk-lib": "2.14.0",
    "@aws-cdk/aws-appsync-alpha": "2.10.0-alpha",
    "constructs": "10.0.0",
    "jsii": "^1.50.0",
    "aws-cdk": "^2.14.0"
  }
}
```

在 `peerDependencies` 中，使用脱字符（^）来指定您的库所使用的 `aws-cdk-lib` 的最低版本。这样可以最大限度地提高您的库与一系列 CDK 版本的兼容性。为 alpha 构造库模块指定确切的版本 APIs ，这些版本可能会发生变化。使用 `peerDependencies` 可以确保 `node_modules` 树中所有 CDK 库副本只有一个副本。

在 `devDependencies` 中，指定测试所需的工具和库，也可以使用 ^ 来表示可以接受更高版本的兼容版本。确切指定（不带 ^ 或 \$1）您宣称您的库与之兼容的 `aws-cdk-lib` 和其他 CDK 软件包的最低版本。这种做法可确保您的测试是针对这些版本运行的。这样，如果您无意中使用了仅较新版本中具备的功能，则您的测试可以将其捕捉到。

**警告**  
 只有 NPM 7 及更高版本才能自动安装 `peerDependencies`。如果您使用的是 NPM 6 或更早版本，或者使用的是 Yarn，则必须在 `devDependencies` 中包含依赖项的依赖项。否则，将不会进行安装，并且您将收到有关对等依赖项未解决的警告。

### 安装和更新依赖项
<a name="work-with-cdk-javascript-dependencies-install"></a>

运行以下命令来安装项目的依赖项。

**Example**  

```
# Install the latest version of everything that matches the ranges in 'package.json'
npm install

# Install the same exact dependency versions as recorded in 'package-lock.json'
npm ci
```

```
# Install the latest version of everything that matches the ranges in 'package.json'
yarn upgrade

# Install the same exact dependency versions as recorded in 'yarn.lock'
yarn install --frozen-lockfile
```

要更新已安装的模块，可以使用前面的 `npm install` 和 `yarn upgrade` 命令。任一命令都会将 `node_modules` 中的软件包更新为可满足 `package.json` 中规则的最新版本。但是，它们不会更新 `package.json` 本身，您可能需要执行此操作来设置新的最低版本。如果您在上托管软件包 GitHub，则可以将 De [pendabot 版本更新配置为自动更新](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates)。`package.json`或者，请使用 [npm-check-updates](https://www.npmjs.com/package/npm-check-updates)。

**重要**  
根据设计，当您安装或更新依赖项时，NPM 和 Yarn 会选择可满足 `package.json` 中指定要求的每个包的最新版本。这些版本始终存在损坏风险（无论是无意还是有意）。更新项目的依赖项后，请彻底进行测试。

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

### Props
<a name="javascript-props"></a>

所有 C AWS onstruct Library 类都使用三个参数进行实例化：定义构造的*作用域*（构造树中的父级）、*id* 和 *props*（构造函数用来配置其创建的 AWS 资源的一 key/value 组对）。其他类和方法也使用“属性捆绑包”模式作为参数。

使用具有良好 JavaScript 自动完成功能的 IDE 或编辑器将有助于避免拼写错误的属性名称。如果一个构造需要一个 `encryptionKeys` 属性，而您将其拼写为 `encryptionkeys`，那么在实例化构造时，您就没有传递您想要传递的值。如果该属性为必需，则这可能会导致在合成时出现错误；如果该属性为可选，则会无提示忽略该属性。在后一种情况下，您可能会得到一个您想要覆盖的默认行为。在这里要特别小心。

对 AWS 构造库类进行子类化（或重写采用类似 props 的参数的方法）时，您可能需要接受其他属性供自己使用。这些值将被父类或重写的方法忽略，因为在该代码中永远不会访问它们，因此通常可以传递收到的所有 props。

Future 版本的 AWS CDK 可能会巧合地添加一个新属性，其名称是你用于自己的财产。将收到的值沿继承链向上传递可能会导致意外行为。更安全的做法是传递您收到的 props 卷影副本，同时移除属性或将其设置为 `undefined`。例如：

```
super(scope, name, {...props, encryptionKeys: undefined});
```

或者，为您的属性命名，以便清楚地表明它们属于您的构造。这样，它们就不太可能在未来的 AWS CDK版本中与属性发生冲突。如果有很多属性，请使用一个适当命名的对象来存放它们。

### 缺失值
<a name="javascript-missing-values"></a>

对象（例如`props`）中的缺失值具有值`undefined` JavaScript。可以使用常用技术来处理这些问题。例如，以下是一个常见的习惯用法，用于访问可能未定义的值的属性：

```
// a may be undefined, but if it is not, it may have an attribute b
// c is undefined if a is undefined, OR if a doesn't have an attribute b
let c = a && a.b;
```

但是，如果 `a` 除 `undefined` 之外还可能具有其他“false”值，则最好让测试更加明确。在这里，我们将利用 `null` 等同于 `undefined` 的事实，来同时测试这两者：

```
let c = a == null ? a : a.b;
```

**提示**  
Node.js 14.0 及更高版本支持新的运算符，这些运算符可以简化未定义值的处理。有关更多信息，请参阅[可选链接](https://github.com/tc39/proposal-optional-chaining/blob/master/README.md)和 [Null 值合并](https://github.com/tc39/proposal-nullish-coalescing/blob/master/README.md)建议。

## 使用 TypeScript 示例 JavaScript
<a name="javascript-using-typescript-examples"></a>

 [TypeScript](https://www.typescriptlang.org/)是我们开发 AWS CDK 时使用的语言，也是开发应用程序时支持的第一种语言，因此编写了许多可用的 AWS CDK 代码示例。 TypeScript对于 JavaScript 开发人员来说，这些代码示例可能是一个很好的资源；你只需要删除代码中 TypeScript特定部分即可。

TypeScript 片段通常使用较新的 ECMAScript `import`和`export`关键字从其他模块导入对象，并声明要在当前模块之外提供的对象。Node.js 刚好在其最新版本中开始支持这些关键词。根据您正在使用（或希望支持）的 Node.js 版本，您可以重写导入和导出以使用旧语法。

可以将导入替换为对 `require()` 函数的调用。

**Example**  

```
import * as cdk from 'aws-cdk-lib';
import { Bucket, BucketPolicy } from 'aws-cdk-lib/aws-s3';
```

```
const cdk = require('aws-cdk-lib');
const { Bucket, BucketPolicy } = require('aws-cdk-lib/aws-s3');
```

可以将导出分配给 `module.exports` 对象。

**Example**  

```
export class Stack1 extends cdk.Stack {
  // ...
}

export class Stack2 extends cdk.Stack {
  // ...
}
```

```
class Stack1 extends cdk.Stack {
  // ...
}

class Stack2 extends cdk.Stack {
  // ...
}

module.exports = { Stack1, Stack2 }
```

**注意**  
使用旧式导入和导出的另一种方法是使用 [esm](https://www.npmjs.com/package/esm) 模块。

对导入和导出进行分类后，就可以深入研究实际的代码了。您可能会遇到以下常用功能 TypeScript ：
+ 类型注释
+ 接口定义
+ 类型转换/强制转换
+ 访问修饰符

可以为变量、类成员、函数参数和函数返回类型提供类型注释。对于变量、参数和成员，则通过在标识符后面加上冒号和类型来指定类型。函数返回值跟在函数签名后，由冒号和类型组成。

要将带类型注释的代码转换为 JavaScript，请删除冒号和类型。类成员中必须有一些值 JavaScript；`undefined`如果类成员中只有类型注释，则将其设置为 TypeScript。

**Example**  

```
var encrypted: boolean = true;

class myStack extends cdk.Stack {
    bucket: s3.Bucket;
    // ...
}

function makeEnv(account: string, region: string) : object {
    // ...
}
```

```
var encrypted = true;

class myStack extends cdk.Stack {
    bucket = undefined;
    // ...
}

function makeEnv(account, region) {
    // ...
}
```
在中 TypeScript，接口用于为必需属性和可选属性的捆绑包及其类型命名。然后，您可以使用接口名称作为类型注释。 TypeScript 将确保你用作函数参数的对象具有正确类型的必需属性。  

```
interface myFuncProps {
    code: lambda.Code,
    handler?: string
}
```

JavaScript 没有接口功能，因此删除类型注释后，请完全删除接口声明。

当函数或方法返回通用类型（例如`object`），但您想将该值视为更具体的子类型以访问不属于更一般类型接口的属性或方法时， TypeScript 允许您使用`as`后跟类型或接口名称来*转换*值。 JavaScript 不支持（或不需要）这个，所以只需删除`as`和以下标识符即可。一种不太常见的强制转换语法是在括号中使用类型名称 `<LikeThis>`；也必须删除这些强制转换。

最后， TypeScript 支持类成员的访问修饰符`public``protected`、和`private`。中的所有班级成员 JavaScript 都是公开的。在任何地方看到这些修饰符，将其删除即可。

知道如何识别和删除这些 TypeScript 功能对于使简短的 TypeScript 片段适应大有帮助. JavaScript 但是，以这种方式转换较长的 TypeScript 示例可能不切实际，因为它们更有可能使用其他 TypeScript 功能。对于这些情况，我们建议使用 [Sucrase](https://github.com/alangpierce/sucrase)。例如，如果代码使用了未定义的变量，Sucrase 就不会像 `tsc` 那样报错。如果它在语法上是有效的，那么除了少数例外，Sucrase 可以将其翻译为。 JavaScript因此，其对于转换可能无法自行运行的代码片段尤为有价值。

## 迁移到 TypeScript
<a name="javascript-to-typescript"></a>

[TypeScript](https://www.typescriptlang.org/)随着项目规模越来越大、越来越复杂，许多 JavaScript 开发人员开始使用。 TypeScript 是 JavaScript（所有 JavaScript 代码均为有效代码，因此无需对 TypeScript 代码进行任何更改）的超集，而且它也是一种受支持的 CDK 语言。 AWS 类型注释和其他 TypeScript 功能是可选的，当你发现其中的价值时，可以将其添加到你的 AWS CDK 应用程序中。 TypeScript 还允许您在新 JavaScript 功能最终确定之前抢先体验这些新功能，例如可选的链接和空值合并，而且无需升级 Node.js。

TypeScript的 “基于形状” 的接口，它定义了对象中的必需和可选属性（及其类型）的捆绑包，允许您在编写代码时发现常见错误，并使您的 IDE 更容易提供强大的自动完成功能和其他实时编码建议。

编程 TypeScript 确实涉及一个额外的步骤：使用编 TypeScript 译器编译应用程序`tsc`。对于典型的 AWS CDK 应用程序，编译最多需要几秒钟。

将现有 JavaScript AWS CDK 应用程序迁移到的最简单方法 TypeScript 是使用创建新 TypeScript 项目`cdk init app --language typescript`，然后将您的源文件（以及任何其他必需的文件，例如 Lamb AWS da 函数源代码等资产）复制到新项目。将 JavaScript 文件重命名为结尾`.ts`并开始开发 TypeScript。

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

Python 是 C AWS loud Development Kit (AWS CDK) 完全支持的客户端语言，被认为是稳定的。在 Python 中使用 AWS CDK 使用熟悉的工具，包括标准 Python 实现 (CPython)、虚拟环境和 Python 包安装程序`pip`。`virtualenv`构成 AWS 构造库的模块通过 [pypi](https://pypi.org/search/?q=aws-cdk) .org 分发。Python 版本的 AWS CDK 甚至使用 Python 风格的标识符（例如，`snake_case`方法名称）。

您可以使用任何编辑器或 IDE。许多 AWS CDK 开发者使用 [Visual Studio Code（或其开源代码](https://code.visualstudio.com/)的等效代码 [VSCodium](https://vscodium.com/)），该代码通过[官方扩展](https://marketplace.visualstudio.com/items?itemName=ms-python.python)对 Python 提供了良好的支持。Python 附带的 IDLE 编辑器足以帮助您入门。 AWS CDK 的 Python 模块确实有类型提示，这对于支持类型验证的 linting 工具或 IDE 非常有用。

## 开始使用 Python
<a name="python-prerequisites"></a>

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

Python AWS CDK 应用程序需要 Python 3.9 或更高版本。如果尚未安装，请在 [python.org](https://www.python.org/) 上为您的操作系统[下载兼容版本](https://www.python.org/downloads/)。如果您运行的是 Linux，则您的系统自带兼容版本，或者您可以使用发行版的包管理器（`yum`、`apt` 等）进行安装。Mac 用户可能会对 [Homebrew](https://brew.sh/) 感兴趣，这是一款适用于 macOS 的 Linux 风格的包管理器。

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

还需要使用 Python 包安装程序 `pip` 和虚拟环境管理器 `virtualenv`。在 Windows 上安装兼容的 Python 版本需要使用这些工具。在 Linux 上，`pip` 和 `virtualenv` 可以在软件包管理器中作为单独的软件包进行提供。或者，您可以使用以下命令进行安装：

```
python -m ensurepip --upgrade
python -m pip install --upgrade pip
python -m pip install --upgrade virtualenv
```

如果遇到权限错误，请运行带有 `--user` 标志的上述命令，以便将模块安装在您的用户目录中，或者使用 `sudo` 来获取在系统范围内安装模块的权限。

**注意**  
Linux 发行版通常使用可执行文件名称 `python3` 表示 Python 3.x，使用 `python` 表示 Python 2.x 安装。有些发行版有一个可以安装的可选包，可让 `python` 命令表示 Python 3。如果失败，您可以通过在项目的主目录中编辑 `cdk.json` 来调整用于运行应用程序的命令。

**注意**  
在 Windows 上，您可能需要使用 `py` 可执行文件（[适用于 Windows 的 Python 启动器](https://docs.python.org/3/using/windows.html#launcher)）来调用 Python（和 `pip`）。除此之外，启动器还允许您轻松指定要使用的 Python 安装版本。  
如果在命令行键入 `python` 后会显示一条关于从 Windows 应用商店安装 Python 的消息，即使安装了 Windows 版本的 Python，也请打开 Windows 的“管理应用程序执行别名”设置面板并关闭 Python 的两个应用程序安装程序条目。

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

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

```
$ mkdir my-project
$ cd my-project
$ cdk init app --language python
```

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

要使用新项目，请激活其虚拟环境。这允许将项目的依赖项安装在本地项目文件夹中，而不是全局安装。

```
$ source .venv/bin/activate
```

**注意**  
您可能会将其识别为激活虚拟环境的 Mac/Linux 命令。Python 模板包含一个批处理文件 `source.bat`，该文件允许在 Windows 上使用相同的命令。也可以使用传统的 Windows 命令 `.\venv\Scripts\activate`。  
如果您使用 AWS CDK Toolkit v1.70.0 或更早版本初始化 CDK 项目，则您的虚拟环境位于目录中，而不是。`.env` `.venv`

**重要**  
无论何时开始处理项目，都要激活该项目的虚拟环境。否则，您将无法访问安装在那里的模块，并且您安装的模块将进入 Python 全局模块目录（或将导致权限错误）。

首次激活虚拟环境后，请安装应用程序的标准依赖项：

```
$ python -m pip install -r requirements.txt
```

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

使用 Python 包安装程序安装和更新 AWS 构造库模块以供您的应用程序使用，以及您需要的其他包。`pip` `pip`还会自动安装这些模块的依赖关系。如果您的系统无法识别 `pip` 为独立命令，请将 `pip` 作为 Python 模块进行调用，如下所示：

```
$ python -m pip <PIP-COMMAND>
```

大多数 AWS CDK 结构都在。`aws-cdk-lib`实验性模块位于名称类似于 `aws-cdk.<SERVICE-NAME>.alpha` 的单独模块中。服务名称包含 *aws* 前缀。如果您不确定某个模块的名称，请[在 PyPI 上进行搜索](https://pypi.org/search/?q=aws-cdk)。例如，下面的命令安装该 AWS CodeStar 库。

```
$ python -m pip install aws-cdk.aws-codestar-alpha
```

某些服务的构造位于多个命名空间中。例如，除 `aws-cdk.aws-route53` 之外，还有另外三个 Amazon Route 53 命名空间，`aws-route53-targets`、`aws-route53-patterns` 和 `aws-route53resolver`。

**注意**  
[CDK API Reference 的 Python 版本](https://docs.aws.amazon.com/cdk/api/v2/python/index.html)也显示了包名称。

用于将 AWS 构造库模块导入 Python 代码的名称如下所示。

```
import aws_cdk.aws_s3 as s3
import aws_cdk.aws_lambda as lambda_
```

在应用程序中导入 AWS CDK 类和 AWS 构造库模块时，我们建议采用以下做法。遵循这些准则将有助于使您的代码与其他 AWS CDK 应用程序保持一致，并且更易于理解。
+ 通常，从顶层 `aws_cdk` 中导入单个类。

  ```
  from aws_cdk import App, Construct
  ```
+ 如果您需要 `aws_cdk` 中的许多类，则可以使用 `cdk` 的命名空间别名，而不是导入单个类。避免同时执行这两项操作。

  ```
  import aws_cdk as cdk
  ```
+ 通常，使用短命名空间别名导入 AWS 构造库。

  ```
  import aws_cdk.aws_s3 as s3
  ```

安装模块后，请更新项目的 `requirements.txt` 文件，其中列出了项目的依赖项。最好手动执行此操作，而不是使用 `pip freeze`。`pip freeze` 会捕获 Python 虚拟环境中安装的所有模块的当前版本，这在将项目捆绑到其他地方运行时非常有用。

但是，通常情况下，您的 `requirements.txt` 应该只列出顶级依赖项（您的应用程序直接依赖的模块），而不会列出这些库的依赖项。这种策略让更新依赖项变得更加简单。

您可以编辑 `requirements.txt` 以允许升级；只需将版本号前面的 `==` 替换为 `~=` 即可升级到更高的兼容版本，或者完全删除版本要求以指定模块的最新可用版本。

适当编辑 `requirements.txt` 以允许升级后，可以随时发出以下命令来升级项目中已安装的模块：

```
$ pip install --upgrade -r requirements.txt
```

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

在 Python 中，您可以在应用程序的 `requirements.txt` 或构造库的 `setup.py` 中输入依赖项来指定依赖项。然后使用 PIP 工具来管理依赖关系。通过以下方式之一来调用 PIP：

```
pip <command options>
python -m pip <command options>
```

`python -m pip` 调用适用于大多数系统；`pip` 要求 PIP 的可执行文件位于系统路径上。如果 `pip` 不起作用，请尝试将其替换为 `python -m pip`。

`cdk init --language python` 命令会为您的新项目创建一个虚拟环境。这样每个项目就都有自己的依赖项版本，还有一个基本 `requirements.txt` 文件。每次开始使用项目时，都必须运行 `source .venv/bin/activate` 来激活此虚拟环境。在 Windows 上，改为运行 `.\venv\Scripts\activate`

### CDK 应用程序
<a name="work-with-cdk-python-dependencies-apps"></a>

下面是一个 `requirements.txt` 示例文件。由于 PIP 不具备依赖锁定功能，我们建议您使用 == 运算符为所有依赖项指定确切的版本，如下所示。

```
aws-cdk-lib==2.14.0
aws-cdk.aws-appsync-alpha==2.10.0a0
```

使用 `pip install` 来安装模块不会自动将其添加到 `requirements.txt`。必须自己动手添加。如果要升级到依赖项的更高版本，请在 `requirements.txt` 中编辑其版本号。

要在创建或编辑 `requirements.txt` 后安装或更新项目的依赖项，请运行以下命令：

```
python -m pip install -r requirements.txt
```

**提示**  
`pip freeze` 命令以可写入文本文件的格式输出所有已安装依赖项的版本。这可以用作 `pip install -r` 的需求文件。此文件便于将所有依赖项（包括传递依赖项）固定到您测试过的确切版本。为避免以后升级软件包时出现问题，请为此使用单独的文件，例如 `freeze.txt`（不是 `requirements.txt`）。然后，在升级项目的依赖项时重新生成此文件。

### 第三方构造库
<a name="work-with-cdk-python-dependencies-libraries"></a>

在库中，依赖项在 `setup.py` 中进行指定，以便应用程序使用包时会自动下载传递依赖项。否则，每个想要使用包的应用程序都需要将您的依赖项复制到其 `requirements.txt` 中。此处显示了一个示例 `setup.py`。

```
from setuptools import setup

setup(
  name='my-package',
  version='0.0.1',
  install_requires=[
    'aws-cdk-lib==2.14.0',
  ],
  ...
)
```

要使用包进行开发，请创建或激活虚拟环境，然后运行以下命令。

```
python -m pip install -e .
```

尽管 PIP 会自动安装传递依赖项，但每个包只能安装一个副本。已选择依赖项树中指定的最高版本；应用程序对安装哪个版本的软件包始终拥有最终决定权。

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

### 语言冲突
<a name="python-keywords"></a>

在 Python 中，`lambda`是一个语言关键字，因此您不能将其用作 Lambda 构造库模块 AWS 或 Lambda 函数的名称。对于此类冲突，Python 的惯例是在变量名称中使用尾随下划线，如 `lambda_` 所示。

按照惯例， AWS CDK 构造的第二个参数被命名。`id`在编写自己的堆栈和构造时，调用参数 `id` 会“掩盖”Python 内置函数 `id()`，该函数用于返回对象的唯一标识符。此函数并不常用，但是如果您在构造中碰巧需要它，请重命名该参数，例如 `construct_id`。

### 参数和属性
<a name="python-props"></a>

所有 C AWS onstruct Library 类都使用三个参数进行实例化：定义构造的*作用域*（构造树中的父级）、*id* 和 *props*（构造函数用来配置其创建的资源的一 key/value 组对）。其他类和方法也使用“属性捆绑包”模式作为参数。

 *scope* 和 *id* 应始终作为位置参数而不是关键字参数进行传递，因为如果构造接受名为 *scope* 或 *id* 的属性，其名称就会改变。

在 Python 中，props 表示为关键字参数。如果参数包含嵌套数据结构，则使用在实例化时采用其自身关键字参数的类来表示这些结构。同样的模式也适用于采用结构化参数的其他方法调用。

例如，在 Amazon S3 存储桶的 `add_lifecycle_rule` 方法中，`transitions` 属性是 `Transition` 实例的列表。

```
bucket.add_lifecycle_rule(
  transitions=[
    Transition(
      storage_class=StorageClass.GLACIER,
      transition_after=Duration.days(10)
    )
  ]
)
```

扩展某个类或重写某种方法时，您可能希望接受父类无法理解的其他参数，以满足自己的目的。在这种情况下，您应该使用 \$1\$1kwargs 习语来接受您不在意的参数，并使用仅限关键字的参数来接受您感兴趣的参数。在调用父级的构造函数或重写的方法时，请仅传递所需的参数（通常只是 \$1\$1kwargs）。传递父类或方法不需要的参数会导致错误。

```
class MyConstruct(Construct):
    def __init__(self, id, *, MyProperty=42, **kwargs):
        super().__init__(self, id, **kwargs)
        # ...
```

Future 版本的 AWS CDK 可能会巧合地添加一个新属性，其名称是你用于自己的财产。这不会为您的构造或方法的用户带来任何技术问题（因为您的属性不会“向上沿链”传递，所以父类或重写的方法只会使用默认值），但可能会造成困惑。您可以对属性进行命名来避免这个潜在问题，这样它们就明确属于您的构造。如果有许多新属性，请将其捆绑到一个适当命名的类中，然后将其用作单个关键字参数进行传递。

### 缺失值
<a name="python-missing-values"></a>

 AWS CDK `None` 用来表示缺失或未定义的值。使用 \$1\$1kwargs 时，如果未提供属性，则使用词典的 `get()` 方法提供默认值。避免使用 `kwargs[…​]`，因为这会引发缺失值的 `KeyError`。

```
encrypted = kwargs.get("encrypted")         # None if no property "encrypted" exists
encrypted = kwargs.get("encrypted", False)  # specify default of False if property is missing
```

某些 AWS CDK 方法（例如`tryGetContext()`获取运行时上下文值）可能会返回`None`，您需要明确检查这些方法。

### 使用接口
<a name="python-interfaces"></a>

Python 不像其他一些语言那样具有接口功能，不过其确实有类似的[抽象基类](https://docs.python.org/3/library/abc.html)。（如果你不熟悉界面，维基百科[有一个很好的介绍](https://en.wikipedia.org/wiki/Interface_(computing)#In_object-oriented_languages)。） TypeScript，实现 AWS CDK 所用的语言，确实提供了接口，而构造和其他 AWS CDK 对象通常需要一个附属于特定接口的对象，而不是从特定类继承的对象。因此，作为 [JSI](https://github.com/aws/jsii) I 层的一部分， AWS CDK 提供了自己的接口功能。

要表示一个类实现了特定的接口，可以使用 `@jsii.implements` 装饰器：

```
from aws_cdk import IAspect, IConstruct
import jsii

@jsii.implements(IAspect)
class MyAspect():
    def visit(self, node: IConstruct) -> None:
        print("Visited", node.node.path)
```

### 类型陷阱
<a name="python-type-pitfalls"></a>

Python 使用动态类型，其中所有变量都可以表示任何类型的值。参数和返回值可以用类型进行注释，但这些是“提示”，不会强制执行。这意味着在 Python 中，很容易将错误类型的值传递给 AWS CDK 构造。当JSII层（在Python和 AWS CDK的 TypeScript 核心之间进行转换）无法处理意外类型时，您可能会遇到运行时错误，而不是像静态类型语言那样在构建过程中出现类型错误。

根据我们的经验，Python 程序员犯的类型错误往往属于以下类别。
+ 在构造需要容器（Python 列表或词典）的地方传递单个值，反之亦然。
+ 将与第 1 层（`CfnXxxxxx`）构造关联的类型的值传递给 L2 或 L3 构造，反之亦然。

## 防止类型错误
<a name="_preventing_type_errors"></a>

AWS CDK Python 模块包含类型注释，因此您可以在部署之前使用支持它们的工具来捕获类型错误。

### 集成集成开发环境（推荐）
<a name="_ide_integration_recommended"></a>

带有 Pylance 的 Visual Studio Code 可在你编写代码时提供实时类型检查：

1. 安装 [Pyl](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) ance 扩展程序 

1. 配置严格的类型检查`.vscode/settings.json`：

   ```
   {
     "python.languageServer": "Pylance",
     "python.analysis.typeCheckingMode": "strict"
   }
   ```

1. 现在，键入错误会立即出现，带有红色波浪线和详细的错误消息

 [PyCharm](https://www.jetbrains.com/pycharm/)还提供具有类似功能的内置类型检查。

### 命令行类型检查
<a name="_command_line_type_checking"></a>

对于 CI/CD 管道或预提交验证，请使用以下类型检查器之一：

 **MyPy （基于 Python）：**

```
pip install mypy
mypy app.py
```

 **Pyright（速度更快， JavaScript基于，引擎与 Pylance 相同）：**

```
npm install -g pyright
pyright app.py
```

### 推荐的工作流
<a name="_recommended_workflow"></a>

1. 开发过程中：使用 Pyright 或 Pylance 获得即时反馈

1. 提交之前：运行`mypy app.py`或 `pyright app.py` 

1. 在 CI/CD 中：在部署之前将类型检查作为必需的步骤

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

Java 是 AWS CDK 完全支持的客户端语言，被认为是稳定的。你可以使用熟悉的工具用 Java 开发 AWS CDK 应用程序，包括 JDK（甲骨文的，或者像 Amazon Corretto 这样的 OpenJDK 发行版）和 Apache Maven。

 AWS CDK 支持 Java 8 及更高版本。但是，我们建议您尽量使用最新版本，因为该语言的更高版本包含了特别便于开发 AWS CDK 应用程序的改进。例如，Java 9 引入了该`Map.of()`方法（一种声明哈希映射的便捷方法，该哈希映射将在中 TypeScript写成对象文字）。Java 10 使用 `var` 关键字引入了本地类型推断。

**注意**  
本《开发人员指南》中的大多数代码示例都采用 Java 8。有几个示例使用了 `Map.of()`；这些示例包含注释，指出它们需要使用 Java 9。

您可以使用任何文本编辑器或可以读取 Maven 项目的 Java IDE 来处理 AWS CDK 应用程序。我们在本指南中提供了 [Eclipse](https://www.eclipse.org/downloads/) 提示，但是 IntelliJ IDEA 等 IDEs 可以导入 Maven 项目 NetBeans，并且可以用来在 Java 中开发 AWS CDK 应用程序。

可以用 Jvm 托管的语言（例如 AWS Kotlin、Groovy、Clojure 或 Scala）以外的其他语言编写 CDK 应用程序，但这种体验可能不是特别习惯，我们无法为这些语言提供任何支持。

## 开始使用 Java
<a name="java-prerequisites"></a>

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

Java AWS CDK 应用程序需要 Java 8 (v1.8) 或更高版本。我们推荐 [Amazon Corretto](https://aws.amazon.com/corretto/)，但您可以使用任何 OpenJDK 发行版或 [Oracle JDK](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)。您还需要 [Apache Maven](https://maven.apache.org/download.cgi) 3.5 或更高版本。你也可以使用诸如 Gradle 之类的工具，但是 AWS CDK 工具包生成的应用程序框架是 Maven 项目。

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

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

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

```
$ mkdir my-project
$ cd my-project
$ cdk init app --language java
```

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

由此生成的项目包含对 `software.amazon.awscdk` Maven 包的引用。该包及其依赖项由 Maven 自动进行安装。

如果您使用的是 IDE，现在可以打开或导入项目了。例如，在 Eclipse 中，依次选择**文件** > **导入** > **Maven** > **现有的 Maven 项目**。确保将项目设置设为使用 Java 8（1.8）。

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

使用 Maven 安装组`software.amazon.awscdk`中的 AWS 构造库软件包。大多数构造都在构件 `aws-cdk-lib` 中，默认情况下，该构件会添加到新的 Java 项目中。仍在开发更高级别 CDK 支持的服务的模块位于单独的 “实验性” 包中，并以其服务名称的简短版本（无或 AWS Amazon 前缀）命名。[搜索 Maven 中央存储库](https://search.maven.org/search?q=software.amazon.awscdk)以查找所有 AWS CDK 和 C AWS onstruct Module 库的名称。

**注意**  
[CDK API Reference 的 Java 版本](https://docs.aws.amazon.com/cdk/api/v2/java/index.html)也显示了包名称。

某些服务的 AWS 构造库支持位于多个命名空间中。例如，Amazon Route 53 将其功能分为 `software.amazon.awscdk.route53`、`route53-patterns`、`route53resolver` 和 `route53-targets`。

主要 AWS CDK 包以 Java 代码导入为。`software.amazon.awscdk` AWS 构造库中各种服务的模块位于其下，其命名`software.amazon.awscdk.services`与它们的 Maven 包名称类似。例如，Amazon S3 模块的命名空间为 `software.amazon.awscdk.services.s3`。

我们建议您为每个 Java 源文件中使用的每个 AWS 构造库类编写单独的 Java `import` 语句，并避免导入通配符。您始终使用类型的完全限定名称（包括其命名空间），而无需使用 `import` 语句。

如果您的应用程序依赖于实验包，请编辑项目的 `pom.xml` 并在 `<dependencies>` 容器中添加新的 `<dependency>` 元素。例如，以下`<dependency>`元素指定了 CodeStar 实验构造库模块：

```
<dependency>
    <groupId>software.amazon.awscdk</groupId>
    <artifactId>codestar-alpha</artifactId>
    <version>2.0.0-alpha.10</version>
</dependency>
```

**提示**  
如果您使用 Java IDE，其可能具备管理 Maven 依赖项的功能。但是，除非您完全确定 IDE 的功能与您手动操作的功能相匹配，否则我们建议您直接编辑 `pom.xml`。

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

在 Java 中，使用 Maven 在 `pom.xml` 中指定依赖项并进行安装。`<dependencies>` 容器包含每个包的 `<dependency>` 元素。以下是常见的 CDK Java 应用程序 `pom.xml` 的其中一部分。

```
<dependencies>
    <dependency>
        <groupId>software.amazon.awscdk</groupId>
        <artifactId>aws-cdk-lib</artifactId>
        <version>2.14.0</version>
    </dependency>
    <dependency>
        <groupId>software.amazon.awscdk</groupId>
        <artifactId>appsync-alpha</artifactId>
        <version>2.10.0-alpha.0</version>
    </dependency>
</dependencies>
```

**提示**  
许多 Java IDEs 都集成了 Maven 支持和可视化`pom.xml`编辑器，您可能会发现它们便于管理依赖关系。

Maven 不支持依赖项锁定。尽管可以在 `pom.xml` 中指定版本范围，但我们建议您始终使用确切版本，以保持构建的可重复性。

Maven 会自动安装传递依赖项，但每个包只能安装一个副本。已选择 POM 树中指定的最高版本；应用程序对安装哪个版本的软件包始终拥有最终决定权。

每当您构建（`mvn compile`）或打包（`mvn package`）项目时，Maven 都会自动安装或更新您的依赖项。每次运行 CDK Toolkit 时，其都会自动执行此操作，因此通常无需手动调用 Maven。

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

### Props
<a name="java-props"></a>

所有 C AWS onstruct Library 类都使用三个参数进行实例化：定义构造的*作用域*（构造树中的父级）、*id* 和 *props*（构造函数用来配置其创建的资源的一 key/value 组对）。其他类和方法也使用“属性捆绑包”模式作为参数。

在 Java 中，props 是使用[生成器模式](https://en.wikipedia.org/wiki/Builder_pattern)来表示的。每种构造类型都有相应的 props 类型；例如，`Bucket` 构造（表示 Amazon S3 存储桶）将 `BucketProps` 的实例作为其 props。

该`BucketProps`类（就像每个 Constru AWS ct Library 道具类一样）有一个名`Builder`为的内部类。`BucketProps.Builder` 类型提供了设置 `BucketProps` 实例各种属性的方法。每个方法都会返回 `Builder` 实例，因此可以链接方法调用来设置多个属性。在链的末端，调用 `build()` 来实际生成 `BucketProps` 对象。

```
Bucket bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps.Builder()
                           .versioned(true)
                           .encryption(BucketEncryption.KMS_MANAGED)
                           .build());
```

构造和其他以类似 props 的对象作为最终参数的类提供了一种快捷方式。该类有自己的 `Builder`，可以一步将类以及其 props 对象进行实例化。这样，您就不必明确实例化（例如）`BucketProps` 和 `Bucket`，也不需要导入 props 类型。

```
Bucket bucket = Bucket.Builder.create(this, "amzn-s3-demo-bucket")
                           .versioned(true)
                           .encryption(BucketEncryption.KMS_MANAGED)
                           .build();
```

从现有构造派生自己的构造时，可能需要接受其他属性。我们建议您遵循这些构建器模式。然而，这并不是对构造类进行子类化那么简单。您必须自己提供这两个新 `Builder` 类的移动部件。您可能更愿意只让您的构造接受一个或多个额外参数。如果参数是可选的，则应提供额外的构造函数。

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

在某些情况下 APIs， 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)的方法。） 在 Java 中，这些对象表示为 `java.util.Map<String, Object>`。在值都为字符串的情况下，则可以使用 `Map<String, String>`。

与其他一些语言不同，Java 不提供为此类容器编写字面量的方法。在 Java 9 及更高版本中，您可以使用 [https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry…​-](https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry…​-) 方便地定义映射，这些映射最多包含十个条目且与其中一个调用内联。

```
java.util.Map.of(
    "base-directory", "dist",
    "files", "LambdaStack.template.json"
 )
```

要创建包含十个以上条目的映射，请使用 [https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry…​-](https://docs.oracle.com/javase/9/docs/api/java/util/Map.html#ofEntries-java.util.Map.Entry…​-)。

如果您使用的是 Java 8，则可以提供与这些方法类似的自己的方法。

JavaScript 数组在 Java `List<String>` 中以`List<Object>`或的形式表示。`java.util.Arrays.asList` 方法对于定义短 `List` 来说很方便。

```
List<String> cmds = Arrays.asList("cd lambda", "npm install", "npm install typescript")
```

### 缺失值
<a name="java-missing-values"></a>

在 Java 中，道具等 AWS CDK 对象中的缺失值用表示。`null`您必须明确测试任何可能为 `null` 的值，以确保其包含一个值，然后才能用其进行操作。Java 不像其他一些语言有“语法糖”来帮助处理 null 值。你可能会发现 Apac ObjectUtil h [https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#defaultIfNull-T-T-](https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#defaultIfNull-T-T-)e 在某些情况下[https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#firstNonNull-T…​-](https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/ObjectUtils.html#firstNonNull-T…​-)很有用。或者，也可以编写自己的静态辅助方法，以便更容易处理潜在的 null 值并提高代码的可读性。

## 构建和运行 CDK 应用程序
<a name="java-running"></a>

 AWS CDK 会在运行您的应用程序之前自动对其进行编译。但是，手动构建应用程序以检查错误并运行测试可能会很有用。您可以在 IDE 中执行此操作（例如，在 Eclipse 中按 Control-B），也可以在项目的根目录中在命令提示符下发出 `mvn compile` 命令来执行此操作。

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

# 在 C\$1 中使用 AWS CDK
<a name="work-with-cdk-csharp"></a>

.NET 是 AWS CDK 完全支持的客户端语言，被认为是稳定的。C\$1 是我们提供示例和支持的主要 .NET 语言。您可以选择使用其他.NET 语言（例如 Visual Bas AWS ic 或 F\$1）编写 AWS CDK 应用程序，但对在 CDK 中使用这些语言的支持有限。

你可以使用 Visual Stu AWS dio、Visual Studio Code、`dotnet`命令和 NuGet 包管理器等熟悉的工具在 C\$1 中开发 CDK 应用程序。构成 AWS 构造库的模块通过 [nuget](https://www.nuget.org/packages?q=amazon.cdk.aws) .org 分发。

我们建议在 Windows 上使用 [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/)（任何版本）使用 C\$1 开发 AWS CDK 应用程序。

## 开始使用 C\$1
<a name="csharp-prerequisites"></a>

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

[C\$1 AWS CDK 应用程序需要.NET 8.0 或更高版本，可在此处获得。](https://dotnet.microsoft.com/en-us/download/dotnet)

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

.NET 工具链包括`dotnet`用于构建和运行.NET 应用程序以及管理软件包的命令行工具。 NuGet 即使您主要在 Visual Studio 中工作，此命令也可用于批处理操作和安装 AWS 构造库包。

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

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

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

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

生成的项目包括对`Amazon.CDK.Lib` NuGet 包的引用。它及其依赖项由自动安装 NuGet。

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

.NET 生态系统使用 NuGet 软件包管理器。包含核心类和所有稳定服务构造的 CDK 主包为 `Amazon.CDK.Lib`。正在积极开发新功能的实验模块命名为`Amazon.CDK.AWS.<SERVICE-NAME>.Alpha`，其中服务名称是一个不带 AWS 或 Amazon 前缀的短名称。例如， AWS 物联网模块的 NuGet 软件包名称是`Amazon.CDK.AWS.IoT.Alpha`。如果您找不到想要的包，请[搜索 Nuget.org](https://www.nuget.org/packages?q=amazon.cdk.aws)。

**注意**  
[CDK API Reference 的 .NET 版本](https://docs.aws.amazon.com/cdk/api/latest/dotnet/api/index.html)也显示了包名称。

某些服务的 AWS 构造库支持位于多个模块中。例如， AWS 物联网有第二个名为的模块`Amazon.CDK.AWS.IoT.Actions.Alpha`。

在大多数 AWS CDK 应用程序中都需要的 AWS CDK 的主模块是以 C\$1 代码导入的。`Amazon.CDK` AWS 构造库中各种服务的模块位于其下`Amazon.CDK.AWS `。例如，Amazon S3 模块的命名空间为 `Amazon.CDK.AWS.S3`。

我们建议为 CDK 核心结构以及您在每个 C\$1 源文件中使用的每项 AWS 服务编写 C\$1 `using` 指令。您可能发现使用命名空间或类型的别名来帮助解决名称冲突会很方便。您始终使用类型的完全限定名称（包括其命名空间），而无需使用 `using` 语句。

## 在 C\$1 中管理依赖项
<a name="work-with-cdk-csharp-dependencies"></a>

在 C\$1 AWS CDK 应用程序中，您可以使用管理依赖关系。 NuGet NuGet 有四个标准的、基本上等同的接口。使用适合您需求和工作方式的接口。您还可以使用兼容的工具，例如 [Paket](https://fsprojects.github.io/Paket/)，[MyGet](https://www.myget.org/)甚至可以直接编辑`.csproj`文件。

NuGet 不允许您为依赖项指定版本范围。每个依赖项都固定在一个特定的版本上。

更新依赖关系后，Visual Studio 将在下次生成时使用 NuGet 检索每个包的指定版本。如果您没有使用 Visual Studio，请使用 `dotnet restore` 命令更新您的依赖项。

### 直接编辑项目文件
<a name="manage-dependencies-csharp-direct-edit"></a>

您项目的 `.csproj` 文件包含一个 `<ItemGroup>` 容器，该容器将您的依赖项列为 `<PackageReference` 元素。

```
<ItemGroup>
    <PackageReference Include="Amazon.CDK.Lib" Version="2.14.0" />
    <PackageReference Include="Constructs" Version="%constructs-version%" />
</ItemGroup>
```

### 视觉工作室 NuGet 图形用户界面
<a name="manage-dependencies-csharp-vs-nuget-gui"></a>

Visual Studio 的 NuGet 工具可通过 “**工具**” > “**NuGet 包管理器**” > **“管理解决方案 NuGet 包” 进行**访问。使用 “**浏览**” 选项卡查找要安装的 AWS 构造库软件包。您可以选择所需的版本，包括模块的预发布版本，然后将其添加到任何打开的项目中。

**注意**  
所有被视为 “实验性” 的 Con AWS struct Library 模块（参见 [AWS CDK 版本控制](versioning.md)）都被标记为预发行版， NuGet 并带有名称后缀。`alpha`

![\[NuGet 包管理器显示各种服务的 Amazon CDK <shared id="AWS"/> alpha 套餐。\]](http://docs.aws.amazon.com/zh_cn/cdk/v2/guide/images/visual-studio-nuget.png)


查看**更新**页面，以便安装软件包的新版本。

### 控制 NuGet 台
<a name="manage-dependencies-csharp-vs-nuget-console"></a>

 NuGet 控制台是一个 PowerShell基于 Visual Studio 项目的界面 NuGet ，可以在 Visual Studio 项目的上下文中运行。你可以在 Visual Studio 中通过选择 “**工具**” > “**NuGet 包管理器” > “Packag** e Man **ager 控制台**” 将其打开。有关使用此工具的更多信息，请参阅[使用 Visual Studio 包管理器控制台安装和管理软件包](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-powershell)。

### `dotnet` 命令
<a name="manage-dependencies-csharp-vs-dotnet-command"></a>

`dotnet` 命令是处理 Visual Studio C\$1 项目的主要命令行工具。您可以从任何 Windows 命令提示符调用该命令。在其众多功能中，`dotnet`可以向 Visual Studio 项目添加 NuGet 依赖关系。

假设您与 Visual Studio 项目（`.csproj`）文件位于同一个目录中，请发出如下命令来安装包。由于创建项目时包含了 CDK 主库，您只需要显式安装实验模块即可。实验性模块需要您指定明确的版本号。

```
dotnet add package Amazon.CDK.AWS.IoT.Alpha -v <VERSION-NUMBER>
```

您可以从另一个目录发出该命令。为此，请将项目文件路径或含有该文件的目录路径包含在 `add` 关键字之后。以下示例假设您位于 AWS CDK 项目的主目录中。

```
dotnet add src/<PROJECT-DIR> package Amazon.CDK.AWS.IoT.Alpha -v <VERSION-NUMBER>
```

要安装包的特定版本，请包含 `-v` 标志和所需版本。

要更新包，请发出与安装包时相同的 `dotnet add` 命令。同样，对于实验性模块，必须指定明确的版本号。

有关使用 `dotnet` 命令来管理软件包的更多信息，请参阅[使用 dotnet CLI 安装和管理软件包](https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-dotnet-cli)。

### `nuget` 命令
<a name="manage-dependencies-csharp-vs-nuget-command"></a>

`nuget`命令行工具可以安装和更新 NuGet 软件包。但是，该工具要求您 Visual Studio 项目的设置方式与 `cdk init` 设置项目的方式不同。（技术细节：`nuget` 用于 `Packages.config` 项目，而 `cdk init` 则创建更新风格的 `PackageReference` 项目。

我们不建议在创建的 AWS CDK 项目中使用该`nuget`工具。`cdk init`如果您正在使用其他类型的项目，并且想要使用`nuget`，请参阅 [NuGet CLI 参考](https://docs.microsoft.com/en-us/nuget/reference/nuget-exe-cli-reference)。

## AWS C\$1 中的 CDK 成语
<a name="csharp-cdk-idioms"></a>

### Props
<a name="csharp-props"></a>

所有 C AWS onstruct Library 类都使用三个参数进行实例化：定义构造的*作用域*（构造树中的父级）、*id* 和 *props*（构造函数用来配置其创建的资源的一 key/value 组对）。其他类和方法也使用“属性捆绑包”模式作为参数。

在 C\$1 中，props 是使用 props 类型表示的。按照惯用的 C\$1 方式，我们可以使用对象初始化程序来设置各种属性。此处我们使用 `Bucket` 构造创建一个 Amazon S3 存储桶；其对应的 props 类型为 `BucketProps`。

```
var bucket = new Bucket(this, "amzn-s3-demo-bucket", new BucketProps {
    Versioned = true
});
```

**提示**  
将包 `Amazon.JSII.Analyzers` 添加到您的项目中，以便在 Visual Studio 内的 props 定义中检查所需值。

在扩展某个类或重写某种方法时，您可能希望接受父类无法理解的其他 props，以满足自己的目的。为此，请将相应的 props 类型进行子类化并添加新属性。

```
// extend BucketProps for use with MimeBucket
class MimeBucketProps : BucketProps {
    public string MimeType { get; set; }
}

// hypothetical bucket that enforces MIME type of objects inside it
class MimeBucket : Bucket {
     public MimeBucket( readonly Construct scope, readonly string id, readonly MimeBucketProps props=null) : base(scope, id, props) {
         // ...
     }
}

// instantiate our MimeBucket class
var bucket = new MimeBucket(this, "amzn-s3-demo-bucket", new MimeBucketProps {
    Versioned = true,
    MimeType = "image/jpeg"
});
```

在调用父类的初始化程序或重写的方法时，通常可以传递接收到的 props。新类型与其父类型兼容，您添加的额外 props 将被忽略。

Future 版本的 AWS CDK 可能会巧合地添加一个新属性，其名称是你用于自己的财产。这不会导致使用您的构造或方法时出现任何技术问题（因为您的属性不会“向上沿链”传递，所以父类或重写的方法只会使用默认值），但可能会给您的构造用户带来困惑。您可以对属性进行命名来避免这个潜在问题，这样它们就明确属于您的构造。如果有许多新属性，请将其捆绑到一个适当命名的类中，然后将其作为单个属性进行传递。

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

在某些情况下 APIs， AWS CDK 使用 JavaScript 数组或非类型化对象作为方法的输入。（例如， AWS CodeBuild请参阅[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_codebuild.BuildSpec.html)的方法。） 在 C\$1 中，这些对象表示为 `System.Collections.Generic.Dictionary<String, Object>`。如果值都是字符串，则可以使用`Dictionary<String, String>`。 JavaScript 在 C\$1 中，`string[]`数组表示为`object[]`或数组类型。

**提示**  
您可以定义简短的别名，以便更容易使用这些特定的词典类型。  

```
using StringDict = System.Collections.Generic.Dictionary<string, string>;
using ObjectDict = System.Collections.Generic.Dictionary<string, object>;
```

### 缺失值
<a name="csharp-missing-values"></a>

在 C\$1 中，道具等 AWS CDK 对象中的缺失值用表示。`null`Null 条件成员访问运算符 `?.` 和 Null 值合并运算符 `??` 可以便捷地处理这些值。

```
// mimeType is null if props is null or if props.MimeType is null
string mimeType = props?.MimeType;

// mimeType defaults to text/plain. either props or props.MimeType can be null
string MimeType = props?.MimeType ?? "text/plain";
```

## 构建和运行 CDK 应用程序
<a name="csharp-running"></a>

 AWS CDK 会在运行您的应用程序之前自动对其进行编译。但是，手动构建应用程序以检查错误并运行测试可能会很有用。您可以通过在 Visual Studio 中按 F6 或从命令行发出 `dotnet build src` 命令来执行此操作，其中 `src` 是项目目录中包含 Visual Studio 解决方案（`.sln`）文件的目录。

# 在 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) `。