(譯)Dart2.12版本發(fā)布内狸,可靠的空安全检眯,dart:ffi正式投入生產(chǎn)

1.Dart平臺獨有的功能

在我們詳細研究可靠的空安全和FFI之前,讓我們討論一下Dart平臺如何將它們適合我們的目標昆淡。編程語言傾向于共享許多的功能锰瘸。例如,許多語言都支持面向?qū)ο蟮木幊袒蛘呖梢栽赪eb上運行昂灵。真正使語言與眾不同的是它們獨特的功能組合


Dart的獨特功能涵蓋了三個方面:

  • 可移植性:高效的編譯器為設(shè)備生成x86ARM機器代碼避凝,并為Web生成優(yōu)化的JavaScript。一個廣泛的目標是支持:移動設(shè)備眨补,臺式機管削,應(yīng)用后端,等等撑螺。大量的庫和軟件包提供了可在所有平臺上使用的一致的API含思,從而進一步降低了創(chuàng)建真正的多平臺應(yīng)用程序的成本。

  • 高效:Dart平臺支持熱重裝甘晤,從而可以對本機設(shè)備和Web進行快速含潘,迭代的開發(fā)。Dart提供了諸如內(nèi)存隔離線程和異步/等待之類的豐富結(jié)構(gòu)线婚,用于處理常見的并發(fā)和事件驅(qū)動的應(yīng)用程序模式遏弱。

  • 健壯:Dart健全的,空安全類型系統(tǒng)會在開發(fā)過程中捕獲錯誤酌伊。整個平臺具有高度的可擴展性和可靠性腾窝,其廣泛的應(yīng)用程序用于生產(chǎn)已超過十年,包括Google AdsGoogle Assistant等業(yè)務(wù)關(guān)鍵型應(yīng)用程序居砖。

可靠的空安全性使類型系統(tǒng)更加強大虹脯,并實現(xiàn)了更好的性能。Dart FFI使您可以使用現(xiàn)有的C庫以實現(xiàn)更好的可移植性奏候,并可以選擇對性能要求很高的任務(wù)使用經(jīng)過高度調(diào)整的C代碼循集。

2.可靠的空安全

自Dart 2.0引入可靠的空安全類型系統(tǒng)以來,空安全是Dart語言的最大補充蔗草≈渫空安全性進一步增強了類型系統(tǒng),使您能夠捕獲空錯誤咒精,這是應(yīng)用程序崩潰的常見原因镶柱。通過選擇空安全性,您可以在開發(fā)過程中捕獲空錯誤模叙,從而防止生產(chǎn)崩潰歇拆。
合理的空安全性是圍繞一些核心原則設(shè)計的。讓我們重新審視這些原則如何影響您作為開發(fā)人員。

3.默認情況下可為空:是對類型系統(tǒng)的基本的改變

空安全之前的核心挑戰(zhàn)是故觅,您無法分辨預期傳遞空值的代碼與不能使用空值的代碼之間的區(qū)別厂庇。幾個月前,我們在Flutter主渠道渠道中發(fā)現(xiàn)了一個錯誤输吏,該錯誤會在某些機器配置上使各種flutter工具命令崩潰权旷,并出現(xiàn)null錯誤:The method '>=' was called on null。根本的問題是這樣的代碼:

final int major = version?.major;
final int minor = version?.minor;
if (globals.platform.isMacOS) {
  // plugin path of Android Studio changed after version 4.1.
  if (major >= 4 && minor >= 1) {
  ...

您能發(fā)現(xiàn)錯誤嗎贯溅?因為version可以為null拄氯,所以majorminor也可以為null。似乎很容易孤立地發(fā)現(xiàn)此錯誤盗迟,但實際上坤邪,即使是經(jīng)過嚴格的代碼審查過程(如Flutter主分支中所用的代碼),這種代碼也會無時無刻不在出現(xiàn)罚缕。出于安全考慮艇纺,靜態(tài)分析會立即捕獲此問題。(可以在DartPad中試用邮弹。

那是一個非常簡單的錯誤黔衡。在Google內(nèi)部內(nèi)部在代碼中早期使用null安全性的過程中,我們發(fā)現(xiàn)了很多復雜的錯誤腌乡。其中一些是已經(jīng)存在多年的bug盟劫,但是如果沒有null安全性的額外靜態(tài)檢查,團隊就無法找到原因与纽。這里有一些例子:

  • 一個內(nèi)部團隊發(fā)現(xiàn)侣签,他們經(jīng)常檢查永遠不能為null的表達式的null值。使用protobuf的代碼中最經(jīng)常出現(xiàn)此問題急迂,其中可選字段在未設(shè)置時返回默認值影所,并且永遠不會為null。如此一來僚碎,通過混淆默認值和空值猴娩,代碼錯誤地檢查了默認條件。
  • Google Pay小組在Flutter代碼中發(fā)現(xiàn)了一些錯誤勺阐,這些錯誤會在嘗試State在上下文之外訪問Flutter對象時失敗的Widget卷中。在實現(xiàn)null安全之前,這些對象將返回null并掩蓋錯誤渊抽;出于安全考慮蟆豫,可靠的分析器確定這些屬性永遠不會為空,并引發(fā)了分析錯誤懒闷。
  • Flutter小組發(fā)現(xiàn)了一個錯誤十减,如果將該錯誤null傳遞給中的scene參數(shù)徙瓶,Flutter引擎可能會崩潰Window.render()。在進行null安全遷移期間嫉称,他們添加了一個提示,將Scene標記為non-nullable灵疮,然后能夠輕松地防止可能觸發(fā)null的潛在應(yīng)用崩潰织阅。

4.默認情況下使用非空

一旦啟用空安全,變量聲明的基本改變震捣,因為默認的類型是不可為空:

// In null-safe Dart, none of these can ever be null.
var i = 42; // Inferred to be an int.
String name = getFileName();
final b = Foo();

如果要創(chuàng)建一個可以包含值或null的變量荔棉,則需要在變量聲明中通過?在類型中添加后綴來使其顯式:

// aNullableInt can hold either an integer or null.
int? aNullableInt = null;

空安全性的實現(xiàn)是健壯的,具有豐富的靜態(tài)流分析功能蒿赢,使的使用可空類型的工作變得更加容易润樱。例如,在檢查了null之后羡棵,Dart將局部變量的類型從nullable提升為non-nullable

int definitelyInt(int? aNullableInt) {
  if (aNullableInt == null) {
    return 0;
  }
  // aNullableInt has now promoted to a non-null int.
  return aNullableInt; 
}

我們還添加了一個新關(guān)鍵字required壹若。當命名參數(shù)被標記為required(在Flutter小部件API中經(jīng)常發(fā)生)并且調(diào)用者忘記提供參數(shù)時,就會發(fā)生分析錯誤:

5.逐步遷移到無效安全性

因為可靠的安全性是對我們的打字系統(tǒng)的根本改變皂冰,所以如果我們堅持強制采用店展,那將是極度破壞性的。這樣秃流,你決定到時是正確的赂蕴,空安全是一項可選功能:你可以用Dart2.12,而無需被迫啟用空安全舶胀。您甚至可以依賴已經(jīng)啟用了空安全性的軟件包概说,無論您的應(yīng)用程序或軟件包是否啟用了空安全性。

為了幫助您將現(xiàn)有代碼遷移到null safety的狀態(tài)嚣伐,我們提供了遷移工具和遷移指南糖赔。該工具首先分析所有現(xiàn)有代碼。然后纤控,您可以交互地查看該工具推斷的可空性屬性挂捻。如果您不同意該工具的任何結(jié)論,則可以添加可空性提示以更改推斷船万。添加一些遷移提示可能會對遷移質(zhì)量產(chǎn)生巨大影響刻撒。

image

目前,使用dart createflutter create不啟用可靠的空安全創(chuàng)建的新程序包和應(yīng)用程序耿导。當我們看到大多數(shù)生態(tài)系統(tǒng)已經(jīng)遷移時声怔,我們希望在將來的穩(wěn)定版本中對此進行更改。您可以輕松的在新創(chuàng)建的包或應(yīng)用中使用null safety,可以使用命令dart migrate舱呻。

6.Dart生態(tài)系統(tǒng)的零安全遷移狀況

在過去的一年中醋火,我們提供了幾種聲音無效安全性的預覽版和Beta版悠汽,目的是為生態(tài)系統(tǒng)植入支持無效性安全的軟件包。這項準備工作很重要芥驳,因為我們建議按順序遷移柿冲,以確保聲音的安全性-您不應(yīng)該在軟件包或應(yīng)用程序的所有依賴項都遷移之前就對其進行遷移。
我們已經(jīng)發(fā)布了Dart兆旬,F(xiàn)lutter假抄,F(xiàn)irebase和Material團隊提供的數(shù)百個軟件包的null安全版本。而且丽猬,我們已經(jīng)從驚人的Dart和Flutter生態(tài)系統(tǒng)中獲得了巨大的支持宿饱,因此pub.dev現(xiàn)在有超過一千個支持null安全的軟件包。重要的是脚祟,最流行的軟件包已首先遷移谬以,因此,對于今天的發(fā)布而言由桌,最流行的前100個軟件包中的98%为黎,前250個頂級軟件包中的78%和前500個頂級軟件包中的57%已及時支持零安全性。我們期待在未來幾周內(nèi)在pub.dev上看到更多具有空安全性的軟件包沥寥。我們的分析表明碍舍,pub.dev上的絕大多數(shù)軟件包已被解除阻止,可以開始遷移邑雅。

7.完全可靠的安全性的好處

完全遷移后片橡,Dart的null safety就可以了。這意味著Dart 100%確保具有不可為null的類型的表達式不能為null淮野。當Dart分析您的代碼并確定某個變量不可為空時捧书,該變量始終為不可為空。Dart與Swift共享可靠的安全性骤星,但其他編程語言卻很少经瓷。
Dart的null safety的健全性還具有另一個受歡迎的含義:這意味著您的程序可以更小更快洞难。由于Dart確保不可為空的變量永遠不會為null舆吮,因此Dart可以進行優(yōu)化。例如队贱,Dart提前(AOT)編譯器可以生成更小色冀,更快的本機代碼,因為當知道變量不是null時柱嫌,它不需要添加對null的檢查锋恬。

8.Dart FFI,用于將Dart與C庫集成

Dart FFI使您能夠利用C庫中的現(xiàn)有代碼编丘,以獲得更好的可移植性与学,并與經(jīng)過高度調(diào)整的C代碼集成以執(zhí)行對性能至關(guān)重要的任務(wù)彤悔。從Dart 2.12開始,Dart FFI已脫離Beta階段索守,現(xiàn)已被認為穩(wěn)定并且可以投入生產(chǎn)晕窑。我們還添加了一些新功能,包括嵌套結(jié)構(gòu)和按值傳遞結(jié)構(gòu)卵佛。

9.通過值傳遞結(jié)構(gòu)

可以在C代碼中按引用和按值傳遞結(jié)構(gòu)幕屹。FFI以前僅支持按引用傳遞,但從Dart 2.12開始级遭,您可以按值傳遞結(jié)構(gòu)。這是兩個同時通過引用和值傳遞的C函數(shù)的小示例:

struct Link {
  double value;
  Link* next;
};
void MoveByReference(Link* link) {
  link->value = link->value + 10.0;
}
Coord MoveByValue(Link link) {
  link.value = link.value + 10.0;
  return link;
}

10.嵌套結(jié)構(gòu)

C API通常使用嵌套結(jié)構(gòu)-本身包含結(jié)構(gòu)的結(jié)構(gòu)渺尘,例如以下示例:

struct Wheel {
  int spokes;
};
struct Bike {
  struct Wheel front;
  struct Wheel rear;
  int buildYear;
};

從Dart 2.12開始挫鸽,F(xiàn)FI支持嵌套結(jié)構(gòu)。

11.API變更

為了聲明FFI穩(wěn)定并支持上述功能鸥跟,我們進行了一些較小的API更改丢郊。
現(xiàn)在禁止創(chuàng)建空結(jié)構(gòu)(打破更改#44622),并產(chǎn)生棄用警告医咨。您可以使用新的類型Opaque來表示空結(jié)構(gòu)枫匾。的dart:ffi功能sizeOfelementAt以及ref現(xiàn)在需要編譯時類型參數(shù)(重大更改#44621)拟淮。因為package:ffi已經(jīng)添加了新的便利功能干茉,所以在常見情況下,不需要分配和釋放內(nèi)存的額外樣板:

// Allocate a pointer to an Utf8 array, fill it from a Dart string,
// pass it to a C function, convert the result, and free the arg.
//
// Before API change:
final pointer = allocate<Int8>(count: 10);
free(pointer);
final arg = Utf8.toUtf8('Michael');
var result = helloWorldInC(arg);
print(Utf8.fromUtf8(result);
free(arg);
// After API change:
final pointer = calloc<Int8>(10);
calloc.free(pointer);
final arg = 'Michael'.toNativeUtf8();
var result = helloWorldInC(arg);
print(result.toDartString);
calloc.free(arg);

12.自動生成FFI綁定

對于較大的API曲面很泊,編寫與C代碼集成的Dart綁定可能非常耗時角虫。為了減輕這種負擔,我們構(gòu)建了一個綁定生成器委造,用于根據(jù)C頭文件自動創(chuàng)建FFI包裝器戳鹅。我們邀請您嘗試一下:package:ffigen

13.FFI路線圖

隨著核心FFI平臺的完成昏兆,我們將重點轉(zhuǎn)移到擴展FFI功能集枫虏,使其具有在核心平臺之上分層的功能。我們正在調(diào)查的一些功能包括:

  • 特定于ABI的數(shù)據(jù)類型爬虱,例如int隶债,longsize_t#36140
  • 內(nèi)聯(lián)結(jié)構(gòu)中的數(shù)組(#35763
  • 打包的結(jié)構(gòu)(#38158
  • 聯(lián)合類型(#38491
  • 將終結(jié)器暴露給Dart(#35770饮潦;但是請注意燃异,您已經(jīng)可以使用C的終結(jié)器

14.FFI的示例用法

我們已經(jīng)看到Dart FFI的許多創(chuàng)造性用法,以與各種基于C的API集成继蜡。這里有一些例子:

  • open_file是用于跨多個平臺打開文件的單個API回俐。它使用FFI調(diào)用Windows逛腿,macOSLinux上的本機操作系統(tǒng)API。
  • win32封裝了最常見的Win32 API仅颇,從而可以直接從Dart調(diào)用各種Windows API单默。
  • objectbox是由基于C的實現(xiàn)支持的快速數(shù)據(jù)庫。
  • tflite_flutter使用FFI包裝TensorFlow Lite API忘瓦。

15.Dart語言的下一步是什么搁廓?

聲音無效安全性是我們幾年來對Dart語言所做的最大改變。接下來耕皮,我們將考慮在我們強大的基礎(chǔ)上對語言和平臺進行更多的增量更改境蜕。快速瀏覽一下我們在語言設(shè)計渠道中正在嘗試的一些事情:

類型別名(#65):可以為非函數(shù)類型創(chuàng)建類型別名凌停。例如粱年,您可以創(chuàng)建一個typedef并將其用作變量類型:

typedef IntList = List<int>;
IntList il = [1,2,3];

三重移位運算符(#120):添加了一個新的,完全可重寫的>>>運算符罚拟,用于對整數(shù)進行無符號移位台诗。
通用元數(shù)據(jù)注釋(#1297):擴展元數(shù)據(jù)注釋以也支持包含類型參數(shù)的注釋。

靜態(tài)元編程(#1482):支持靜態(tài)元編程— Dart程序在編譯期間生成新的Dart源代碼赐俗,類似于Rust宏和Swift函數(shù)生成器拉队。該功能仍處于早期探索階段,但是我們認為它可以啟用當今依賴于代碼生成的用例阻逮。

16.Dart 2.12現(xiàn)已上市

Dutter 2.12Flutter 2.0 SDK現(xiàn)已提供具有可靠的null safety和穩(wěn)定的FFI粱快。請花點時間查看Dart和Flutter的已知的null safety問題。如果您發(fā)現(xiàn)任何其他問題叔扼,請在Dart問題跟蹤器中報告這些問題皆尔。

如果您已經(jīng)開發(fā)了發(fā)布在pub.dev上的軟件包,請立即查看遷移指南币励,并了解如何遷移以達到安全性慷蠕。遷移您的軟件包可能會幫助解除阻止其他依賴于該軟件包的軟件包和應(yīng)用程序。我們還要感謝已經(jīng)遷移的人食呻!

我們很想聽聽您在可靠安全性和FFI方面的經(jīng)驗流炕。在下面發(fā)表評論或通過推特給我們@dart_lang

原文地址:https://medium.com/dartlang/announcing-dart-2-12-499a6e689c87

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仅胞,一起剝皮案震驚了整個濱河市每辟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌干旧,老刑警劉巖渠欺,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異椎眯,居然都是意外死亡挠将,警方通過查閱死者的電腦和手機胳岂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舔稀,“玉大人乳丰,你說我怎么就攤上這事∧谥” “怎么了产园?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長夜郁。 經(jīng)常有香客問我什燕,道長,這世上最難降的妖魔是什么竞端? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任秋冰,我火速辦了婚禮,結(jié)果婚禮上婶熬,老公的妹妹穿的比我還像新娘。我一直安慰自己埃撵,他們只是感情好赵颅,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著暂刘,像睡著了一般饺谬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谣拣,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天募寨,我揣著相機與錄音,去河邊找鬼森缠。 笑死拔鹰,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的贵涵。 我是一名探鬼主播列肢,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宾茂!你這毒婦竟也來了瓷马?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤跨晴,失蹤者是張志新(化名)和其女友劉穎欧聘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體端盆,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡怀骤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年费封,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晒喷。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡孝偎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凉敲,到底是詐尸還是另有隱情衣盾,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布爷抓,位于F島的核電站势决,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蓝撇。R本人自食惡果不足惜果复,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望渤昌。 院中可真熱鬧虽抄,春花似錦、人聲如沸独柑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忌栅。三九已至车酣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間索绪,已是汗流浹背湖员。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瑞驱,地道東北人娘摔。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像唤反,于是被迫代替她去往敵國和親晰筛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容