现在位置: 首页 > Dart 教程 > 正文

第一个 Dart 程序

学习一门编程语言,最好的方式不是先背语法规则,而是先跑起来一个程序,再一行一行地问这是什么意思。

本章我们将从一个最简单的程序出发,逐步扩展到一个稍微完整的小程序,在这个过程中把 Dart 最基础的概念都过一遍。


最简单的程序:Hello, Dart!

打开 DartPad(或本地编辑器),输入以下代码:

实例

void main() {
  print('Hello, Dart!');
}

点击运行,输出:

Hello, Dart!

就这 3 行代码。现在我们来把每一个字符都弄清楚。


逐行解析

void main() {

这是程序的入口函数声明,Dart 程序永远从 main() 开始执行。

拆开来看:

部分含义
void返回值类型。void 表示"这个函数执行完后不返回任何值"
main函数名。这是 Dart 约定的入口函数名,不能改成别的
()参数列表。这里是空的,表示 main 函数不接受任何参数
{函数体的开始。与最后一行的 } 配对,包裹函数的所有代码

main() 是 Dart 的唯一入口。不管你的程序有多少个文件、多少个类,执行总是从 main() 的第一行开始。

print('Hello, Dart!');

这是一条语句,作用是把括号内的内容输出到控制台。

拆开来看:

部分含义
print内置函数名,用于向控制台输出一行文字
(...)函数调用的参数列表
'Hello, Dart!'一个字符串字面量,用单引号 ' 包裹
;语句结束符。每条语句必须以分号结尾
前面的两个空格缩进,表示这行代码属于 main() 函数内部。Dart 约定用 2 个空格缩进

}

main() 函数体的结束标志,与开头的 { 配对。

整体结构图

void main() {          ← 函数签名(返回类型 + 函数名 + 参数)
  print('Hello,        ← 函数体:调用 print 函数
         Dart!');      ← 传入字符串参数,以 ; 结尾
}                      ← 函数体结束

字符串的两种写法

Dart 中字符串可以用单引号或双引号包裹,两者完全等价。

实例

void main() {
  print('Hello, Dart!');   // 单引号
  print("Hello, Dart!");   // 双引号,效果相同
}
Hello, Dart!
Hello, Dart!

什么时候用哪种引号?可以参考以下场景:

场景推荐示例
一般情况单引号(Dart 社区约定)'Hello'
字符串内含有单引号双引号"It's a beautiful day!"
字符串内含有双引号单引号'他说:"你好"'

字符串内容本身含有单引号时,用双引号包裹更方便,省去转义。Dart 社区约定优先使用单引号,本教程后续也以单引号为主。


注释

注释是写给人看的说明文字,Dart 编译器会完全忽略它。

实例

void main() {
  // 这是单行注释,从 // 开始到行尾
  print('Hello, Dart!'); // 也可以写在语句后面

  /*
    这是多行注释。
    可以跨越多行,
    常用于临时注释掉一大段代码。
  */


  /// 这是文档注释,用于描述函数、类或变量的作用。
  /// IDE 会将文档注释显示为悬浮提示。
}
注释类型语法用途
单行注释// 内容解释某一行代码
多行注释/* 内容 */注释掉一段代码,或写较长说明
文档注释/// 内容描述 API,生成文档用

好注释解释"为什么",而不是"做了什么"。代码本身已经说明了"做了什么",注释应该补充背后的原因或意图。


变量:给数据起名字

程序不可能只输出固定文字,我们需要变量来存储和使用数据。

实例

void main() {
  String name = 'RUNOOB';
  int age = 25;
  double height = 1.68;
  bool isStudent = true;

  print(name);
  print(age);
  print(height);
  print(isStudent);
}
RUNOOB
25
1.68
true

变量声明的格式

类型名  变量名  =  初始值  ;
 │       │         │      └─ 语句结束符
 │       │         └─ 赋值运算符
 │       └─ 你给这个数据起的名字
 └─ 告诉 Dart 这个变量存储什么类型的数据

基本数据类型速览

类型说明示例
String文本字符串'RUNOOB'、"hello"
int整数25、-10、0
double小数(浮点数)1.68、3.14
bool布尔值(真/假)true、false

数据类型的详细内容将在后续章节展开,这里先有个初步印象。


用 var 自动推断类型

每次都写类型名有点繁琐。

Dart 支持用 var 关键字自动推断变量类型——编译器会根据你赋的值来判断类型。

实例

void main() {
  var name = 'RUNOOB';    // 推断为 String
  var age = 25;           // 推断为 int
  var height = 1.68;      // 推断为 double
  var isStudent = true;   // 推断为 bool

  print(name);
  print(age);
}
RUNOOB
25

var 推断的类型在编译期就确定了,之后不能再赋值成别的类型。

实例

void main() {
  var name = 'RUNOOB';
  name = 'Bob';    // 可以,仍然是 String
  // name = 123;   // 错误:不能把 int 赋给 String 类型的变量
}

什么时候用 var,什么时候写明类型?

场景推荐原因
局部变量,类型一眼就能看出来var更简洁
函数参数、类的字段、返回值类型写明类型代码更清晰,自文档化

字符串插值:把变量嵌入字符串

如果想把变量的值嵌入到字符串里,Dart 提供了非常简洁的字符串插值语法——用 $变量名 或 ${表达式}。

实例

void main() {
  var name = 'RUNOOB';
  var age = 25;

  print('我叫 $name,今年 $age 岁。');
  print('明年我将 ${age + 1} 岁。');
}
我叫 RUNOOB,今年 25 岁。
明年我将 26 岁。
语法用途示例
$变量名直接嵌入变量值,简洁$name
${表达式}嵌入任意表达式(计算、方法调用等)${age + 1}、${name.toUpperCase()}

相比 print('我叫 ' + name + ',今年 ' + age.toString() + ' 岁。') 这种字符串拼接写法,插值语法更清晰、更安全,是 Dart 的惯用风格。


一个稍完整的小程序

现在我们把前面学到的东西综合起来,写一个稍微真实一点的程序:一个简单的自我介绍生成器。

实例

void main() {
  // 个人信息
  var name = 'RUNOOB';
  var age = 25;
  var city = '上海';
  var isStudent = false;
  var hobby = 'Dart 编程';

  // 生成介绍语:三元运算符判断身份
  var occupation = isStudent ? '学生' : '职场人';

  print('=============================');
  print('       个人简介');
  print('=============================');
  print('姓名:$name');
  print('年龄:$age 岁');
  print('城市:$city');
  print('身份:$occupation');
  print('爱好:$hobby');
  print('-----------------------------');
  print('大家好,我是来自$city的$name,');
  print('今年 $age 岁,是一名$occupation。');
  print('我的爱好是${hobby},很高兴认识大家!');
  print('=============================');
}
=============================
       个人简介
=============================
姓名:RUNOOB
年龄:25 岁
城市:上海
身份:职场人
爱好:Dart 编程
-----------------------------
大家好,我是来自上海的RUNOOB,
今年 25 岁,是一名职场人。
我的爱好是Dart 编程,很高兴认识大家!
=============================

新出现的语法:三元运算符

实例

var occupation = isStudent ? '学生' : '职场人';

这是 Dart 的三元运算符,格式为:

条件 ? 条件为真时的值 : 条件为假时的值

等价于以下 if/else 写法:

实例

String occupation;
if (isStudent) {
  occupation = '学生';
} else {
  occupation = '职场人';
}

三元运算符在值只有两种可能时非常简洁,后续章节会详细介绍 if/else 的完整用法。


代码风格:Dart 的书写规范

好的代码风格让代码更易读、更专业。

Dart 有一套官方推荐的规范,初学阶段掌握以下几点就够了。

缩进用 2 个空格

实例

// 正确:2 个空格
void main() {
  print('Hello');
}

// 不推荐:4 个空格(其他语言常见,但 Dart 社区偏好 2 格)

变量和函数名用小驼峰(lowerCamelCase)

实例

var firstName = 'RUNOOB';     // 小驼峰:正确
// var first_name = 'RUNOOB'; // 下划线风格:非 Dart 惯例
// var FirstName = 'RUNOOB';  // 大驼峰:保留给类名

类名用大驼峰(UpperCamelCase)

实例

class UserProfile { }   // 正确
// class user_profile { }  // 错误
// class userProfile { }   // 错误

常量用小驼峰(不是全大写)

实例

const maxRetries = 3;       // Dart 惯例:正确
// const MAX_RETRIES = 3;   // 这是 C/Java 风格,Dart 不推荐

使用 dart format 自动格式化

不用死记规范,只需在项目目录下运行:

$ dart format .

Dart 官方格式化工具会自动把代码调整为标准风格,保存时 VS Code 也可以配置自动格式化。


常见错误与解读

初学者写第一个程序时经常遇到以下错误,来认识一下它们。

错误一:忘记分号

实例

void main() {
  print('Hello, Dart!')  // 缺少 ;
}

报错信息:

Error: Expected ';' after this.

解决方法:在语句末尾加上 ;。

错误二:括号不配对

实例

void main() {
  print('Hello, Dart!'   // 缺少右括号 )
}

报错信息:

Error: Expected ')' before this.

解决方法:仔细检查每个 ( 是否都有对应的 )。VS Code 会高亮显示不匹配的括号。

错误三:字符串引号不匹配

void main() {
  print('Hello, Dart!");  // 一个单引号、一个双引号
}

报错信息:

Error: Unterminated string literal.

解决方法:确保字符串两端用同一种引号。

错误四:main 拼写错误

实例

void Main() {  // M 大写了
  print('Hello, Dart!');
}

Dart 区分大小写,Main 和 main 是完全不同的名字。

程序能编译,但运行时会报错:

Error: No 'main' method found.

解决方法:入口函数必须是小写的 main。

错误五:变量在使用前未赋值

实例

void main() {
  String name;
  print(name);  // name 未初始化
}

Dart 空安全机制的报错:

Error: Non-nullable variable 'name' must be assigned before it can be used.

解决方法:声明变量时同时赋初值,或声明为可空类型 String? name(后续章节详细介绍)。