前言
RUST:
- 不適合編程初學(xué)者學(xué)習(xí)内贮、當前不適合當團隊的語言選型對象、不優(yōu)雅
- 適合學(xué)習(xí)夜郁、適合準備什燕、適合強迫癥、適合玩
缺點
- 1 上手困難竞端,相對其他語言有較復(fù)雜的語法和理念屎即,門檻比較高
- 2 有很多獨有表達式,可讀性較差
- 3 嚴格的語法限制婶熬,如作用域剑勾、生命周期等,學(xué)習(xí)成本高
- 4 目前版本不統(tǒng)一赵颅,stable和nightly版本區(qū)別較大
- 5 不好做語言遷移虽另,生態(tài)還不完全
優(yōu)點
- 1 有毒,容易上癮
- 2 社區(qū)開發(fā)速度快饺谬,現(xiàn)在是個學(xué)習(xí)的好時候捂刺,目前,保持著每 6 周更新一次的節(jié)奏募寨。Rust 發(fā)布的工具鏈包括了
stable
族展、beta
和nightly
三種不同版本。nightly
是最激進的版本拔鹰,包含了大量(可能不穩(wěn)定)的新/高級特性仪缸。stable
版本目前可能還不支持一些高級特性。beta
介于兩者之間列肢。 - 3 從語言層面就減少各種開銷和數(shù)據(jù)競爭恰画,更加安全
- 4 性能
參考資料
官方中文網(wǎng)站
crates 庫類搜索
簡體中文文檔
語法基礎(chǔ)教程
RUST 特性分析 by austenliao
Rust中文社區(qū)
tokio文檔
Rocket文檔
必看語法
目錄
- 安裝RUST
- hello world
- 使用第三方庫
- 測試socket stream
- 搭建http服務(wù)
- 數(shù)據(jù)庫操作
- 與golang的壓測對比
- 接入基于consul的grpc微服務(wù)集群
一 安裝RUST
- 下載
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- 激活環(huán)境
source $HOME/.cargo/env
- 檢查是否安裝成功
$ cargo --version
cargo 1.38.0 (23ef9a4ef 2019-08-20)
cargo 命令介紹
cargo build
可以構(gòu)建項目cargo run
可以運行項目cargo test
可以測試項目cargo doc
可以為項目構(gòu)建文檔cargo publish
可以將庫發(fā)布到 crates.io宾茂。
二 helloworld
$ cargo new myhello
- 生成的文件結(jié)構(gòu)
$ tree
.
├── Cargo.toml
└── src
└── main.rs
//main.rs
fn main() {
println!("Hello, world!");
}
//Cargo.toml
[package]
name = "myhello"
version = "0.1.0"
authors = ["root"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
- 運行
$ cargo run
Compiling myhello v0.1.0 (/mnt/hgfs/winwork/rust/myhello)
error: linker `cc` not found
|
= note: No such file or directory (os error 2)
error: aborting due to previous error
error: Could not compile `myhello`.
To learn more, run the command again with --verbose.
- 失敗了,新裝的虛擬機環(huán)境不夠完全,注意最好換成aliyun的源再繼續(xù)
$ sudo apt install build-essential
- 再次運行拴还,成功
$ cargo run
Compiling myhello v0.1.0 (/mnt/hgfs/winwork/rust/myhello)
Finished dev [unoptimized + debuginfo] target(s) in 0.54s
Running `target/debug/myhello`
Hello, world!
三 簡單使用第三方庫
- 參照官方示例跨晴,使用
ferris-says
庫,用來畫個say hi的小人
// main.rs
use ferris_says::say; // from the previous step
use std::io::{stdout, BufWriter};
fn main() {
let stdout = stdout();
let out = b"Hello fellow Rustaceans!";
let width = 24;
let mut writer = BufWriter::new(stdout.lock());
say(out, width, &mut writer).unwrap();
}
# Cargo.toml中加入
[dependencies]
ferris-says = "0.1"
# 編譯 后可在target目錄中找到可執(zhí)行文件
$ cargo build
# 或者直接運行
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 1.79s
Running `target/debug/myhello`
----------------------------
| Hello fellow Rustaceans! |
----------------------------
\
\
_~^~^~_
\) / o o \ (/
'_ - _'
/ '-----' \
四 測試socket stream
- 當我們需要寫功能的時候片林,可以從crates.io 可以搜索需要用到的庫
image.png
注意:
Documentation 會指向官方文檔網(wǎng)站
Repository 會指向github
-
tokio
異步編程框架是使用人數(shù)較多的框架端盆,不僅是引用量和下載量都是最高的,而且是官方支持的項目。但是rust生態(tài)目前還不是很完善费封,因此很多項目都不穩(wěn)定焕妙,從github中可以看到
NOTE: Tokio's
master
is currently undergoing heavy development. This branch and the alpha releases will see API breaking changes and there are currently significant performance regressions that still need to be fixed before the final release. Use thev0.1.x
branch for stable releases.
- 根據(jù)官方的start文檔 修改Cargo.toml 和 main.rs
[dependencies]
tokio = "0.1"
extern crate tokio;
use tokio::io;
use tokio::net::TcpStream;
use tokio::prelude::*;
fn main() {
// Parse the address of whatever server we're talking to
let addr = "127.0.0.1:6142".parse().unwrap();
let client = TcpStream::connect(&addr).and_then(|stream| {
println!("created stream");
// Process stream here.
io::write_all(stream, "hello world\n").then(|result| {
println!("wrote to stream; success={:?}", result.is_ok());
Ok(())
})
}).map_err(|err| {
// All tasks must have an `Error` type of `()`. This forces error
// handling and helps avoid silencing failures.
// In our example, we are only going to log the error to STDOUT.
println!("connection error = {:?}", err);
});
println!("About to create the stream and write to it...");
tokio::run(client);
println!("Stream has been created and written to.");
}
- 先用
nc
啟動6142端口的監(jiān)聽進程, 然后運行cargo run
可以看到以下狀態(tài)
$ nc -l -p 6142
hello world
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 3.90s
Running `target/debug/myhello`
About to create the stream and write to it...
created stream
wrote to stream; success=true
Stream has been created and written to.
五 搭建一個http restful服務(wù)
- 這里我們直接使用框架rocket弓摘,類似于
node
中的express
,go
里面的gin
等。 - 推薦先讀rocket api文檔
- 注意 需要使用nightly版本
$ rustup default nightly
$ rustc --version
rustc 1.40.0-nightly (aa69777ea 2019-10-29)
新建項目
$ cargo new management
- main.rs代碼:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}
- 運行
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 2m 28s │root@cowkeysu1:/mnt/hgfs/winwork/rust/Rocket# cd ..
Running `target/debug/management` │root@cowkeysu1:/mnt/hgfs/winwork/rust# cd ..
Configured for development. │root@cowkeysu1:/mnt/hgfs/winwork# mv^C
=> address: localhost │root@cowkeysu1:/mnt/hgfs/winwork# ls
=> port: 8000 │faf go go1.12.12.linux-amd64.tar.gz ocr rust ziliao
=> log: normal │root@cowkeysu1:/mnt/hgfs/winwork# cd rust/
=> workers: 2 │root@cowkeysu1:/mnt/hgfs/winwork/rust# s
=> secret key: generated │cd s: command not found
=> limits: forms = 32KiB │root@cowkeysu1:/mnt/hgfs/winwork/rust# ls
=> keep-alive: 5s │hello myrust Rocket rustover
=> tls: disabled │root@cowkeysu1:/mnt/hgfs/winwork/rust# cd rustover/
Mounting /: │root@cowkeysu1:/mnt/hgfs/winwork/rust/rustover# ls
=> GET / (index) │management myhello
Rocket has launched from http://localhost:8000
- 調(diào)用測試
$ curl http://127.0.0.1:8000
hello,world!
- 加入GET、POST的方法
下面的代碼只有不到50行势决,不過很容易出錯蓝撇,主要難點還是在rust語法以及Rocket
框架的處理上 - main.rs 代碼:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate serde;
use serde::{Serialize, Deserialize};
use rocket::response::status;
use rocket::response::{self,Responder,Response};
use std::io::Cursor;
use rocket::http::{Status, ContentType};
use rocket::request::Request;
use rocket_contrib::json::Json;
use serde_json::json;
#[derive(Serialize)]
struct User {
id : usize,
name : String,
age : i32,
updated : i64,
}
impl<'r> Responder<'r> for User {
fn respond_to(self, _: &Request) -> response::Result<'r> {
Response::build()
.sized_body(Cursor::new(json!(self).to_string()))
.header(ContentType::new("application", "json"))
.ok()
}
}
#[post("/user/<id>")]
fn addUser(id: usize) -> status::Accepted<String> {
status::Accepted(Some(format!("id: '{}'", id)))
}
//fn getUser(id: usize) -> Json<User> {
#[get("/user/<id>")]
fn getUser(id: usize) -> User {
User{
id:id,
name:"cowkeys".to_string(),
age:27,
updated:0
}
}
fn main() {
rocket::ignite().mount("/", routes![addUser,getUser]).launch();
}
- 運行
$ Cargo run
Configured for development.
=> address: 0.0.0.0
=> port: 8000
=> log: normal
=> workers: 2
=> secret key: generated
=> limits: forms = 32KiB
=> keep-alive: 5s
=> tls: disabled
Mounting /:
=> POST /user/<id> (addUser)
=> GET /user/<id> (getUser)
Rocket has launched from http://0.0.0.0:8000
- 測試調(diào)用
// GET
curl http://localhost:8000/user/1
id: '1'
// POST
curl -X POST http://localhost:8000/user/1
{"age":19,"id":1,"name":"cowkeys","updated":0}
- 控制臺會出現(xiàn):
GET /user/1:
=> Matched: GET /user/<id> (getUser)
=> Outcome: Success
=> Response succeeded.
GET /user/1:
=> Matched: GET /user/<id> (getUser)
=> Outcome: Success
=> Response succeeded.
- 到此渤昌,http服務(wù)完成。
總結(jié)
本文介紹了RUST的基礎(chǔ)入門独柑,如何開始使用rust。下篇會從接入數(shù)據(jù)庫開始忌栅,一直到使用grpc接入consul服務(wù)發(fā)現(xiàn)。