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

Rust 初体验1

Rust 初体验

安装

打开官网,下载 rustup-init.exe, 选择缺省模式(1)安装。

国内源设置

.Cargo 目录下新建 config 文件,添加如下内容:

[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
# 指定镜像
replace-with = 'tuna' # 清华大学
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"[registries.rsproxy]
index = "https://rsproxy.cn/crates.io-index"[net]
git-fetch-with-cli = true

第一个程序

使用任意代码编辑器,编写如下代码,保存为后缀是.rs的源文件,如 hello.rs。

fn main()
{println!("Hello World!");
}

了解C语言的同学,会发现这个程序和C语言的hello.c非常相似。不同之处在于,fn 表示函数,main 表示程序的入口,println! 表示输出。! 表示宏,即 println 是个宏,而不是函数。

在源文件文件夹里,运行 rustc hello.rs 进行编译,生成 hello.exe。

运行 hello.exe,输出:

Hello World!

使用 Cargo 管理

cargo new project_name 创建一个新项目

cd project_name 进入项目

cargo build 编译生成Debug版本

cargo build --release 编译并生成可执行文件

cargo run 运行

cargo check 检查错误(不编译)

cargo 常用命令

build, b    Compile the current package
check, c    Analyze the current package and report errors, but don't build object files
clean       Remove the target directory
doc, d      Build this package's and its dependencies' documentation
new         Create a new cargo package
init        Create a new cargo package in an existing directory
add         Add dependencies to a manifest file
remove      Remove dependencies from a manifest file
run, r      Run a binary or example of the local package
test, t     Run the tests
bench       Run the benchmarks
update      Update dependencies listed in Cargo.lock
search      Search registry for crates
publish     Package and upload this package to the registry
install     Install a Rust binary. Default location is $HOME/.cargo/bin
uninstall   Uninstall a Rust binary

变量

Rust 是强类型语言,使用关键字 let 声明变量后,具有自动判断变量类型的能力,如:

let a = 123; 则默认 a 为整型数字,且精度不允许变化,即 a 的值不可改变,可以理解为“只读”。

这与 C 语言中的 const 修饰符起到的效果一样。在 C 语言中 int const a = 10; a 的值也不允许改变。

Rust 中如果要让变量可变,需要用 mut 关键词:

let mut a = 123;
a = 456;

指定数据类型

let a: u64 = 123;  // 后面跟数据类型u64,表示无符号64位整型变量。
let y: f32 = 3.0;   // 后面跟数据类型f32,表示32位浮点型变量。

Shadowing(影射)

变量名可以被重新使用,如:

let x = 5;
let x = x + 1;
let x = x * 2;

最终 x 的值为12。从语法上说, 变量 x 可以作为右值。

注释

可以使用 C/C++, Java 注释。

另外,可用 /// 表示文档开头注释

函数

定义函数,如需要参数,必须声明参数名称、类型。

fn another_function(x: i32, y: i32) { }

可在{}包括的块里,编写较为复杂的表达式,即所谓的函数体表达式。注:函数体表达式,并不能等同于函数体,不能使用 return 关键字。

let y = {let x = 3;x + 1
};

返回值类型声明

在参数声明之后用->来声明函数返回值的类型。 注:Rust 不支持自动返回值类型判断。

fn add(a: i32, b: i32) -> i32 {return a + b;
}

条件语句

if a > 0 {b = 1;
}  
else if a < 0 {b = -1;
}  
else {b = 0;
}
println!("b is {}", b);

if 后面不需要小括号,{} 必用。右括号 } 后不加

条件表达式必须是 bool 类型,不同于 C/C++ 的非 0 即真。

可以使用 if-else 结构实现类似于三元条件运算表达式 (A ? B : C) 。如:

let number = if a > 0 { 1 } else { -1 };

注:此处编译报错,检测出来其中 0 为 i32,代码未指定数据类型。故将0改为&0

let number = if a > &0 { 1 } else { -1 };

for 循环

最常用的循环结构。

let a = [10, 20, 30, 40, 50];
for i in a.iter() {println!("值为 : {}", i);
}

a.iter() 代表 a 的迭代器(iterator)

也可以通过下标来访问数组。如:

let a = [10, 20, 30, 40, 50];
for i in 0..5 {println!("a[{}] = {}", i, a[i]);
}

以上代码会报错。正确写法是:

const a: [i32; 5] = [10, 20, 30, 40, 50];
for i in 0..5 {println!("a[{}] = {}", i, a[i]);
}

可见,代码检查更严格。

while 循环

let mut number = 1;  // mut 表示number 在循环体内可以改变。
while number != 4 {println!("{}", number);number += 1;
}

无限循环结构 loop

可以通过 break 关键字,起到类似 return 一样的作用,使整个循环退出并给予外部一个返回值。

let mut i = 0;
let location = loop {let ch = s[i];if ch == '*' {break i;}i += 1;
};

以上代码会报错,可以改为:

fn main() {let s = "hello world";let mut i = 0;let location = loop {let ch = s.chars().nth(i).unwrap();if ch == ' ' {break i;}i += 1;};println!("{}", location);
}

变量与数据交互

方式有移动(Move)和克隆(Clone)两种,前者不保存移动前的变量,后者继续保留移动前的变量。

let s1 = String::from("hello");
let s2 = s1; 
println!("{}, world!", s1); // 错误!s1 已经失效let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2); //ok

引用(Reference)

& 运算符可以取变量的"引用"。当一个变量的值被引用时,变量本身不会被认定无效。注:C++中的概念。

引用不会获得值的所有权。引用只能租借(Borrow)值的所有权。

引用本身也是一个类型并具有一个值,这个值记录的是别的值所在的位置,但引用不具有所指值的所有权。

&mut 修饰可变的引用类型。

可变引用不允许多重引用,但不可变引用可以。

以上机制设计,主要出于对并发状态下发生数据访问碰撞的考虑,使得编译阶段就避免发生。

垂悬引用(Dangling References)

Rust 语言里不允许出现,如果有,编译器会发现它。

更多内容参看: https://www.runoob.com/rust/rust-ownership.html

字符串切片(String Slice)

let s = String::from("broadcast");
let part1 = &s[0..5];
let part2 = &s[5..9];
println!("{}={}+{}", s, part1, part2);

在 Rust 中有两种常用的字符串类型:str 和 String。

str 是 Rust 核心语言类型,凡用双引号包括的字符串常量整体的类型性质都是 &str。

String 类型是 Rust 标准公共库提供的一种数据类型,其功能更完善。String 和 str 都支持切片,切片的结果是 &str 类型的数据。

注:切片结果必须是引用类型,但开发者必须明示:

let slice = &s[0..3]; 

除了字符串,其他一些线性数据结构也支持切片操作,如:

let arr = [1, 3, 5, 7, 9];
let part = &arr[0..3];
for i in part.iter() {println!("{}", i);
}

结构体

定义结构体:

struct Site {domain: String,name: String,nation: String,found: u32
}

注:Rust 里 struct 语句仅用来定义,不能声明实例,结尾不需要; 符号,且每个字段定义之后用 , 分隔。

Rust 很多地方受 JavaScript 影响,在实例化结构体的时候用 JSON 对象的 key: value 语法来实现定义:

let runoob = Site {domain: String::from("www.runoob.com"),name: String::from("RUNOOB"),nation: String::from("China"),found: 2013
};

如果正在实例化的结构体,有字段名称与现存变量名称一样,可以简化书写。

let domain = String::from("www.runoob.com");
let name = String::from("RUNOOB");
let runoob = Site {domain,  // 等同于 domain : domain,name,    // 等同于 name : name,nation: String::from("China"),traffic: 2013
};

新建一个结构体实例,如果其中大部分属性需要被设置成与现存的一个结构体属性一样,仅需更改其中一两个字段的值,可以使用结构体更新语法:

let site = Site {domain: String::from("www.runoob.com"),name: String::from("RUNOOB"),..runoob
};

注:…runoob 后面不可以有逗号。这种语法不允许一成不变的复制另一个结构体实例,至少重新设定一个字段的值才能引用其他实例的值。

元组结构体

struct Color(u8, u8, u8);
struct Point(f64, f64);let black = Color(0, 0, 0);
let origin = Point(0.0, 0.0);

元组结构体对象的使用方式和元组一样,通过 . 和下标来进行访问:

struct Color(u8, u8, u8);
struct Point(f64, f64);
let black = Color(0, 0, 0);
let origin = Point(0.0, 0.0);
println!("black = ({}, {}, {})", black.0, black.1, lack.2);
println!("origin = ({}, {})", origin.0, origin.1);

结构体必须掌握字段值所有权,因为结构体失效的时候会释放所有字段。

结构体输出

导入调试库 #[derive(Debug)]

在 println 和 print 宏中可以用 {:?} 占位符输出一整个结构体;结构体如果属性较多,可使用另一个占位符 {:#?}

结构体方法

结构体方法的第一个参数必须是 &self,不需声明类型。

struct Rectangle {width: u32,height: u32,
}impl Rectangle {fn area(&self) -> u32 {self.width * self.height}
}fn main() {let rect1 = Rectangle { width: 30, height: 50 };println!("rect1's area is {}", rect1.area());
}

这里与Python中的Class方法有神似。

结构体关联函数

不依赖实例,使用时需要声明是在哪个 impl 块中的。String::from函数就是一个"关联函数"。

# [derive(Debug)]struct Rectangle {width: u32,height: u32,
}impl Rectangle {fn create(width: u32, height: u32) -> Rectangle {Rectangle { width, height }}
}fn main() {let rect = Rectangle::create(30, 50);println!("{:?}", rect);
}

这里的Rectangle中的create函数,即是结构体关联函数。这个概念与 C++语言里面的类成员函数有些相似。不同之处在于, C++ 类成员函数是在类的内部定义,并且使用 this 指针来访问类的实例。

单元结构体

结构体可以只作为一种象征而无需任何成员:

struct UnitStruct;

枚举类

# [derive(Debug)]enum Book {Papery, Electronic
}fn main() {let book = Book::Papery;println!("{:?}", book);
}

为枚举类成员添加元组属性描述

enum Book {Papery(u32),Electronic(String),
}let book = Book::Papery(1001);
let ebook = Book::Electronic(String::from("url://..."));

为属性命名,可以用结构体语法:

enum Book {Papery { index: u32 },Electronic { url: String },
}
let book = Book::Papery{index: 1001};

match 语法

枚举的目的是对某一类事物的分类,分类的目的是为了对不同的情况进行描述。Rust 通过 match 语句来实现分支结构。

fn main() {enum Book {Papery {index: u32},Electronic {url: String},}let book = Book::Papery{index: 1001};let ebook = Book::Electronic{url: String::from("url...")};match book {Book::Papery { index } => {println!("Papery book {}", index);},Book::Electronic { url } => {println!("E-book {}", url);}}
}

注意其中的,号与号。

match 枚举类实例 {分类1 => 返回值表达式,分类2 => 返回值表达式,...
}

对非枚举类进行分支选择时必须注意处理例外情况,即使在例外情况下没有任何要做的事 . 例外情况用下划线 _ 表示:

fn main() {let t = "abc";match t {"abc" => println!("Yes"),_ => {},}
}

Option 枚举类

Rust 标准库中的枚举类,用于填补 Rust 不支持 null 引用的空白。Rust 在语言层面彻底不允许空值 null 的存在,但null 可以高效地解决少量的问题,所以 Rust 引入了 Option 枚举类:

enum Option<T> {Some(T),None,
}

如果想定义一个可以为空值的类,可以这样:

let opt = Option::Some("Hello");

如果想针对 opt 执行某些操作,必须先判断它是否是 Option::None:

fn main() {let opt = Option::Some("Hello");match opt {Option::Some(something) => {println!("{}", something);},Option::None => {println!("opt is nothing");}}
}

初始值为空的 Option 必须明确类型:

fn main() {let opt: Option<&str> = Option::None;match opt {Option::Some(something) => {println!("{}", something);},Option::None => {println!("opt is nothing");}}
}

这种设计会让空值编程变得不容易,但这正是构建一个稳定高效的系统所需要的。由于 Option 是 Rust 编译器默认引入的,在使用时可以省略 Option:: 直接写 None 或者 Some()。

fn main() {let t = Some(64);match t {Some(64) => println!("Yes"),_ => println!("No"),}
}

又:

let i = 0;
match i {0 => println!("zero"),_ => {},
}

用 if let 语法缩短这段代码:

let i = 0;
if let 0 = i {println!("zero");
}

如:

fn main() {enum Book {Papery(u32),Electronic(String)}let book = Book::Electronic(String::from("url"));if let Book::Papery(index) = book {println!("Papery {}", index);} else {println!("Not papery book");}
}

注意其中 if 语句后的 = 号。

组织管理

Rust 中有三个重要的组织概念:箱、包、模块。

箱(Crate)

"箱"是二进制程序文件或者库文件,存在于"包"中。树状结构,树根是编译器开始运行时编译的源文件所编译的程序。

注意:“二进制程序文件"不一定是"二进制可执行文件”,只能确定是是包含目标机器语言的文件,文件格式随编译环境的不同而不同。

包(Package)

当使用 Cargo 执行 new 命令创建 Rust 工程时,工程目录下会建立一个 Cargo.toml 文件。工程的实质就是一个包,包必须由一个 Cargo.toml 文件来管理,该文件描述了包的基本信息以及依赖项。

一个包最多包含一个库"箱",可以包含任意数量的二进制"箱",但是至少包含一个"箱"(不管是库还是二进制"箱")。

当使用 cargo new 命令创建完包之后,src 目录下会生成一个 main.rs 源文件,Cargo 默认这个文件为二进制箱的根,编译之后的二进制箱将与包名相同。

模块(Module)

对于一个软件工程来说,往往按照所使用的编程语言的组织规范来进行组织,组织模块的主要结构往往是树。Java 组织功能模块的主要单位是类,而 JavaScript 组织模块的主要方式是 function。Rust 中的组织单位是模块(Module)。

这些先进的语言的组织单位可以层层包含,就像文件系统的目录结构一样。Rust 中的组织单位是模块(Module)。

路径分为绝对路径和相对路径。绝对路径从 crate 关键字开始描述。相对路径从 self 或 super 关键字或一个标识符开始描述。Rust 中的路径分隔符是 ::。如:

crate::nation::government::govern();

是描述 govern 函数的绝对路径,相对路径可以表示为:

nation::government::govern();

访问权限

Rust 中有两种简单的访问权:公共(public)和私有(private)。

默认情况下,如果不加修饰符,模块中的成员访问权将是私有的。

如果想使用公共权限,需要使用 pub 关键字。

对于私有的模块,只有在与其平级的位置或下级的位置才能访问,不能从其外部访问。

mod nation {pub mod government {pub fn govern() {}}mod congress {pub fn legislate() {}}mod court {fn judicial() {super::congress::legislate();}}
}fn main() {nation::government::govern();
}

这段程序是能通过编译的。请注意观察 court 模块中 super 的访问方法。更多的信息请参考:
https://www.runoob.com/rust/rust-project-management.html

use 关键字能够将模块标识符引入当前作用域

mod nation {pub mod government {pub fn govern() {}}
}use crate::nation::government::govern; // 解决局部模块路径过长的问题。fn main() {govern();
}

重命名

mod nation {pub mod government {pub fn govern() {}}pub fn govern() {}
}use crate::nation::government::govern;   
use crate::nation::govern as nation_govern;  // 解决重名问题fn main() {nation_govern();govern();
}

还可以与 pub 关键字配合使用:

mod nation {pub mod government {pub fn govern() {}}pub use government::govern;
}fn main() {nation::govern();
}

Rust 官方标准库字典

所有系统库模块都是被默认导入的,所以在使用的时候只需要使用 use 关键字简化路径即可使用。

在 Rust 中没有 Exception。对可恢复错误用 Result<T, E> 类来处理,对不可恢复错误使用 panic! 宏来处理。

不可恢复错误

fn main() {panic!("error occured"); // 程序将在此处中断,不执行后续语句println!("Hello, Rust");
}

回溯是不可恢复错误的另一种处理方式,它会展开运行的栈并输出所有的信息,然后程序依然会退出。上面的省略号省略了大量的输出信息,我们可以找到我们编写的 panic! 宏触发的错误。

可恢复的错误

Rust 通过 Result<T, E> 枚举类作返回值来进行异常表达。

use std::fs::File;fn main() {let f = File::open("hello.txt");match f {Ok(file) => {println!("File opened successfully.");},Err(err) => {println!("Failed to open the file.");}}
}

可用 if let 语法对简化 match 语法块:

use std::fs::File;fn main() {let f = File::open("hello.txt");if let Ok(file) = f {println!("File opened successfully.");} else {println!("Failed to open the file.");}
}

Rust 中可以在 Result 对象后添加 ? 操作符将同类的 Err 直接传递出去.

fn f(i: i32) -> Result<i32, bool> {if i >= 0 { Ok(i) }else { Err(false) }
}fn g(i: i32) -> Result<i32, bool> {let t = f(i)?;Ok(t) // 因为确定 t 不是 Err, t 在这里已经是 i32 类型
}fn main() {let r = g(10000);if let Ok(v) = r {println!("Ok: g(10000) = {}", v);} else {println!("Err");}
}

? 符的实际作用是将 Result 类非异常的值直接取出,如果有异常就将异常 Result 返回出去。所以,? 符仅用于返回值类型为 Result<T, E> 的函数,其中 E 类型必须和 ? 所处理的 Result 的 E 类型一致。

判断 Result 的 Err 类型,用函数 kind()。

use std::io;
use std::io::Read;
use std::fs::File;fn read_text_from_file(path: &str) -> Result<String, io::Error> {let mut f = File::open(path)?;let mut s = String::new();f.read_to_string(&mut s)?;Ok(s)
}fn main() {let str_file = read_text_from_file("hello.txt");match str_file {Ok(s) => println!("{}", s),Err(e) => {match e.kind() {io::ErrorKind::NotFound => {println!("No such file");},_ => {println!("Cannot read the file");}}}}
}

相关文章:

Rust 初体验1

Rust 初体验 安装 打开官网&#xff0c;下载 rustup-init.exe&#xff0c; 选择缺省模式&#xff08;1&#xff09;安装。 国内源设置 在 .Cargo 目录下新建 config 文件&#xff0c;添加如下内容&#xff1a; [source.crates-io] registry "https://github.com/rus…...

【深度学习】实验7布置,图像超分辨

清华大学驭风计划 因为篇幅原因实验答案分开上传&#xff0c; 实验答案链接http://t.csdnimg.cn/P1yJF 如果需要更详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢迎私信博主&#xff0c;大家可以相互讨论交流哟~~ 深度学习训练营 案例 7 &#xff1…...

【八大排序】归并排序 | 计数排序 + 图文详解!!

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅C语言进阶之路 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、归并排序1.1 基本思想 动图演示2.2 递归版本代码实现 算法步骤2.3 非递归版本代…...

Netty应用(三) 之 NIO开发使用 网络编程 多路复用

目录 重要&#xff1a;logback日志的引入以及整合步骤 5.NIO的开发使用 5.1 文件操作 5.1.1 读取文件内容 5.1.2 写入文件内容 5.1.3 文件的复制 5.2 网络编程 5.2.1 accept&#xff0c;read阻塞的NIO编程 5.2.2 把accept&#xff0c;read设置成非阻塞的NIO编程 5.2.3…...

融资项目——配置redis

一、 在maven中导入相关依赖。在springboot框架中&#xff0c;我们使用spring data redis <!-- spring boot redis缓存引入 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifa…...

npm修改镜像源

背景&#xff1a;切换npm镜像源是经常遇到的事&#xff0c;下面记录下具体操作命令 1. 打开终端运行"npm config get registry"命令来查看当前配置的镜像源 npm config get registry2. 修改成淘宝镜像源"https://registry.npmjs.org/" npm config set re…...

K8S系列文章之 [基于 Alpine 使用 kubeadm 搭建 k8s]

先部署基础环境&#xff0c;然后根据官方文档 K8s - Alpine Linux&#xff0c;进行操作。 将官方文档整理为脚本 整理脚本时&#xff0c;有部分调整 #!/bin/shset -x # 添加源&#xff0c;安装时已经配置 #cat >> /etc/apk/repositories <<"EOF" #htt…...

JVM相关-JVM模型、垃圾回收、JVM调优

一、JVM模型 JVM内部体型划分 JVM的内部体系结构分为三部分&#xff0c;分别是&#xff1a;类加载器&#xff08;ClassLoader&#xff09;子系统、运行时数据区&#xff08;内存&#xff09;和执行引擎 1、类加载器 概念 每个JVM都有一个类加载器子系统&#xff08;class l…...

提升图像分割精度:学习UNet++算法

文章目录 一、UNet 算法简介1.1 什么是 UNet 算法1.2 UNet 的优缺点1.3 UNet 在图像分割领域的应用 二、准备工作2.1 Python 环境配置2.2 相关库的安装 三、数据处理3.1 数据的获取与预处理3.2 数据的可视化与分析 四、网络结构4.1 UNet 的网络结构4.2 UNet 各层的作用 五、训练…...

排序算法---冒泡排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 冒泡排序是一种简单的排序算法&#xff0c;其原理是重复地比较相邻的两个元素&#xff0c;并将顺序不正确的元素进行交换&#xff0c;使得每次遍历都能将一个最大&#xff08;或最小&#xff09;的元素放到末尾。通过多次遍…...

基于数据挖掘的微博事件分析与可视化大屏分析系统

设计原理&#xff0c;是指一个系统的设计由来&#xff0c;其将需求合理拆解成功能&#xff0c;抽象的描述系统的模块&#xff0c;以模块下的功能。功能模块化后&#xff0c;变成可组合、可拆解的单元&#xff0c;在设计时&#xff0c;会将所有信息分解存储在各个表中&#xff0…...

数学建模-灰色预测最强讲义 GM(1,1)原理及Python实现

目录 一、GM&#xff08;1&#xff0c;1&#xff09;模型预测原理 二、GM&#xff08;1&#xff0c;1&#xff09;模型预测步骤 2.1 数据的检验与处理 2.2 建立模型 2.3 检验预测值 三、案例 灰色预测应用场景&#xff1a;时间序列预测 灰色预测的主要特点是模型使用的…...

智慧自助餐饮系统(SpringBoot+MP+Vue+微信小程序+JNI+ncnn+YOLOX-Nano)

一、项目简介 本项目是配合智慧自助餐厅下的一套综合系统&#xff0c;该系统分为安卓端、微信小程序用户端以及后台管理系统。安卓端利用图像识别技术进行识别多种不同菜品&#xff0c;识别成功后安卓端显示该订单菜品以及价格并且生成进入小程序的二维码&#xff0c;用户扫描…...

零基础学编程从入门到精通,系统化的编程视频教程上线,中文编程开发语言工具构件之缩放控制面板构件用法

一、前言 零基础学编程从入门到精通&#xff0c;系统化的编程视频教程上线&#xff0c;中文编程开发语言工具构件之缩放控制面板构件用法 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例源码文件下载可以点击最下方官网卡片——软件下载—…...

【MySQL进阶之路】MySQL 中表空间和数据区的概念以及预读机制

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…...

JVM 性能调优 - 常用的垃圾回收器(6)

垃圾收集器 在 JVM(Java虚拟机)中,垃圾收集器(Garbage Collector)是负责自动管理内存的组件。它的主要任务是在程序运行过程中,自动回收不再使用的对象所占用的内存空间,以便为新的对象提供足够的内存。 JVM中的垃圾收集器使用不同的算法和策略来实现垃圾收集过程,以…...

【java】Hibernate访问数据库

一、Hibernate访问数据库案例 Hibernate 是一个在 Java 社区广泛使用的对象关系映射&#xff08;ORM&#xff09;工具。它简化了 Java 应用程序中数据库操作的复杂性&#xff0c;并提供了一个框架&#xff0c;用于将对象模型数据映射到传统的关系型数据库。下面是一个简单的使…...

从零开始手写mmo游戏从框架到爆炸(八)— byte数组传输

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 Netty帧解码器 Netty中&#xff0c;提供了几个重要的可以直接使用的帧解码器。 LineBasedFrameDecoder 行分割帧解码器。适用场景&#xff1a;每个上层数据包&#xff0c;使…...

Elasticsearch:BM25 及 使用 Elasticsearch 和 LangChain 的自查询检索器

本工作簿演示了 Elasticsearch 的自查询检索器将非结构化查询转换为结构化查询的示例&#xff0c;我们将其用于 BM25 示例。 在这个例子中&#xff1a; 我们将摄取 LangChain 之外的电影样本数据集自定义 ElasticsearchStore 中的检索策略以仅使用 BM25使用自查询检索将问题转…...

uniapp的api用法大全

页面生命周期API uniApp中的页面生命周期API可以帮助开发者在页面的不同生命周期中执行相应的操作。常用的页面生命周期API包括&#xff1a;onLoad、onShow、onReady、onHide、onUnload等。其中&#xff0c;onLoad在页面加载时触发&#xff0c;onShow在页面显示时触发&#xf…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

【WebSocket】SpringBoot项目中使用WebSocket

1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖&#xff0c;添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...

Pydantic + Function Calling的结合

1、Pydantic Pydantic 是一个 Python 库&#xff0c;用于数据验证和设置管理&#xff0c;通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发&#xff08;如 FastAPI&#xff09;、配置管理和数据解析&#xff0c;核心功能包括&#xff1a; 数据验证&#xff1a;通过…...