marion 5 years ago
commit
2adbce545f
13 changed files with 619 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 2 0
      .idea/.gitignore
  3. 14 0
      .idea/hello-rust.iml
  4. 9 0
      .idea/misc.xml
  5. 8 0
      .idea/modules.xml
  6. 6 0
      .idea/vcs.xml
  7. 298 0
      Cargo.lock
  8. 12 0
      Cargo.toml
  9. 57 0
      README.md
  10. 13 0
      src/keygen/mod.rs
  11. 84 0
      src/keygen/snowflake_keygen.rs
  12. 92 0
      src/main.rs
  13. 23 0
      src/test/mod.rs

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+/target

+ 2 - 0
.idea/.gitignore

@@ -0,0 +1,2 @@
+# Default ignored files
+/workspace.xml

+ 14 - 0
.idea/hello-rust.iml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="CPP_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/examples" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/benches" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 9 - 0
.idea/misc.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+  <component name="elmot.OpenOcdPlugin">
+    <option name="openOcdHome" value="/usr/local" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/hello-rust.iml" filepath="$PROJECT_DIR$/.idea/hello-rust.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 298 - 0
Cargo.lock

@@ -0,0 +1,298 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
+
+[[package]]
+name = "backtrace"
+version = "0.3.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8"
+dependencies = [
+ "backtrace-sys",
+ "cfg-if",
+ "libc",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca797db0057bae1a7aa2eef3283a874695455cecf08a43bfb8507ee0ebc1ed69"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "cc"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "chrono"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
+dependencies = [
+ "num-integer",
+ "num-traits",
+ "time",
+]
+
+[[package]]
+name = "clap"
+version = "2.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "error-chain"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
+dependencies = [
+ "backtrace",
+]
+
+[[package]]
+name = "ferris-says"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07a21339b4ddc37834c200a769f0fa58919bfda64950abcc1b6438e8b50b32fd"
+dependencies = [
+ "clap",
+ "error-chain",
+ "smallvec",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hello-rust"
+version = "0.1.0"
+dependencies = [
+ "chrono",
+ "ferris-says",
+ "rand",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
+
+[[package]]
+name = "num-integer"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom",
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
+
+[[package]]
+name = "smallvec"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f90c5e5fe535e48807ab94fc611d323935f39d4660c52b26b96446a7b33aef10"
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "time"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
+dependencies = [
+ "libc",
+ "redox_syscall",
+ "winapi",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
+
+[[package]]
+name = "vec_map"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

+ 12 - 0
Cargo.toml

@@ -0,0 +1,12 @@
+[package]
+name = "hello-rust"
+version = "0.1.0"
+authors = ["marion <marion@aionnect.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+ferris-says = "0.1.1"
+rand = "0.7.3"
+chrono = "0.4.11"

+ 57 - 0
README.md

@@ -0,0 +1,57 @@
+## Rust测试项目
+
+### 基础使用
+
+项目依赖在 Cargo.toml
+
+各种轮子库 [crates.io](https://crates.io)
+
+各种轮子库文档 [docs.rs](https://docs.rs/)
+
+**创建项目**
+
+> cargo new <项目名>
+
+加 --lib 参数创建库项目,加 --vcs none 不初始化本地git仓库
+
+默认是 --bin 和初始化 .git
+
+**下载依赖和构建项目**
+
+> cargo build
+
+加 --release 参数开启优化,并将编译结果输出到 target/release 目录
+
+默认是 --debug 和输出到 target/debug 目录
+
+**运行**
+
+如果未构建则先构建
+
+> cargo run
+
+**测试**
+
+> cargo test
+
+**为项目构建文档**
+
+> cargo doc
+
+**将库发布到crates.io**
+
+> cargo publish
+
+更多cargo工具链说明参考 [Cargo 中文文档](https://cargo.budshome.com/index.html)
+
+### 加国内镜像
+
+> vim ~/.cargo/config
+
+```
+[source.crates-io]
+registry = "https://github.com/rust-lang/crates.io-index"
+replace-with = 'ustc'
+[source.ustc]
+registry = "git://mirrors.ustc.edu.cn/crates.io-index"
+```

+ 13 - 0
src/keygen/mod.rs

@@ -0,0 +1,13 @@
+mod snowflake_keygen;
+
+// 也可以 pub use XXX 直接导出更内层的对象或方法
+use self::snowflake_keygen::SnowflakeKeygen;
+
+pub fn next_id() -> u64 {
+    let keygen = SnowflakeKeygen::new();
+    keygen.next_id() // 锁不住!!!
+}
+
+trait IProgramKeygen {
+    fn next_id(&self) -> u64;
+}

+ 84 - 0
src/keygen/snowflake_keygen.rs

@@ -0,0 +1,84 @@
+use std::{thread, time};
+use std::sync::RwLock;
+use chrono::prelude::*;
+use crate::keygen::IProgramKeygen;
+
+// 时间单位,一纳秒的多少倍,1e6 = 一毫秒,1e7 = 百分之一秒,1e8 = 十分之一秒
+const SNOWFLAKE_TIME_UNIT: i64 = (1e7 as i64);
+// 序列号的个数最多256个(0-255),即每单位时间并发数,如时间单位是1e7,则单实例qps = 25600
+const BIT_LEN_SEQUENCE: u16 = 8;
+// 数据中心个数最多8个(0-7),即同一个环境(生产、预发布、测试等)的数据中心(假设一个机房相同数据域的应用服务器集群只有一个,则数据中心数等于机房数)最多有8个
+const BIT_LEN_DATA_CENTER_ID: u16 = 3;
+// 同一个数据中心下最多65536个应用实例(0-65535),默认是根据实例ip后两段算实例id(k8s环境动态创建Pod,也建议用此方式),所以需要预留255 * 255这么多
+const BIT_LEN_MACHINE_ID: u16 = 16;
+// 时间戳之差最大 = 2的36次方 * 时间单位 / 1e9 秒,目前的设计最多可以用21.79年就需要更新开始时间(随之还需要归档旧数据和更新次新数据id)
+const BIT_LEN_TIME: i64 = 1 << 36;
+// 总共63位,不超过bit64
+
+pub struct SnowflakeKeygen {
+    start_time: i64,
+    elapsed_time: RwLock<i64>,
+    sequence: RwLock<u16>,
+    data_center_id: u16,
+    machine_id: u16,
+}
+
+fn to_snowflake_time(t: DateTime<Utc>) -> i64 {
+    t.timestamp_nanos() / SNOWFLAKE_TIME_UNIT
+}
+
+fn get_current_elapsed_time(start_time: i64) -> i64 {
+    to_snowflake_time(Utc::now()) - start_time
+}
+
+fn get_sleep_time(overtime: i64) -> time::Duration {
+    time::Duration::from_nanos(overtime as u64) * 10000000 -
+        time::Duration::from_nanos((Utc::now().timestamp_nanos() % SNOWFLAKE_TIME_UNIT) as u64)
+}
+
+impl IProgramKeygen for SnowflakeKeygen {
+    fn next_id(&self) -> u64 {
+        const MASK_SEQUENCE: u16 = 1 << BIT_LEN_SEQUENCE - 1;
+
+        let mut elapsed_time = self.elapsed_time.write().unwrap();
+        let mut sequence = self.sequence.write().unwrap();
+
+        let current = get_current_elapsed_time(self.start_time);
+        if *elapsed_time < current {
+            *elapsed_time = current;
+            *sequence = 0;
+        } else { // self.elapsed_time.get() >= current
+            *sequence = (*sequence + 1) & MASK_SEQUENCE;
+            if *sequence == 0 {
+                *elapsed_time += 1;
+                let overtime = *elapsed_time - current;
+                thread::sleep(get_sleep_time(overtime));
+            }
+        }
+
+        self.to_id(*elapsed_time, *sequence)
+    }
+}
+
+impl SnowflakeKeygen {
+    pub fn new() -> SnowflakeKeygen {
+        SnowflakeKeygen {
+            start_time: to_snowflake_time(Utc.ymd(2019, 7, 1).and_hms_nano(0, 0, 0, 0_000_000)),
+            elapsed_time: RwLock::new(0),
+            sequence: RwLock::new(1 << BIT_LEN_SEQUENCE - 1),
+            data_center_id: 0,
+            machine_id: 0,
+        }
+    }
+
+    fn to_id(&self, elapsed_time: i64, sequence: u16) -> u64 {
+        if elapsed_time >= BIT_LEN_TIME {
+            return 0;
+        }
+
+        (elapsed_time as u64) << ((BIT_LEN_SEQUENCE + BIT_LEN_DATA_CENTER_ID + BIT_LEN_MACHINE_ID) as u64) |
+            (sequence as u64) << ((BIT_LEN_DATA_CENTER_ID + BIT_LEN_MACHINE_ID) as u64) |
+            (self.data_center_id as u64) << (BIT_LEN_MACHINE_ID as u64) |
+            (self.machine_id as u64)
+    }
+}

+ 92 - 0
src/main.rs

@@ -0,0 +1,92 @@
+// 应用的入口文件,在项目根目录,统一命名为main.rs
+// 库的入口文件统一命名为lib.rs
+
+// 引用模块
+mod test;
+mod keygen;
+
+// 将其他模块的成员声明为当前模块直接可用的,等同于java的静态引用
+// 若省略这句,下面不可以直接使用Random结构体,而需要加上模块名,即test::Random
+use self::test::Random;
+
+use std::thread;
+use std::sync::mpsc;
+use std::collections::HashMap;
+use chrono::prelude::*;
+
+use std::io::{stdout, BufWriter};
+use ferris_says::say;
+
+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(); // unwrap为rust预定义错误处理模式,正常时返回OK值,错误时panic!
+
+    let rd = Random { seed: 100 };
+    println!("a random number:{}", rd.next());
+    let id = keygen::next_id();
+    println!("key from keygen:{}", id);
+    println!();
+    test_next_id();
+}
+
+fn test_next_id() {
+    let id_size = 100000;
+
+    let start_time = Utc::now().timestamp_nanos();
+    let (tx, rx) = mpsc::channel();
+
+
+    for _ in 0..id_size {
+        let tx = tx.clone();
+        thread::spawn(move || {
+            let id = keygen::next_id();
+            tx.send(id).unwrap()
+        });
+    };
+
+    let (tx2, rx2) = mpsc::channel();
+    let tx2 = tx2.clone();
+    let handle = thread::spawn(move || {
+        let mut m: HashMap<u64, i32> = HashMap::new();
+        let mut i = id_size;
+        loop {
+            let id = rx.recv().unwrap();
+            //let mut wrap = wrap.lock().unwrap();
+            if m.contains_key(&id) {
+                let v = *(m.get_mut(&id).unwrap());
+                m.insert(id, v + 1);
+            } else {
+                m.insert(id, 1);
+            }
+            i -= 1;
+            if i == 0 {
+                break;
+            }
+        }
+        tx2.send(m).unwrap();
+    });
+
+    handle.join().expect("The thread being joined has panicked");
+
+    let m = rx2.recv().unwrap();
+
+    let end_time = Utc::now().timestamp_nanos();
+    let used_time = end_time - start_time;
+    println!("Id size: {}\nTotal seconds:{}\nAvg nanos per id:{}", m.len(), used_time / 1000000000, (used_time as i64) / (id_size as i64));
+
+    let mut bad_size = 0;
+    for (_, v) in m.iter() {
+        if *v > 1 {
+            bad_size += 1;
+        }
+    }
+
+    if bad_size > 0 {
+        println!("Not good")
+    }
+}
+

+ 23 - 0
src/test/mod.rs

@@ -0,0 +1,23 @@
+// 一个模块(子目录)下的入口文件,统一命名为mod.rs,模块下的其他文件需要公开的,在mod.rs中统一导出
+
+use rand::prelude::*;
+
+// 声明一个结构体
+pub struct Random {
+    pub seed: i32 // 成员变量
+}
+
+impl Random { // 实现结构体,添加成员函数
+    pub fn next(&self) -> i32 { // lambda式语法
+        // rust没有gc,变量离开其作用域时,立即释放,这是使rust能作为一个实时语言支持更严苛应用场景下的开发的最大魅力所在
+        // 分配在栈上的基本类型、全由基本类型组成的元组变量或切片,赋值(包括作为参数或返回值传递)给另一个变量时都是深拷贝
+        // 分配在堆上的字符串等复杂类型变量,赋值(包括作为参数或返回值传递)给另一个变量时不是浅拷贝(rust没有这个东西),而是直接移动,原变量立即失效
+        // 如果希望原变量依然有效,不被移出,可以采用&引用符号传递变量引用,引用是更多一层指向原变量的指针,不是浅拷贝,这种方式称之为"借用",且借来的引用只读不可改写,称之为"不可变借用"
+        // 如果希望借来的引用可改写,则加上mut关键字即可,函数参数传递时型参和实参都要加,加mut的引用方式称之为"可变借用";且有约束,同一个变量仅可有一个可变借用,多个可变借用,或可变和不可变借用并存都不行,但允许有多个不可变借用
+        // 不能返回引用,因为离开作用域引用所指向的变量已经释放了,外部再使用其引用自然会报错;直接返回原变量,或者通过传入可变借用参数来解决
+        let mut rng = rand::thread_rng();
+        let mut nums : Vec<i32> = (1..*(&self.seed)).collect(); // 构造一个从1到seed的向量类型,向量类似于java的List,或go的切片,而相较于rust的数组它是不定长的,相较于rust的切片它是可变的
+        nums.shuffle(&mut rng);
+        nums[0] // 函数最后一行即返回值,所以可以用if else if实现三目表达式,最后一行表达式返回值类型需要与函数声明的返回类型一致,也有return用于提前返回;可用元组返回多值;无返回值的函数直接不要声明箭头和后面的返回值类型,或者用"空元组" -> ()
+    }
+}