当前位置: 首页 > news >正文

做进口货的电商网站铜川网络推广

做进口货的电商网站,铜川网络推广,怀柔网站建设,一物一码二维码生成系统文档:Rust 程序设计语言 - Rust 程序设计语言 简体中文版 (bootcss.com) 墙裂推荐这个文档 第一章入门 入门指南 - Rust 程序设计语言 简体中文版 第二章猜猜看游戏 猜猜看游戏教程 - Rust 程序设计语言 简体中文版 (bootcss.com) // 导入库 use std::io; use s…

文档:Rust 程序设计语言 - Rust 程序设计语言 简体中文版 (bootcss.com)

墙裂推荐这个文档

第一章入门

入门指南 - Rust 程序设计语言 简体中文版

第二章猜猜看游戏

猜猜看游戏教程 - Rust 程序设计语言 简体中文版 (bootcss.com)

// 导入库
use std::io;
use std::cmp::Ordering;
use rand::Rng;fn main() {println!("Guess the number!");// 生成一个随机数,范围在[1, 100],,需要在配置文toml中加依赖let secret_number = rand::thread_rng().gen_range(1, 101);// loop循环loop {println!("Please input your guess.");// 定义一个可变变量,加mut是可变的,不加mut是不可变的let mut guess = String::new();// 读一行数据到guess中,返回值是Result(枚举,成员是Ok和Err)// Result 拥有expect方法// 如果 io::Result 实例的值是 Err,expect 会导致程序崩溃,并显示当做参数传递给 expect 的信息。// 如果 read_line 方法返回 Err,则可能是来源于底层操作系统错误的结果。如果 io::Result 实例的值是 Ok,expect 会获取 Ok 中的值并原样返回。io::stdin().read_line(&mut guess).expect("Failed to read line");// Rust 允许用一个新值来 隐藏 (shadow) guess 之前的值// String 实例的 trim 方法会去除字符串开头和结尾的空白字符。// 字符串的 parse 方法 将字符串解析成数字。// parse也是有返回值,成功的话就是返回num,失败则继续输入let guess: u32 = match guess.trim().parse() {Ok(num) => num,Err(_) => continue,};println!("You guessed: {}", guess);// 用match来匹配match guess.cmp(&secret_number) {Ordering::Less => println!("Too small!"),       // guess < secret_numberOrdering::Greater => println!("Too big!"),Ordering::Equal => {println!("You win!");                       // 匹配,跳出循环break;}}}
}

代码量不大,学了不少语法

测试

第三章常见编程概念

3.1 变量与可变性

变量不可改

fn main() {println!("Hello, world!");let i = 3;println!("i = {}", i);i = 23;                 // 变量不可以更改println!("i = {}", i);
}

结果

 可变变量,可以修改

fn main() {println!("Hello, world!");let mut i = 3;println!("i = {}", i);i = 23;println!("i = {}", i);
}

变量与常量的区别

(1)不允许对常量使用mut;

(2)声明常量使用 const 关键字而不是 let,并且 必须 注明值的类型;

(3)常量可以在任何作用域中声明;

(4)常量只能被设置为常量表达式,而不能是函数调用的结果,或任何其他只能在运行时计算出的值。

const MAX_POINTS : u32 = 100_100;

隐藏(Shadowing)

fn main() {let x = 5;let x = x + 1;let x = x * 2;println!("The value of x is: {}", x);
}

隐藏与将变量标记为 mut 是有区别的。当不小心尝试对变量重新赋值时,如果没有使用 let 关键字,就会导致编译时错误。通过使用 let,我们可以用这个值进行一些计算,不过计算完之后变量仍然是不变的。

mut 与隐藏的另一个区别是,当再次使用 let 时,实际上创建了一个新变量,我们可以改变值的类型,但复用这个名字。

3.2 数据类型

标量类型 标量(scalar)类型代表一个单独的值。Rust 有四种基本的标量类型:整型、浮点型、布尔类型和字符类型

整数

长度有符号无符号
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

整形字面值

数字字面值例子
Decimal98_222
Hex0xff
Octal0o77
Binary0b1111_0000
Byte (u8 only)b'A'

浮点型

Rust 也有两个原生的 浮点数floating-point numbers)类型,它们是带小数点的数字。Rust 的浮点数类型是 f32 和 f64,分别占 32 位和 64 位。默认类型是 f64,因为在现代 CPU 中,它与 f32 速度几乎一样,不过精度更高。

Rust 中的所有数字类型都支持基本数学运算:加法、减法、乘法、除法和取余。

fn main() {// 加法let _sum = 5 + 10;// 减法let _difference = 95.5 - 4.3;// 乘法let _product = 4 * 30;// 除法let _quotient = 56.7 / 32.2;// 取余let _remainder = 43 % 5;
}

布尔型

正如其他大部分编程语言一样,Rust 中的布尔类型有两个可能的值:true 和 false。Rust 中的布尔类型使用 bool 表示。

字符类型

在 Rust 中,拼音字母(Accented letters),中文、日文、韩文等字符,emoji(绘文字)以及零长度的空白字符都是有效的 char 值。Unicode 标量值包含从 U+0000 到 U+D7FF 和 U+E000 到 U+10FFFF 在内的值。不过,“字符” 并不是一个 Unicode 中的概念,所以人直觉上的 “字符” 可能与 Rust 中的 char 并不符合。

fn main() {let c = 'z';let z = 'ℤ';let heart_eyed_cat = '😻';
}

复合类型

复合类型Compound types)可以将多个值组合成一个类型。Rust 有两个原生的复合类型:元组(tuple)数组(array)

元组是一个将多个其他类型的值组合进一个复合类型的主要方式。元组长度固定:一旦声明,其长度不会增大或缩小。

使用包含在圆括号中的逗号分隔的值列表来创建一个元组。元组中的每一个位置都有一个类型,而且这些不同值的类型也不必是相同的。

fn main() {let tup: (i32, f64, u8) = (500, 6.4, 1);let tup = (500, 6.4, 1);let (x, y, z) = tup;println!("The value of y is: {}", y);let x: (i32, f64, u8) = (500, 6.4, 1);let _five_hundred = x.0;          // 解构let _six_point_four = x.1;        // 解构let _one = x.2;                   // 解构}

另一个包含多个值的方式是 数组array)。与元组不同,数组中的每个元素的类型必须相同。Rust 中的数组与一些其他语言中的数组不同,因为 Rust 中的数组是固定长度的:一旦声明,它们的长度不能增长或缩小。

Rust 中,数组中的值位于中括号内的逗号分隔的列表中。

fn main() {let a = [1, 2, 3, 4, 5];let months = ["January", "February", "March", "April", "May", "June", "July","August", "September", "October", "November", "December"];let a: [i32; 5] = [1, 2, 3, 4, 5];let first = a[0];let second = a[1];let index = 3;let element = a[index];println!("The value of element is: {}", element);
}

3.3 函数如何工作

和C++大同小异,这里不同的是具有返回值的函数

fn five() -> i32 {// 没有return// 没有分号5
}fn main() {let x = five();println!("The value of x is: {}", x);
}

3.4 注释

不赘述

3.5 控制流

if-else

fn main() {let number = 6;// 注意没有括号if number % 4 == 0 {println!("number is divisible by 4");} else if number % 3 == 0 {println!("number is divisible by 3");} else if number % 2 == 0 {println!("number is divisible by 2");} else {println!("number is not divisible by 4, 3, or 2");}
}

在let语句中使用if

fn main() {let condition = true;let number = if condition {5} else {6};println!("The value of number is: {}", number);
}

if 的每个分支的可能的返回值都必须是相同类型

循环语句

Rust 有三种循环:loopwhile 和 for

loop

fn main() {let mut counter = 0;let result = loop {counter += 1;if counter == 10 {break counter * 2;}};println!("The result is {}", result);
}

while

fn main() {let mut number = 3;while number != 0 {println!("{}!", number);number = number - 1;}println!("LIFTOFF!!!");
}

for

fn main() {let a = [10, 20, 30, 40, 50];for element in a.iter() {println!("the value is: {}", element);}for number in (1..4).rev() {println!("{}!", number);}println!("LIFTOFF!!!");
}

第四章认识所有权

所有权(系统)是 Rust 最为与众不同的特性,它让 Rust 无需垃圾回收(garbage collector)即可保障内存安全。因此,理解 Rust 中所有权如何工作是十分重要的。

4.1 所有权

所有运行的程序都必须管理其使用计算机内存的方式。一些语言中具有垃圾回收机制,在程序运行时不断地寻找不再使用的内存;在另一些语言中,程序员必须亲自分配和释放内存。Rust 则选择了第三种方式:通过所有权系统管理内存,编译器在编译时会根据一系列的规则进行检查。在运行时,所有权系统的任何功能都不会减慢程序。

所有权规则

  1. Rust 中的每一个值都有一个被称为其 所有者owner)的变量。
  2. 值有且只有一个所有者。
  3. 当所有者(变量)离开作用域,这个值将被丢弃。

字符串字面值不可变,这里以String为例

fn main() {println!("Hello, world!");// String在堆上// from 函数基于字符串字面值来创建 Stringlet mut str = String::from("hello");str.push_str(", world");              // push_str() 在字符串后追加字面值println!("{}", str);
}

结果

对于 String 类型,为了支持一个可变,可增长的文本片段,需要在堆上分配一块在编译时未知大小的内存来存放内容。这意味着:

  • 必须在运行时向操作系统请求内存。
  • 需要一个当我们处理完 String 时将内存返回给操作系统的方法。

第一部分由我们完成:当调用 String::from 时,它的实现 (implementation) 请求其所需的内存。这在编程语言中是非常通用的。

然而,第二部分实现起来就各有区别了。在有 垃圾回收garbage collectorGC)的语言中, GC 记录并清除不再使用的内存,而我们并不需要关心它。没有 GC 的话,识别出不再使用的内存并调用代码显式释放就是我们的责任了,跟请求内存的时候一样。从历史的角度上说正确处理内存回收曾经是一个困难的编程问题。如果忘记回收了会浪费内存。如果过早回收了,将会出现无效变量。如果重复回收,这也是个 bug。我们需要精确的为一个 allocate 配对一个 free

Rust 采取了一个不同的策略:内存在拥有它的变量离开作用域后就被自动释放。

fn main() {{let s = String::from("hello"); // 从此处起,s 是有效的// 使用 s}                                  // 此作用域已结束,// s 不再有效
}

注意:在 C++ 中,这种 item 在生命周期结束时释放资源的模式有时被称作 资源获取即初始化Resource Acquisition Is Initialization (RAII))。如果你使用过 RAII 模式的话应该对 Rust 的 drop 函数并不陌生。

变量与数据交互的方式(一):移动

fn main() {let x = 5;let y = x;
}

基本变量赋值,x和y都在栈中,且值为5。

那么String类型呢?

fn main() {let s1 = String::from("hello");let s2 = s1;
}

String 由三部分组成,如图左侧所示:一个指向存放字符串内容内存的指针,一个长度,和一个容量。这一组数据存储在栈上。右侧则是堆上存放内容的内存部分。

长度表示 String 的内容当前使用了多少字节的内存。容量是 String 从操作系统总共获取了多少字节的内存。长度与容量的区别是很重要的,不过在当前上下文中并不重要,所以现在可以忽略容量。

当将 s1 赋值给 s2String 的数据被复制了,这意味着我们从栈上拷贝了它的指针、长度和容量。我们并没有复制指针指向的堆上数据。

 像C++中的浅拷贝

如果 Rust 也拷贝了堆上的数据,那么内存看起来就是这样的。如果 Rust 这么做了,那么操作 s2 = s1 在堆上数据比较大的时候会对运行时性能造成非常大的影响。

浅拷贝)这就有了一个问题:当 s2 和 s1 离开作用域,他们都会尝试释放相同的内存。这是一个叫做 二次释放double free)的错误,也是之前提到过的内存安全性 bug 之一。两次释放(相同)内存会导致内存污染,它可能会导致潜在的安全漏洞。

为了确保内存安全,这种场景下 Rust 的处理有另一个细节值得注意。与其尝试拷贝被分配的内存,Rust 则认为 s1 不再有效,因此 Rust 不需要在 s1 离开作用域后清理任何东西。看看在 s2 被创建之后尝试使用 s1 会发生什么;这段代码不能运行:

fn main() {let s1 = String::from("hello");let s2 = s1;println!("{}, world!", s1);}

结果:

如果你在其他语言中听说过术语 浅拷贝shallow copy)和 深拷贝deep copy),那么拷贝指针、长度和容量而不拷贝数据可能听起来像浅拷贝。不过因为 Rust 同时使第一个变量无效了,这个操作被称为 移动(move),而不是浅拷贝。上面的例子可以解读为 s1 被 移动 到了 s2 中。那么具体发生了什么,如图

这样就解决了之前的问题!因为只有 s2 是有效的,当其离开作用域,它就释放自己的内存。

另外,这里还隐含了一个设计选择:Rust 永远也不会自动创建数据的 “深拷贝”。因此,任何 自动 的复制可以被认为对运行时性能影响较小。

变量与数据交互的方式(二):克隆

如果 确实 需要深度复制 String 中堆上的数据,而不仅仅是栈上的数据,可以使用一个叫做 clone 的通用函数。

fn main() {let s1 = String::from("hello");let s2 = s1.clone();println!("{}, world!", s1);println!("{}, world!", s2);
}

这段代码的实际结果就是如下图

只在栈上的数据:拷贝

但这段代码似乎与我们刚刚学到的内容相矛盾:没有调用 clone,不过 x 依然有效且没有被移动到 y 中。

fn main() {let x = 5;let y = x;println!("x = {}, y = {}", x, y);
}

原因是像整型这样的在编译时已知大小的类型被整个存储在栈上,所以拷贝其实际的值是快速的。这意味着没有理由在创建变量 y 后使 x 无效。换句话说,这里没有深浅拷贝的区别,所以这里调用 clone 并不会与通常的浅拷贝有什么不同,可以不用管它。

所有权与函数

将值传递给函数在语义上与给变量赋值相似。向函数传递值可能会移动或者复制,就像赋值语句一样。

简单的案例,见注释

fn main() {let s = String::from("hello");           // s 进入作用域takes_ownership(s);                  // s 的值移动到函数里 ...// ... 所以到这里不再有效// println!("{}", s);                               // 报错let x = 5;                                  // x 进入作用域makes_copy(x);                      // x 应该移动函数里,// 但 i32 是 Copy 的,所以在后面可继续使用 x} // 这里, x 先移出了作用域,然后是 s。但因为 s 的值已被移走,// 所以不会有特殊操作fn takes_ownership(some_string: String) { // some_string 进入作用域println!("{}", some_string);
} // 这里,some_string 移出作用域并调用 `drop` 方法。占用的内存被释放fn makes_copy(some_integer: i32) { // some_integer 进入作用域println!("{}", some_integer);
} // 这里,some_integer 移出作用域。不会有特殊操作

复杂一点的

fn main() {let s = String::from("hello");           // s 进入作用域takes_ownership(s);                  // s 的值移动到函数里 ...// ... 所以到这里不再有效// println!("{}", s);                               // 报错
} 
fn takes_ownership(some_string: String) { // some_string 进入作用域let str = String::from(some_string);println!("{}", some_string);                      // 报错         
}

返回值与作用域

返回值也可以转移所有权

见注释

fn main() {let s1 = gives_ownership();         // gives_ownership 将返回值// 移给 s1let s2 = String::from("hello");     // s2 进入作用域let s3 = takes_and_gives_back(s2);  // s2 被移动到// takes_and_gives_back 中, // 它也将返回值移给 s3
} // 这里, s3 移出作用域并被丢弃。s2 也移出作用域,但已被移走,// 所以什么也不会发生。s1 移出作用域并被丢弃fn gives_ownership() -> String {             // gives_ownership 将返回值移动给// 调用它的函数let some_string = String::from("hello"); // some_string 进入作用域.some_string                                      // 返回 some_string 并移出给调用的函数
}// takes_and_gives_back 将传入字符串并返回该值
fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域a_string  // 返回 a_string 并移出给调用的函数
}

变量的所有权总是遵循相同的模式:将值赋给另一个变量时移动它。当持有堆中数据值的变量离开作用域时,其值将通过 drop 被清理掉,除非数据被移动为另一个变量所有。

在每一个函数中都获取所有权并接着返回所有权有些啰嗦。如果想要函数使用一个值但不获取所有权该怎么办呢?如果还要接着使用它的话,每次都传进去再返回来就有点烦人了,除此之外,也可能想返回函数体中产生的一些数据。可以使用元组来返回多个值

fn main() {let s1 = String::from("hello");let (s2, len) = calculate_length(s1);println!("The length of '{}' is {}.", s2, len);
}fn calculate_length(s: String) -> (String, usize) {let length = s.len(); // len() 返回字符串的长度(s, length)
}

返回参数的所有权

见引用部分

4.4 引用与借用

下面是如何定义并使用一个calculate_length 函数,它以一个对象的引用作为参数而不是获取值的所有权:

fn main() {let s1 = String::from("hello");let len = calculate_length(&s1);println!("The length of '{}' is {}.", s1, len);
}fn calculate_length(s: &String) -> usize {s.len()
}

& 符号就是 引用,它允许你使用值但不获取其所有权。

注意:与使用 & 引用相反的操作是 解引用dereferencing),它使用解引用运算符,*

变量 s 有效的作用域与函数参数的作用域一样,不过当引用离开作用域后并不丢弃它指向的数据,因为我们没有所有权。

将获取引用作为函数参数称为 借用(borrowing)。

正如变量默认是不可变的,引用也一样(默认)不允许修改引用的值。

fn main() {let s = String::from("hello");change(&s);
}fn change(some_string: &String) {some_string.push_str(", world");
}

结果

可变引用 

fn main() {// s也必须是mut的let mut s = String::from("hello");change(&mut s);
}// 注意形参的形式
fn change(some_string: &mut String) {some_string.push_str(", world");
}

不过可变引用有一个很大的限制:在特定作用域中的特定数据有且只有一个可变引用。

fn main() {let mut s = String::from("hello");let r1 = &mut s;let r2 = &mut s;             // 错误println!("{}, {}", r1, r2);}

http://www.khdw.cn/news/18727.html

相关文章:

  • 织梦中二次开发新的网站网络营销怎么推广
  • 淄博网站制作营销型网站建设ppt
  • 国外客户的网站电话推广优化
  • 视频网站能备案吗营销策略有哪些
  • 下载长沙appsem优化是什么
  • google站长工具哈尔滨seo网络推广
  • 热卖平台网站怎么做餐饮管理和营销方案
  • 灵川建设局网站福建百度推广开户
  • 网站开发专利申请互联网金融营销案例
  • 做开发的工资一般多少重庆排名优化整站优化
  • 房地产网站互动设计公司seo黑帽是什么
  • 制作网站语言产品推广思路
  • 后台网站怎么做视频百度关键词推广公司
  • 娄底网站建设公司温州高端网站建设
  • 织梦可以做大型网站吗打广告去哪个平台免费
  • 中煤浙江基础建设有限公司网站建网站需要多少钱
  • 电子商务网站建设的答案免费营销软件网站
  • 上海企业网站建设服务seo发包技术教程
  • w3c网站模板sem和seo的区别
  • 外贸网站好做吗免费查权重工具
  • 东莞外贸推广windows优化大师怎么使用
  • 兰州做网站多少钱推广普通话宣传语100字
  • 网站图解图片是用什么软件做的成都搜索优化排名公司
  • 中国水土保持生态环境建设网站免费开通网站
  • 老年大学网站建设长沙网站托管优化
  • 如何建设内部网站如何提高关键词搜索排名
  • 学校网站开发背景抖音seo是什么
  • 网站域名解析页面网络营销的策略
  • 免费零食网站模板网站优化网络推广seo
  • 做外贸推广自己网站镇江百度seo