前言
Dart 不是學院語言 (C、C++),也不是商業語言 (Java、C#)。所以我們採取「避坑」的角度介紹這個語言,降低從其他語言轉過來時的摩擦。
當前定位
目前 Dart 最主要的用途是寫 Flutter 應用程式。這是一個跨平台 Mobile Framework。由於 Flutter 的 UI 是直接繪製的,反而不會有平台間不一致的問題。只有在深入一部分硬體底層功能時,才會撞到 Flutter 的邊界。
如果要把 Dart 當成通用語言的話,語法成熟度是足夠的。但 Dart 的 ecosystem 比較小,要懂得如何和沒有 binding 的外部庫合作。一些常見的模式是 FFI、Microservice、CLI,可根據情境來選擇。
沒有全域函式庫
主流程式語言,像 Python,會先從一個 app.py 開始,慢慢擴大 code base。必要時用 pip install 安裝全域庫來用。Python 也有基於 project 的隔離環境,但那是後來加上去的,不是原生功能。
但 Dart 一開始就沒有全域庫。使用 app.dart 單檔撰碼的話,只能用 Dart 內建庫,很快就會碰到邊界。所以,Dart 一定是基於 project 來撰碼。關鍵在於專案根目錄的那份 pubspec.yaml 設定檔。
選擇合適的 Dart 專案
這裡的「專案」不是什麼商業產品,也不是開源專案,只是用目錄和設定檔管理 Dart 程式碼的一種方式。
當你執行 dart create 時,可選的專案如下:
console:簡單的命令列程式,最適合初學者練習。cli:帶有命令列解析的命令列程式package:當你想把程式碼打包成函式庫供人使用時選擇。server-shelf:用 Shelf 撰寫網頁中介程式。web:用 Dart 標準函式庫寫網頁程式。
初學的話,建議用 console 專案。等到寫熟了,可以開始用 package 寫函式庫。其他專案較少使用,知道有這些選項即可。
寫一陣子後,預設專案會不夠用,這時候要學習如何手動修改 pubspec.yaml。如果有自己用得順手的專案架構,也可以弄成一個 GitHub Template Repo,以後根據這個 Repo 改就好,不用每次從頭刻。
安裝函式庫
Dart 有兩種安裝模式:
- 局部安裝:
dart pub add,用來安裝專案所需的函式庫,會記錄在pubspec.yaml。 - 全域安裝:
dart pub global activate,用來安裝命令列工具。
即使你全域安裝了某個工具,Dart 在執行專案代碼時,只會認定專案內的局部函式庫。這是為了保護專案穩定度,避免不同專案因為同一個函式庫的版本衝突而炸掉。
自動排版程式碼
不要花時間排 Dart 程式碼,寫完後用 dart format 自動重排。只要注意維持一致的撰碼風格,像是 camelCase、PascalCase、snake_case 的差別。
這裡有個排版秘訣:多用「尾隨逗號」 (Trailing Commas)。在函式或建構式的最後一個參數後面加上逗號,dart format 就會自動幫你把長參數展開成多行,這在寫 Flutter UI 時特別有用。建議到官網看一下撰碼風格指南。
自動檢查程式碼
Dart 沒必要像 Rust 那麼嚴格,連所有權、多執行緒規範都寫進編譯器。但 Dart 也不是直接放任程式碼在 runtime 炸掉的語言。
不要輕易地用 dynamic 型態或語法技巧來迴避 Dart 的 Linter 檢查。想一下為什麼會報錯,當下多花 15 分鐘弄清楚程式碼在做什麼,可以讓你晚上睡得更安穩。
Null Safety (空安全)
Dart 3.0 以後已經全面進入「100% Sound Null Safety」時代。這意味著你無法再寫出非空安全的代碼。
雖然 Dart 無法保證外部資料(如 API 回傳值)不為空,但它強制你處理。有可能為空的變數必須寫成 String? 而不是 String。善用 ?. (選用串連) 或 ?? (預設值),可以讓程式碼更簡潔,避免 null 在 runtime 導致崩潰。
主函式
Dart 的主函式很彈性。傳統的主函式如下:
void main(List<String> arguments) {
/* 撰寫程式碼 */
}
如果你需要處理非同步(例如呼叫 API、讀寫檔案),則使用非同步模式:
Future<void> main(List<String> arguments) async {
/* 使用 await 處理非同步邏輯 */
}
除非你的程式完全不涉及 Web 環境或非同步資源,否則習慣寫非同步模式是比較保險的做法。
道地的 Dart 程式碼
幾乎沒有人把 Dart 當成第一個語言。剛開始寫時,往往會寫出帶著其他語言味道的 Dart 程式碼。
這是正常現象。程式的底線是「能正常運作」,再來是「有效率」。寫久了,自然會發現 Dart 獨有的語法糖(如級連操作符 .. 或展開操作符 ...)能大幅縮減代碼。不用急著一次到位,別讓語法規則限制了你的解題邏輯。
結語
本文提出了一些學習 Dart 常見的坑,希望可以幫助讀者順利啟航,避開不必要的挫折。