學 Rust 要有大局觀 -五- 屬性的功能
什麼是 attribute?
attribute 是 rust 編譯器留給程序員的交互接口,一段代碼可以編譯產出爲二進制機器碼的過程通常來說,用戶的代碼是編譯器的輸入,當編譯器認爲代碼有問題,而程序員認爲沒問題的時候,必須允許程序員和編譯器有交互,允許程序員指導個別代碼的處理方式。
下面列舉幾個比較有代表性的場景:
讓編譯器閉嘴
rustc 要求結構體的命名需爲駱駝體,否則就會給出警告,假如程序員‘故意’要給出一個結構體,但是用了 python 的下劃線命名,爲了讓編譯器忽略對命名格式的‘異議’,可以通過
#[allow(non_camlel_case_types)]
這個標記,把它放在結構體聲明之前,編譯器就可以按照程序員的意願主動放過。而不是輸出一堆警告。
讓編譯器臨場應變
所謂的臨場應變經典場景主要是硬件和操作系統環境區別,比如當前這個程序員的操作系統是windows
, CPU 架構是x86_64
又或者是arm64
, 代碼編譯的時候有些別人的代碼確實不可能編譯通過,程序員需要主動處理條件編譯規則,指導編譯器不同架構下同一個代碼應該編譯哪一個具體實現。對應的 attribute 類似#[cfg(windows)]
的標記說明具體信息。
讓編譯器改變默認行爲
rust 瞭解之後你會知道有很多特有的術語,比如‘氧化’表示用 rust 去重寫一些現有的庫,或者用 rust 去實現一個特定的功能,但是畢竟很多東西編譯之後會有一些歷史命名習慣或者接口規則,不能按照 rust 本身的約定輸出,我們可以通過
#![crate_type = "cdylib"]
#![create_name=''crypto3]
這樣我們得到的名字是libcrypto3.so
,我們還特意多加了一個3
在o
後面,表示這個庫是我們自己用 rust 氧化之後的版本; 否則我們得到的是一個原版命名的libcrate.rlib
這樣的 rust 二進制庫名字.
讓編譯器區別對待一些函數和代碼
單測就是這樣一個典型場景,相比於其他語言用文件名後綴,前綴,或者是引入某些包單獨編碼而言,rust 支持的更爲簡單直接,只要有 #[test]
修飾的函數都會標記爲測試函數,會在cargo test
命令下被拉出來單獨執行。
讓編譯自動添加一些行爲
這個用法就非常多樣了,典型場景是用#[derive(Debug)]
類似的標記好,以便編譯器自動給我們的類型添加特性.
#[derive(Debug)]
struct Point {
x:f32,
y:f32,
}
編譯器現在會給 Point 類自動添加一個fmt
函數,這個函數功能類似 java 的toString
, 或者 python 的__repr__
等,注意:derive 的意義爲派生,但這裏並沒有一個默認的父類實現
, 代碼都是編譯器根據當前的類程成員變量自動添加並編譯的。
derive
和trait
搭配使用共同左右,想要明白其中細節可以閱讀本系列上關於trait
的單獨篇章.
結語
看了一些快速簡單的例子,你應該知道 attribute 這個概念是什麼內涵了,知道了內涵也就明白了概念,遇到的時候就不會有疑惑了。下一篇我們講一下 rust 惱人的宏,用不用不重要,重要的時候通過了解 rust,大家一起思考一下手頭使用的語言到底哪裏不好,爲什麼有新的設計。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/Snof5jzcw9F7weHZwS5lYw