1. 基础语法与变量
变量声明
var name = 'Dart'; // 类型推导为 String
String name = 'Dart'; // 显式类型
final name = 'Dart'; // 运行时常量 (类似 Go 的 const,但值可以运行时确定)
const name = 'Dart'; // 编译时常量 (类似 Go 的常量,只能赋编译时常量值)
late String name; // 延迟初始化,类似 TS 的 ! 断言或 Go 里先声明后赋值
dynamic anything = 'hello'; // 动态类型,类似 TS 的 any
Object anything = 'hello'; // 所有类的基类,类似 TS 的 unknown
与 Go 的差异
Go 用 := 短声明,Dart 用 var 或直接类型标注。
Go 的 const 只能是编译时常量(数字、字符串、布尔),Dart 的 const 同理,但 final 可以运行时赋值一次,这是 Go 没有的概念。
Dart 有 late 关键字,解决非空延迟赋值,Go 没有对应特性(靠指针默认零值)。
与 TS 的差异
TS 的 let 和 const 是变量绑定不可变,值本身可变。Dart 的 final 和 const 才是真正不可重新赋值。
TS any 是“放弃类型检查”,Dart dynamic 也是,但 Dart 的类型系统更严格,调用不存在的方法会在运行时抛出异常,而 TS 不会。
late 在 TS 中通常配合 ! 断言使用,但 Dart 的 late 会在第一次访问时自动检查是否已初始化,更安全。
空安全 (Null Safety)
Dart 默认不可为 null,需显式声明:
String? nullable; // 可为 null
String nonNullable = 'hi'; // 不可为 null
nonNullable ??= 'default'; // 若为 null 则赋值 (类似 Go 的 if nil)
nullable?.length; // 安全调用 (类似 TS 可选链)
Go 对比 :Go 无空安全,nil 指针可用但无语法糖,需手动 if err != nil。Dart 的 ?.、?? 是强制的空安全语法,减少代码。
TS 对比 :TS 有 strictNullChecks 选项,开启后与 Dart 类似,但 ?. 和 ?? 语法相同,Dart 多了 late 非空延迟和 required 命名参数(见下方)。
2. 函数
Dart 函数是一等公民,支持闭包、箭头函数、可选参数。
// 普通函数
int add(int a, int b) => a + b;
// 命名可选参数 (大括号)
void greet({required String name, int age = 18}) { }
// 位置可选参数 (中括号)
void sum(int a, [int b = 0, int c = 0]) { }
// 函数类型定义
typedef IntCallback = int Function(int a);
Go 差异
Go 函数没有默认参数(需通过结构体或函数选项模式),Dart 支持默认值和命名参数。
Dart 箭头函数 => 只能是单一表达式,而 Go 没有箭头函数。
Dart 的 required 在 Go 中只能通过结构体强制要求。
TS 差异
TS 也有默认参数和可选参数(?),但 Dart 明确区分命名参数(名称必须提供)和位置参数,TS 只有位置参数。
Dart 的 required 是编译时强制,类似 TS 中在类型上标记为必填(但 TS 常有 undefined)。
TS 支持函数重载声明(多个签名),Dart 不支持重载,但可通过可选参数和命名参数实现类似效果。
3. 类和面向对象
Dart 是纯面向对象语言,所有非 null 值都是对象,支持单继承、mixin、接口(隐式实现)。
class Animal {
final String name; // 成员变量
Animal(this.name); // 构造函数简写
Animal.named({required this.name}); // 命名构造函数
}
class Dog extends Animal with Bark {
Dog(String name) : super(name); // 初始化列表调用父类构造
@override
void makeSound() => print('Woof'); // 方法重写
}
mixin Bark {
void bark() => print('Bark!');
}
// 隐式接口:任何类都可作为接口实现
class Robot implements Animal {
@override
String get name => 'Robot';
}
Go 差异
Go 没有类,用结构体和接口组合。Dart 有完整的类、继承、构造函数体系。
Go 的接口是鸭子类型隐式实现,Dart 的 implements 需要显式声明并实现所有成员(隐式接口)。
Dart 支持 mixin(代码复用机制,类似多继承但无状态),Go 通过嵌入(embedding)实现组合,但不能像 mixin 那样复用方法实现并限制范围。
Dart 的构造函数可重载不同名称,Go 需使用工厂函数。
TS 差异
TS 的类语法与 Dart 非常相似,但 Dart 没有 public/protected/private 关键字,用 _ 前缀表示库私有(library-private),文件内可见。
TS 通过 implements 实现接口(显式),Dart 相同。TS 的 abstract 类 Dart 也有。
Dart 不支持装饰器实验性语法外的元数据,比 TS 的装饰器弱。
Dart 的 mixin 更纯粹,TS 一般用 mixin 模式(函数实现)或多重继承结合接口,不如 Dart 的语言级别支持。
4. 异步编程
Dart 使用 Future 和 Stream,配合 async/await。
Future
<String> fetchData() async {
final result = await http.get(url);
return result.body;
}
// Stream (类似 Go 的 channel 或 RxJS Observable)
Stream
<int> countStream(int max) async* {
for (var i = 1; i <= max; i++) {
yield i;
await Future.delayed(Duration(seconds: 1));
}
}
Go 对比
Go 没有 async/await,使用 goroutine + channel。Dart 的异步模型是单线程事件循环(isolate),类似 Node.js 的事件驱动。
Dart 的 Future 类似 Go 的 future 模式或 channel,但语法更简洁。Go 的并发是 M:N 调度,Dart 的并发通过 isolate(独立内存堆)。
Stream 对应 Go 的 channel,但 Dart 是 push-based,且可通过 async* 生成。
TS 对比
TS/JS async/await 与 Dart 几乎一致,都基于 Promise/Future。
TS 的 Observable(RxJS)比 Dart 的 Stream 功能更丰富,Dart 的 Stream 更基础,但有转换方法。
注意:Dart 的 `Future
` 类似 `Promise`,但 Dart 没有 `.then` 链上自动展开嵌套,需显式处理。
5. 集合类型 (List, Set, Map)
类型
Dart
Go
TS
列表
`List
或[1,2]| 切片[]int,无泛型方法 |number[]或Array`
集合
`Set
,{1,2}字面量 | 无内建 Set,用map[Key]bool|Set`
映射
Map<String, int>,{k:v}
map[string]int
Record<string, number> 或 Map
常用方法
map, where, fold,first
for range, slices 包
原生 map, filter, reduce 等
Dart 集合是泛型和强类型的,支持链式操作(返回 Iterable),可再转为 List。
Dart 特有的 collection if/for 语法糖:
var list = [
1,
if (promoActive) 2,
for (var i in items) i.price,
];
Go 差异 :Go 的切片/映射无内置高阶方法,需循环处理。Dart 集合 API 更接近函数式风格。需注意 Dart 的 List.filled(n, el) 填的是相同引用,Go 的 make([]T, n) 是零值。
TS 差异 :API 相似,但 TS 的数组方法会直接修改原数组(如 push),Dart 的 List 默认是可变的,但 add 等操作类似。Dart 的 const 列表是不可变且编译时常量。
6. 类型系统与泛型
Dart 的类型是强静态类型,有类型推断,泛型支持型变控制。
class Box
<T> {
final T value;
Box(this.value);
}
// 限制类型参数
class NumberBox<T extends num> {}
// 型变(Dart 默认是 invariant,可使用关键字)
// 但典型用法是使用 `covariant` 关键字或函数型变。
Go 差异
Go 1.18+ 引入泛型,语法为 func F[T any](t T),Dart 用 `
` 紧跟类、函数名。
Go 泛型基于合约 (interface 约束),Dart 用 extends 限制上界。
Dart 没有类似 Go 的类型集和近似类型的理念。
TS 差异
TS 泛型语法极为相似,差异点:TS 有条件类型、映射类型、模板字面量类型等高级特性,Dart 类型系统更简单。
TS 结构类型 (structural) ,Dart 名义类型 (nominal),即便相同结构的两个类也不同,需显式实现接口。
7. 模块、导入和可见性
Dart 使用库 (library) 作为代码组织单位,每个 .dart 文件默认是一个库。
import 'dart:math'; // 核心库
import 'package:http/http.dart'; // 包
import 'my_file.dart'; // 相对/绝对路径
import 'my_file.dart' as utils; // 别名,类似 Go 的 import alias / TS 的 import * as
import 'my_file.dart' show foo; // 只导入 foo
import 'my_file.dart' hide bar; // 隐藏 bar
Go 差异
Go 使用包 (package) ,一个目录一个包,导入路径。Dart 鼓励单文件一个库,无强制目录对应。
Go 的导出通过首字母大写,Dart 以 _ 前缀表示库私有(仅文件内可见)。
Go 不允许循环导入,Dart 允许(但不鼓励)。
TS 差异
TS/ES 模块是 import/export,Dart 的 import 语法类似,但 Dart 没有 default export,所有顶级声明被隐式导出,除非用 _ 前缀私有。
TS 的 import type 在 Dart 无对应,Dart 全部导入。
8. 错误处理
try {
throw FormatException('bad');
} on FormatException catch (e, stack) {
print(e);
} finally {
// cleanup
}
Go 差异 :Go 没有异常,用返回错误值和多返回值。Dart 既有异常也有 Error 和 Exception 类型,类似其他面向对象语言。
TS 差异 :TS/JS 也有 try/catch,但 Dart 不支持 catch 无参数,必须捕获对象。Dart 的 on 可以只捕获特定类型。
9. 并发模型:Isolate
Dart 是单线程事件循环(类似 JS),长时间任务需使用 Isolate。
import 'dart:isolate';
Isolate.spawn(heavyTask, message);
Go 对比 :Go 天然支持 goroutine 和 channel,Dart 的 Isolate 有独立内存,通信靠消息传递,与 Go 的并发哲学类似但重量不同。普通开发中用 compute 函数快捷创建。
TS 对比 :TS 通过 Web Workers 或 Node.js worker_threads,同样通过消息通信。语法差异明显。
10. 常用模式速查
场景
Dart
Go
TS
多返回值
返回 Record (2.17+) 或 List
原生多返回值
返回元组或对象
枚举
enum Color { red, green }
无原生枚举,用 iota
类似 Dart,支持数字和字符串枚举
扩展方法
extension on String { }
无,通过函数
类似,声明合并也可
别名
typedef 或 extension
type MyType = ...
type 关键字
代码生成
build_runner, 注解处理器
go generate
装饰器/ts-morph等
11. 变量声明:final vs const vs late
差异点 :Go 只有编译时 const,没有运行时单次赋值的 final;TS 的 const 是引用不可变。late 是 Dart 特有的延迟非空初始化。
Dart 示例 :
// final:运行时确定,但只能赋值一次
final now = DateTime.now(); // Go 无法用 const 做到,TS 的 const 允许 push 数组,这里不一样
// const:编译时常量,类似 Go 的 const,TS 没有这个概念
const apiUrl = 'https://api.example.com';
// late:先声明后初始化,访问前必须赋值,类似 TS 的非空断言!但带检查
late String description;
description = 'Dart is fun';
print(description); // OK
// Go: const apiUrl = "..."
// TS: const apiUrl = "..." as const? 不是编译时常量
12. 空安全:?、??、required
差异点 :Go 没有以此为基础的语法糖,全靠 nil 检查;TS 可选链 ?. 类似,但 Dart 强制非空,必须显式声明可空类型 String?。
Dart 示例 :
String? nullableName;
// 空安全调用
print(nullableName?.length); // 不会报错,输出 null
// 空值合并
String name = nullableName ?? 'Guest'; // 类似 Go: if name == "" { name = "Guest" }
// required 命名参数
void greet({required String name}) {}
// greet(); // 编译错误,类似 TS 里强制必填,但 Dart 更严格,运行时不会有 undefined
13. 函数参数:命名可选 vs 位置可选 vs 重载
差异点 :Go 函数无默认参数和命名参数;TS 只有位置可选参数,且通过函数重载声明多签名。
Dart 示例 :
// 命名可选参数(必须通过名称传递)
void configure({bool? darkMode, int? fontSize}) {}
configure(darkMode: true, fontSize: 14); // 必须指定参数名
// 位置可选参数
void log(String msg, [String? tag, int? level]) {}
log('hello'); // 可选的位置参数可跳过
// Dart 没有函数重载,用可选参数模拟
// TS 可以写多个 function signature,Dart 不行
void handle(String input) => print('String');
// void handle(int input) => print('int'); // 错误:重复定义
14. 类:构造函数、mixin、隐式接口、私有成员
差异点 :Go 无类,用结构体和接口;TS 有类但 mixin 较弱,且访问修饰符为 public/private/protected。
Dart 示例 :
class Animal {
final String name;
Animal(this.name); // 简洁构造
Animal.named({required this.name}); // 命名构造,Go 需要工厂函数
// 私有成员(下划线开头,库内可见,非类内)
void _privateMethod() {}
}
mixin Swimmer {
void swim() => print('swimming');
}
class Duck extends Animal with Swimmer {
Duck(String name) : super(name);
}
// 隐式接口:任何类都可以作为接口被实现
class Robot implements Animal {
@override
String get name => 'Robot'; // 必须实现 Animal 的所有公共成员
// 不需要继承,纯粹实现接口
}
对比 :Go 的结构体嵌入可以实现类似组合,但无法像 mixin 那样复用方法同时限制基类。TS 没有原生的 mixin 关键字,一般用函数生成类或者混入模式实现。
15. 异步:Future、Stream vs Go goroutine vs Promise
差异点 :Go 用 goroutine + channel,Dart 用单线程事件循环 + Future/Stream;TS 类似但 Stream 更基础,且 Dart 没有自带 Observable。
Dart 示例 :
Future
<String> fetchData() async {
// 类似 TS 的 async/await,Go 需要用 goroutine+channel 模拟
await Future.delayed(Duration(seconds: 1));
return 'data';
}
// Stream 类似 Go 的 channel,但有更多变换
Stream
<int> numbers() async* {
for (int i = 0; i < 3; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
Go 类似概念 :
// chan int 类似 Stream
<int>
func numbers() chan int {
ch := make(chan int)
go func() {
for i := 0; i < 3; i++ {
time.Sleep(time.Second)
ch <- i
}
close(ch)
}()
return ch
}
// 消费:for num := range numbers() { }
16. 集合操作与 collection if/for
差异点 :Go 切片/映射无内置高阶方法;TS 有 map、filter 等,但 Dart 提供了额外的声明式集合构建语法。
Dart 示例 :
// collection if:根据条件添加元素
bool promoActive = true;
var items = [1, 2, 3];
var list = [
'header',
if (promoActive) 'PROMO',
for (var i in items) i * 10, // 循环生成
];
// list => ['header', 'PROMO', 10, 20, 30]
// Go 需要手动循环 append
// TS 可以用数组展开 [...(promoActive ? ['PROMO'] : []), ...items.map(x => x*10)]
链式调用 :
final result = [1, 2, 3, 4]
.where((n) => n > 2) // 过滤
.map((n) => n * 2) // 映射
.toList(); // 转为 List,TS 自动转换,Dart 需显式调用
// Go 需要 for 循环实现
17. 类型系统:名义类型 vs 结构类型
差异点 :TS 是结构类型,Dart 是名义类型(除了 dynamic 和 Object 的兼容)。Go 的接口也是结构类型。
Dart 示例 :
class Point {
int x, y;
Point(this.x, this.y);
}
class Coordinate {
int x, y;
Coordinate(this.x, this.y);
}
// 即使结构完全相同,也不能直接赋值
Point p = Coordinate(1, 2); // 编译错误
// 需要显式实现接口或转换
// TS 中如果两个类型结构相同,可以互相赋值,无错误
18. 模块可见性:_ 私有 vs export 导出
差异点 :Go 首字母大写导出;TS 用 export 显式导出,有默认导出。Dart 顶级声明默认全部导出,仅 _ 前缀表示文件内私有。
Dart 示例 :
// file: utils.dart
void publicFunction() {}
void _privateFunction() {} // 仅本文件可见
// 使用时
import 'utils.dart';
publicFunction(); // OK
_privateFunction(); // 编译错误
对比 :
Go:func privateFunc() 小写包内可见,PublicFunc 大写导出。
TS:需要 export function publicFunc(),未导出的在模块外不可见,且支持 export default。
19. 错误处理:catch 必须指定参数,on 类型捕获
差异点 :Go 无异常,用多返回值;TS 的 catch 可以不写参数,Dart 必须捕获对象。
Dart 示例 :
try {
throw FormatException('Bad format');
} on FormatException catch (e) {
// 捕获特定类型
print(e.message);
} catch (e) {
// 捕获所有,必须写参数
print(e);
} finally {
// 清理
}
TS 可以写 catch { /* 无参数 */ },Dart 不允许。
20. Isolate 并发 vs goroutine vs Worker
差异点 :Dart 的 Isolate 是独立内存的隔离体,通过消息通信。Go 的 goroutine 共享内存但有 GMP 调度,更轻量。TS 的 Worker 类似 Isolate 但 API 不同。
Dart 示例 :
import 'dart:isolate';
void heavyComputation(SendPort sendPort) {
// 这里运行在独立 Isolate,内存不共享
int result = 0;
for (int i = 0; i < 100000000; i++) {
result += i;
}
sendPort.send(result);
}
void main() async {
final receivePort = ReceivePort();
await Isolate.spawn(heavyComputation, receivePort.sendPort);
final result = await receivePort.first;
print(result);
}
Go 直接用 go heavyComputation() 共享内存。TS 需要 new Worker('worker.js') 并在不同文件。
21. 扩展方法 (extension)
差异点 :Go 不支持扩展一个类型(只能定义新函数);TS 也有声明合并/原型扩展,但 Dart 通过 extension 提供类型安全的静态扩展。
Dart 示例 :
extension StringX on String {
String get reversed => split('').reversed.join();
}
void main() {
print('hello'.reversed); // olleh
}
Go :定义包级函数 func Reverse(s string) string。TS :可以 String.prototype.reversed 或通过 interface 声明合并,但不如 Dart 安全明确。
22. 枚举:增强型枚举 vs iota 与 TS 枚举
差异点 :Go 用 iota 实现枚举常量,功能较弱;TS 支持数字和字符串枚举。Dart 支持增强型枚举,可带成员和方法。
Dart 示例 :
enum Color {
red(0xFF0000),
green(0x00FF00),
blue(0x0000FF);
final int hex;
const Color(this.hex);
}
void main() {
print(Color.red.hex); // 16711680
}
Go :
type Color int
const (
Red Color = iota
Green
Blue
)
TS 枚举更接近 Dart,但不能直接带方法和工厂。