日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Golang和Rust語(yǔ)言常見(jiàn)功能/庫(kù)

時(shí)下最流行、最具發(fā)展前途的的兩門語(yǔ)言是Golang和Rust。Golang語(yǔ)言簡(jiǎn)潔、高效、并發(fā)、并且有個(gè)強(qiáng)大的囊括了常見(jiàn)功能標(biāo)準(zhǔn)庫(kù)。與之相對(duì)比,Rust語(yǔ)言則主要是安全、高性能。雖然Rust沒(méi)有g(shù)olang那種"內(nèi)置電池(Batteries included)"的標(biāo)準(zhǔn)庫(kù),但是Rust的第三方庫(kù)(crate,板條箱)極大補(bǔ)充了Rust精煉基本庫(kù)的功能。本文我們就介紹一下Golang和Rust常用的庫(kù)功能。

參數(shù)處理

Golang標(biāo)準(zhǔn)庫(kù)中提供了功能。flag庫(kù)是非?;A(chǔ)的功能,在實(shí)踐上也非常有用,在做命令行交互程序時(shí)候必不可少。

 
 
 
  1. package main 
  2. import "flag" 
  3. var ( 
  4. program = flag.String("p", "", "h program to compile/run") 
  5. outFname = flag.String("o", "", "if specified, write the webassembly binary created by -p here") 
  6. watFname = flag.String("o-wat", "", "if specified, write the uncompiled webassembly created by -p here") 
  7. port = flag.String("port", "", "HTTP port to listen on") 
  8. writeTao = flag.Bool("koan", false, "if true, print the h koan and then exit") 
  9. writeVersion = flag.Bool("v", false, "if true, print the version of h and then exit") 

上述代碼會(huì)生成一些程序包全局變量,其中將包含命令行參數(shù)的值。

在Rust中,常用的命令行解析包是structopt。但是,其工作方式與Golang flag程序包有所不同。structopt會(huì)選項(xiàng)加載到結(jié)構(gòu)中,而非全局可變變量。主要因?yàn)镽ust語(yǔ)言編程實(shí)踐中,基本上都會(huì)避免全局可變的變量。在大多數(shù)情況下,帶有包的全局變量flag是可以的,但前提是必須在程序真正開(kāi)始執(zhí)行其需要做的工作之前將它們寫入到程序中。

一個(gè)簡(jiǎn)單示例源自于pahi庫(kù)源碼:

 
 
 
  1. #[derive(Debug, StructOpt)] 
  2. #[structopt( 
  3. name = "pa'i", 
  4. about = "A WebAssembly runtime in Rust meeting the Olin ABI." 
  5. )] 
  6. struct Opt { 
  7. #[structopt(short, long, default_value = "cranelift")] 
  8. backend: String, 
  9. #[structopt(short, long)] 
  10. function_log: bool, 
  11. #[structopt(short, long)] 
  12. no_cache: bool, 
  13. #[structopt()] 
  14. fname: String, 
  15. #[structopt(short, long, default_value = "_start")] 
  16. entrypoint: String, 
  17. #[structopt()] 
  18. args: Vec

Rust編譯器會(huì)生成所需的參數(shù)解析代碼,然后可以使用:

 
 
 
  1. fn main() { 
  2. let opt = Opt::from_args(); 
  3. debug!("args: {:?}", opt.args); 
  4. if opt.backend != "cranelift" { 
  5.         return Err(format!( 
  6.             "wanted backend to be cranelift, got: {}", 
  7.             opt.backend 
  8.         )); 

錯(cuò)誤處理

Golang的標(biāo)準(zhǔn)庫(kù)具有error接口,可以創(chuàng)建一個(gè)描述類型的函數(shù),函數(shù)描述為什么功能無(wú)法按預(yù)期執(zhí)行,Golang程序必須先做好錯(cuò)誤處理。比如:

 
 
 
  1. func Write(w io.Writer, buf []byte) error { 
  2. _, err := w.Write(buf) 
  3. if err != nil { 
  4. log.Println("unable to write:", err) 
  5. return err 
  6. return nil 

Rust也具有Error 特性,它使還可以創(chuàng)建一個(gè)描述函數(shù)為何無(wú)法實(shí)現(xiàn)其預(yù)期功能的類型。這兒我們介紹更加易用的thiserror板條箱構(gòu)建自定義錯(cuò)誤類型:

 
 
 
  1. [dependencies] 
  2. thiserror = "1" 

然后,在程序中使用:

 
 
 
  1. use std::fmt; 
  2. use thiserror::Error; 
  3. #[derive(Debug, Error)] 
  4. struct Divide0?; 
  5. impl fmt::Display for Divide0? { 
  6. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 
  7. write!(f, "不能被零整除!") 

日志記錄

Go標(biāo)準(zhǔn)庫(kù)中也自帶了log庫(kù)。該庫(kù)是一個(gè)非常有爭(zhēng)議的記錄器,它的日志記錄缺乏日志記錄級(jí)別和上下文感知值之類的功能。

 
 
 
  1. package main 
  2. import ( 
  3. "log" 
  4. func init() { 
  5. log.SetPrefix("TRACE: ") 
  6. log.SetFlags(log.Ldate | log.Lmicroseconds | log.Llongfile) 
 
 
 
  1. func main() { 
  2. log.Println("message") 
  3. log.Fatalln("fatal message") 
  4. log.Panicln("panic message") 
 
 
 
  1. ------------------------------- 
  2. TRACE: 2020/09/09 14:24:32.868375 TestLog.go:15: message 
  3. TRACE: 2020/09/09 14:24:32.962329 TestLog.go:18: fatal message 
  4. Process finished with exit code 1 

在Rust中,有一個(gè)板條箱,這是一個(gè)非常簡(jiǎn)單的包,它使用error!,warn!,info!,debug!和trace!宏分別關(guān)聯(lián)到最高和最低日志打印水平。同樣要使用log板條箱,先要增加的項(xiàng)目中,即添加到Cargo.toml的依賴部分。

 
 
 
  1. [dependencies] 
  2. log = "0.4" 

然后,就可以使用了:

 
 
 
  1. use log::{error, warn, info, debug, trace}; 
  2. fn main() { 
  3. trace!("starting main"); 
  4. debug!("debug message"); 
  5. info!("this is some information"); 
  6. warn!("oh no something bad is about to happen"); 
  7. error!("oh no it's an error"); 

注意,默認(rèn)該庫(kù)日志記錄是不會(huì)記錄到本地文件中的。要記錄日志還需要其他庫(kù)。

pretty_env_logger是和log買一送一,最常搭配使用的板條箱。同樣,先添加項(xiàng)目依賴:

 
 
 
  1. [dependencies] 
  2. log = "0.4" 
  3. pretty_env_logger = "0.4" 

然后,在代碼中使用:

 
 
 
  1. use log::{error, warn, info, debug, trace}; 
  2. fn main() { 
  3. pretty_env_logger::init(); 
  4. trace!("這是一個(gè)示例程序。"); 
  5. debug!("調(diào)試信息xxx。"); 
  6. info!("程序正在運(yùn)行中。"); 
  7. warn!("[WARN]程序有些參數(shù)配置有問(wèn)題。"); 
  8. error!("[ERROR]程序發(fā)生嚴(yán)重錯(cuò)誤!"); 

然后在啟動(dòng)時(shí)候增加,日志級(jí)別參數(shù)RUST_LOG=trace 運(yùn)行:

 
 
 
  1. env RUST_LOG=trace cargo run 
  2.   
  3. Compiling errex v0.1.0 (/home/lz/test/rust/commoncrate/errex) 
  4.     Finished dev [unoptimized + debuginfo] target(s) in 1.32s 
  5.      Running `target/debug/errex` 
  6.  TRACE errex > 這是一個(gè)示例程序。 
  7.  DEBUG errex > 調(diào)試信息xxx。 
  8.  INFO  errex > 程序正在運(yùn)行中。 
  9.  WARN  errex > [WARN]程序有些參數(shù)配置有問(wèn)題。 
  10.  ERROR errex > [ERROR]程序發(fā)生嚴(yán)重錯(cuò)誤! 

序列化/反序列化

Golang在標(biāo)準(zhǔn)庫(kù)內(nèi)置了 包用來(lái)實(shí)現(xiàn)JSON編碼/解碼功能。我們可以定義可以輕松讀取和寫入JSON的類型。下面一個(gè)例子:

 
 
 
  1. "id": 3137, 
  2. "author": { 
  3. "id": 420, 
  4. "name": "Chongchong" 
  5. }, 
  6. "body": "Hello,This is Chongchong web!", 
  7. "in_reply_to": 3135 

在Golang中,可以生成如下的結(jié)構(gòu)體:

 
 
 
  1. type Author struct { 
  2. ID int `json:"id"` 
  3. Name string `json:"name"` 
 
 
 
  1. type Comment struct { 
  2. ID int `json:"id"` 
  3. Author Author `json:"author"` 
  4. Body string `json:"body"` 
  5. InReplyTo int `json:"in_reply_to"` 

Rust沒(méi)有開(kāi)箱即用的功能,需要使用第三方板條箱,最常用的一個(gè)庫(kù)是serde,可以跨JSON和能想到的所有其他序列化方法使用。

 
 
 
  1. [dependencies] 
  2. serde = { version = "1", features = ["derive"] } 
  3. serde_json = "1" 

注意,上面serde的依賴配置,和其他包有差異。

Golang的JSON包通過(guò)使用struct標(biāo)簽作為元數(shù)據(jù)來(lái)工作,但是Rust沒(méi)有,需要改用Rust的衍生功能。

因此,要將serde用于的注釋類型:

 
 
 
  1. use serde::{Deserialize, Serialize}; 
  2. #[derive(Clone, Debug, Deserialize, Serialize)] 
  3. pub struct Author { 
  4. pub id: i32, 
  5. pub name: String, 
  6. #[derive(Clone, Debug, Deserialize, Serialize)] 
  7. pub struct Comment { 
  8. pub id: i32, 
  9. pub author: Author, 
  10. pub body: String, 
  11. pub in_reply_to: i32, 

然后,使用以下代碼解析Json:

 
 
 
  1. fn main() { 
  2. let data = r#" 
  3. "id": 3137, 
  4. "author": { 
  5. "id": 420, 
  6. "name": "Chongchong" 
  7. }, 
  8. "body": "Hello,This is Chongchong web!", 
  9. "in_reply_to": 3135 
  10. "#; 
  11. let c: Comment = serde_json::from_str(data).expect("json to parse"); 
  12. println!("comment: {:#?}", c); 

cargo run

 
 
 
  1. ... 
  2. Finished dev [unoptimized + debuginfo] target(s) in 0.04s 
  3.      Running `target/debug/serdeex` 
  4. comment: Comment { 
  5.     id: 3137, 
  6.     author: Author { 
  7.         id: 420, 
  8.         name: "Chongchong", 
  9.     }, 
  10.     body: "Hello,This is Chongchong web!", 
  11.     in_reply_to: 3135, 

Web開(kāi)發(fā)

在Web開(kāi)發(fā)中HTTP包必不可少的。Golang中可使用net/http充當(dāng)生產(chǎn)級(jí)HTTP客戶端和服務(wù)器。

 
 
 
  1. import ( 
  2. "net/http" 
  3. "fmt" 
  4. "log" 
  5.  
  6. func sayhelloGolang(w http.ResponseWriter, r *http.Request) { 
  7. r.ParseForm() 
  8. fmt.Println("path", r.URL.Path) 
  9. w.Write([]byte("Hello Chongchong!")) 
  10.  
  11. func main() { 
  12. http.HandleFunc("/",hello) 
  13. err := http.ListenAndServe(":8080", nil) 
  14. if err != nil { 
  15. log.Fatal("ListenAndServe: ", err) 

它可以讓我們非常輕松地進(jìn)行Web開(kāi)發(fā)。Rust標(biāo)準(zhǔn)庫(kù)沒(méi)有開(kāi)箱即用的HTTP功能,但是Web的框架也非常豐富。

客戶端

對(duì)于HTTP客戶端,可以使用。它還可以與serde無(wú)縫集成,以允許從HTTP解析JSON:

 
 
 
  1. [dependencies] 
  2. reqwest = { version = "0.10", features = ["json"] } 
  3. tokio = { version = "0.2", features = ["full"] } 

tokio默認(rèn)情況下Rust不附帶異步運(yùn)行時(shí),tokio大約等同于Golang運(yùn)行時(shí)幫助處理的大多數(shù)重要事項(xiàng)。簡(jiǎn)單實(shí)例如下:

運(yùn)行此命令:

 
 
 
  1. cargo run  
  2. ... 
  3. Finished dev [unoptimized + debuginfo] target(s) in 3.31s 
  4.      Running `target/debug/webcer` 
  5. Status: 200 OK 
  6. Body: 
  7.  
  8.  
  9.    
  10.      
  11.  
  12. hyper.rs | hyper 
  13.  

結(jié)合其他功能,reqwest可以做作為一個(gè)功能強(qiáng)大的HTTP客戶端。

服務(wù)器端

至于HTTP服務(wù)器,可以使用warp板條箱。warp是一個(gè)建立在Rust的類型系統(tǒng)之上的HTTP服務(wù)器框架。

 
 
 
  1. [dependencies] 
  2. tokio = { version = "0.2", features = ["macros"] } 
  3. warp = "0.2" 

讓我們寫個(gè)簡(jiǎn)單的"Hello,Chongchong"示例:

 
 
 
  1. use warp::Filter; 
  2. #[tokio::main] 
  3. async fn main() { 
  4. // GET /hello/Chongchong=> 200 OK with body "Hello, Chongchong!" 
  5. let hello = warp::path!("hello" / String) 
  6. .map(|name| format!("Hello, {}!", name)); 
  7. warp::serve(hello) 
  8. .run(([127, 0, 0, 1], 3030)) 
  9. .await; 

然后通過(guò)127.0.0.1:3030/hello/Chongchong,就可以提示Hello, Chongchong!。

對(duì) warp應(yīng)用可以使用其or模式構(gòu)建多條Web路由:

 
 
 
  1. let hello = warp::path!("hello" / String) 
  2. .map(|name| format!("Hello, {}!", name)); 
  3. let health = warp::path!(".within" / "health") 
  4. .map(|| "OK"); 
  5. let routes = hello.or(health); 

還可通過(guò)過(guò)濾器將其他數(shù)據(jù)類型注入到處理程序中:

 
 
 
  1. let fact = { 
  2. let facts = pfacts::make(); 
  3. warp::any().map(move || facts.clone()) 
  4. }; 
  5. let fact_handler = warp::get() 
  6. .and(warp::path("fact")) 
  7. .and(fact.clone()) 
  8. .and_then(give_fact); 

warp是功能強(qiáng)大的HTTP服務(wù)器,可以跨生產(chǎn)級(jí)Web應(yīng)用程序所需的所有內(nèi)容工作。

模版

Web開(kāi)發(fā)中要常用模版來(lái)特定化頁(yè)面的輸出。Golang的標(biāo)準(zhǔn)庫(kù)還包括HTML和純文本模板包html/template和text/template。在Rust中有很多用于HTML模板化的解決方案,比如ructe板條箱。ructe使用Cargo的build.rs功能在編譯時(shí)為其模板生成Rust代碼。這樣就可以將HTML模板編譯成結(jié)果應(yīng)用程序二進(jìn)制文件,從而以驚人的速度呈現(xiàn)它們。

添加Cargo.toml:

 
 
 
  1. [build-dependencies] 
  2. ructe = { version = "0.12", features = ["warp02"] } 
  3. 還依賴mime板條箱: 
 
 
 
  1. [dependencies] 
  2. mime = "0.3.0" 

完成此操作后,templates在當(dāng)前工作目錄中創(chuàng)建一個(gè)新文件夾。創(chuàng)建一個(gè)名為的文件hello.rs.html,并將以下內(nèi)容放入其中:

 
 
 
  1. @(title: String, message: String) 
  2.  
  3.  
  4. @title 
  5.  
  6.  
  7. @title

     
  8. @message

     
  9.  
  10.  

然后使用模板templates.rs:

 
 
 
  1. use warp::{http::Response, Filter, Rejection, Reply}; 
  2. async fn hello_html(message: String) -> Result { 
  3. Response::builder() 
  4. .html(|o| templates::index_html(o, "Hello".to_string(), message).unwrap().clone())) 

在src/main.rs底部,通過(guò)以下語(yǔ)句引入模版定義:

 
 
 
  1. include!(concat!(env!("OUT_DIR"), "/templates.rs")); 

在main()函數(shù)中調(diào)用:

 
 
 
  1. let hello_html_rt = warp::path!("hello" / "html" / String) 
  2. .and_then(hello_html); 
  3. let routes = hello_html_rt.or(health).or(hello); 

總結(jié)

本文我們介紹了Golang和Rust中常用的功能包括命令行參數(shù)解析、錯(cuò)誤處理、日志、Json處理和Web庫(kù),我們可以發(fā)現(xiàn)基本上這些功能都在Golang標(biāo)準(zhǔn)庫(kù)中都提供了,而Rust則要引入額外的板條箱,但是借助強(qiáng)大的Cargo包管理工具,其使用也非常便捷。


當(dāng)前題目:Golang和Rust語(yǔ)言常見(jiàn)功能/庫(kù)
URL標(biāo)題:http://www.5511xx.com/article/cdgedei.html