Dart: Dart 基础语法 — 程序结构、注释与代码风格
语法是代码的骨架 — 规范的语法习惯决定代码的可读性和可维护性。
1. 你将学到
- main() 入口函数与程序执行模型
- 分号、花括号与缩进规范(dart format 规则)
- 三种注释:行注释 / 块注释 / 文档注释(
///) - 关键字总览与保留字
- 语句与表达式的区别
2. 一个开发者的真实故事
(1) 痛点:注释缺失导致代码无法维护
Charlie 接手了前同事留下的一段数据处理代码,没有任何注释。500 行代码里充斥着魔法数字和缩写变量名,他花了 3 天才搞清楚 p 代表 product、t 代表 taxRate。更糟的是,一个关键的税率计算逻辑因为缺少文档注释,新同事误以为是 bug 而修改,导致 2000 笔订单的税额计算错误,直接经济损失 50,000 USD。
(2) 规范语法的解法
Dart 提供了三种注释方式,配合 dart format 自动格式化和 dart analyze 静态检查,可以写出结构清晰、注释完善的代码。
/// Calculates the tax amount for an order.
///
/// Uses the regional tax rate and applies exemptions
/// for orders below the minimum threshold.
double calculateTax(double amount, double taxRate, {double exemptThreshold = 0}) {
// Apply exemption threshold
if (amount <= exemptThreshold) return 0;
/* Complex tax calculation logic
that may span multiple lines */
final taxableAmount = amount - exemptThreshold;
return taxableAmount * taxRate;
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
(3) 收益
- 文档注释可被
dart doc自动生成 API 文档 - dart format 统一团队代码风格,消灭格式争论
- 规范命名 + 注释让代码可维护性提升 3 倍
3. 程序结构与 main 入口
(1) 程序执行模型
每个 Dart 程序都从 main() 函数开始执行。Dart 是单线程事件循环模型,但可以通过 Isolate 实现并行。
graph TD
A[OS loads Dart VM] --> B[Find main function]
B --> C[Execute main body]
C --> D{Has async operations?}
D -->|No| E[Program exits]
D -->|Yes| F[Event loop runs]
F --> G[Process microtasks]
G --> H[Process events]
H --> I{More events?}
I -->|Yes| G
I -->|No| E
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
▶ 示例
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
:main 函数的基本形式
// Simplest main function
void main() {
print('DataPipeline starting...');
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
▶ 示例
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
:带参数的 main 函数
// main with command line arguments
void main(List``<String>`` arguments) {
// arguments[0] is the first arg (not the program name)
print('Arguments received: $arguments');
print('Argument count: ${arguments.length}');
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
| main 形式 | 签名 | 用途 |
|---|---|---|
| 无参数 | void main() |
简单脚本 |
| 带参数 | void main(List``<String>`` args) |
CLI 工具 |
| 带返回值 | Future``<void>`` main() |
异步入口 |
4. 分号、花括号与缩进
(1) 基本语法规则
Dart 使用分号 ; 结束语句,花括号 {} 包裹代码块。缩进为 2 个空格(dart format 强制)。
▶ 示例
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
:分号与花括号
void main() {
// Each statement ends with semicolon
int orderCount = 1000;
double totalAmount = 50000.0;
// Block body requires curly braces
if (orderCount > 0) {
print('Processing $orderCount orders');
} else {
print('No orders to process');
}
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
| 规则 | 说明 | dart format 处理 |
|---|---|---|
| 分号结尾 | 每条语句必须以 ; 结束 |
不自动添加 |
| 花括号 | if/for/while 必须用 {} |
自动格式化 |
| 缩进 | 2 空格缩进 | 自动修正 |
| 行宽 | 建议 80 字符内 | 不强制 |
5. 三种注释方式
(1) 行注释 //
用于单行说明,最常用。
▶ 示例
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
:行注释
void main() {
// Initialize the data pipeline
final maxRecords = 1000000; // Maximum records to process
// TODO: Add config file support
print('Max capacity: $maxRecords records');
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
(2) 块注释 /* */
用于多行说明或临时禁用代码。
▶ 示例
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
:块注释
void main() {
/* This section handles the initial setup
of the DataPipeline configuration.
It reads from environment variables. */
final config = 'production';
/*
// Temporarily disabled for debugging
if (config == 'production') {
enableLogging();
}
*/
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
(3) 文档注释 ///
用于生成 API 文档,支持 Markdown 格式。
▶ 示例
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
:文档注释
/// Represents an e-commerce order with tax calculation.
///
/// This class models a single order from the DataPipeline
/// system, including amount, tax rate, and status.
///
/// Example:
/// ```dart
/// final order = Order(id: 'ORD-001', amount: 1500.0);
/// print(order.totalWithTax);
/// ```
class Order {
final String id;
final double amount;
Order({required this.id, required this.amount});
double get totalWithTax => amount * 1.08;
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
| 注释类型 | 语法 | 用途 | 生成文档 |
|---|---|---|---|
| 行注释 | // |
代码说明、TODO | 否 |
| 块注释 | /* */ |
多行说明、禁用代码 | 否 |
| 文档注释 | /// |
API 文档 | 是(dart doc) |
6. 关键字与保留字
(1) Dart 关键字分类
| 类别 | 关键字 | 说明 |
|---|---|---|
| 声明 | class enum mixin extension typedef |
类型声明 |
| 修饰 | abstract sealed final const late static |
修饰符 |
| 控制 | if else for while do switch return |
流程控制 |
| 异常 | try catch finally throw rethrow |
异常处理 |
| 异步 | async await sync yield |
异步编程 |
| 类型 | int double String bool dynamic void |
内置类型 |
| 空安全 | null late required |
Null Safety |
▶ 示例
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
:避免使用保留字作为标识符
// Correct - use descriptive names
int orderCount = 100;
String customerName = 'Alice';
double taxRate = 0.08;
// Wrong - avoid reserved words as identifiers
// int class = 5; // Syntax error!
// String function = 'test'; // Syntax error!
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
7. 语句与表达式
(1) 核心区别
表达式(Expression) 有返回值,语句(Statement) 没有返回值。这是理解 Dart 语法的基础。
graph TD A[Code Unit] --> B[Expression<br/>has value] A --> C[Statement<br/>no value] B --> B1[literal: 42] B --> B2[variable: count] B --> B3[operation: a + b] B --> B4[function call: max(1, 2)] C --> C1[if-else] C --> C2[for loop] C --> C3[return statement] C --> C4[variable declaration]
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
▶ 示例
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
:表达式 vs 语句
void main() {
// Expressions - produce values
int count = 100; // 100 is an expression
double price = 29.99; // 29.99 is an expression
double total = price * count; // price * count is an expression
bool isExpensive = total > 1000; // total > 1000 is an expression
// Statements - do not produce values
if (isExpensive) { // if statement
print('High value order'); // print call statement
}
// Dart 3: switch expression (expression!)
String label = switch (count) {
0 => 'empty',
<= 10 => 'small',
<= 100 => 'medium',
_ => 'large',
};
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
| 维度 | 表达式 | 语句 |
|---|---|---|
| 返回值 | 有 | 无 |
| 嵌套 | 可以嵌套在其他表达式中 | 独立执行 |
| 示例 | a + b, x > 0 |
if, for, return |
| Dart 3 新增 | switch 表达式 | — |
8. 完整示例:DataPipeline 代码风格模板
// ============================================
// DataPipeline - Code Style Template
// Demonstrates proper syntax, comments, and structure
// ============================================
/// Configuration for the DataPipeline processing engine.
///
/// Holds settings like maximum batch size, output format,
/// and whether to enable verbose logging.
class PipelineConfig {
/// Maximum number of records per processing batch.
final int batchSize;
/// Output format for generated reports.
final String outputFormat;
/// Enable detailed processing logs.
final bool verbose;
/// Creates a new pipeline configuration.
///
/// Default batch size is 10,000 records.
/// Default output format is 'json'.
PipelineConfig({
this.batchSize = 10000,
this.outputFormat = 'json',
this.verbose = false,
});
/// Returns a human-readable summary of the config.
String get summary =>
'Batch: $batchSize records, Format: $outputFormat, Verbose: $verbose';
}
/// Entry point for DataPipeline CLI tool.
void main(List``<String>`` arguments) {
// Step 1: Load configuration
final config = PipelineConfig(
batchSize: 50000,
outputFormat: 'csv',
verbose: true,
);
// Step 2: Display configuration
print('=== DataPipeline Configuration ===');
print(config.summary);
// Step 3: Process based on arguments
/* TODO: Implement actual data processing
- Read input source
- Transform records
- Write output report
*/
final recordCount = arguments.isNotEmpty ? int.tryParse(arguments[0]) ?? 0 : 0;
if (recordCount > 0) {
print('Processing $recordCount records...');
} else {
print('No records specified. Use: dart run bin/main.dart ``<record_count>``');
}
}
> **输出:** 在本地 DartPad 或 `dart run` 执行。Dart 课程所有示例基于 Dart 3.x / Flutter 3.x,运行结果会因 SDK 版本略有差异。
输出(
dart run bin/main.dart 100000):
=== DataPipeline Configuration ===
Batch: 50000 records, Format: csv, Verbose: true
Processing 100000 records...
❓ 常见问题
Q:Dart 必须用分号吗? A:是的,Dart 每条语句必须以分号结尾,不像 Python/Go 可以省略。这是 Dart 最常见的初学者错误。
Q:行注释和文档注释该用哪个? A:公开 API(类、公开方法、公开属性)用 /// 文档注释;内部实现细节用 // 行注释。dart doc 只处理文档注释。
Q:dart format 会改变代码逻辑吗? A:不会。dart format 只调整空白和换行,不改变代码语义。可以放心在 CI 中使用 --set-exit-if-changed。
Q:Dart 中 if 可以不用花括号吗? A:语法上,if 后跟单条语句可以省略花括号,但 dart format 会自动加上。强烈建议始终使用花括号。
Q:switch 表达式和 switch 语句有什么区别? A:switch 表达式(Dart 3)有返回值,用 => 分支;switch 语句没有返回值,用 case: 分支。前者更简洁,后者更灵活。
Q:文档注释用 /// 还是 / /? A:Dart 官方推荐用 ///。虽然 /* / 也有效,但 /// 是 Dart 社区的主流风格,dart format 也按 /// 排版。*
Q:main 函数可以返回 int 吗? A:Dart 的 main 返回类型是 void 或 Future
<void>。进程退出码可通过 dart:io 的 exit() 函数设置。
📖 小节
- Dart 程序从 main() 开始执行,支持同步和异步两种入口形式
- 分号、花括号、2 空格缩进是 Dart 的基本语法规则,dart format 自动保障
- 三种注释各司其职:// 行注释、/* */ 块注释、/// 文档注释(生成 API 文档)
- 关键字分为声明、修饰、控制、异常、异步、类型、空安全 7 大类
- 表达式有返回值,语句没有 — Dart 3 的 switch 表达式弥合了这一鸿沟
📝 作业
- 基础题(难度⭐):写一个 main 函数,用三种注释方式各写一段注释,运行
dart doc .查看生成的文档注释效果。 - 进阶题(难度⭐⭐):故意写几段格式不规范的 Dart 代码(混合缩进、缺少花括号),然后用
dart format自动修正,对比修改前后的差异。 - 挑战题(难度⭐⭐⭐):为一个包含 3 个方法的类编写完整的文档注释(包含描述、参数说明、示例代码),运行
dart doc生成 HTML 文档并查看效果。