Rust 初体验

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");}}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/671240.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring-security SecurityContextHolder

翻译版本【spring-security 6.2.1】SecurityContextHolder SecurityContextHolder Spring Security身份验证模型的核心是SecurityContextHolder。它包含SecurityContext。 SecurityContextHolder是Spring Security存储身份验证详细信息的地方。Spring Security并不关心Secur…

【C语言】深入理解函数指针

函数指针是 C 语言中一个非常有用且强大的概念&#xff0c;它允许我们将函数作为参数传递给其他函数、在运行时动态选择要调用的函数以及实现回调函数等功能。在本篇博客中&#xff0c;我们将深入探讨函数指针的概念、用法以及其在实际编程中的应用。 目录 前言 什么是函数指…

C++ 动态规划 状态压缩DP 蒙德里安的梦想

求把 NM 的棋盘分割成若干个 12 的长方形&#xff0c;有多少种方案。 例如当 N2&#xff0c;M4 时&#xff0c;共有 5 种方案。当 N2&#xff0c;M3 时&#xff0c;共有 3 种方案。 如下图所示&#xff1a; 2411_1.jpg 输入格式 输入包含多组测试用例。 每组测试用例占一行…

OCR文本纠错思路

文字错误类别&#xff1a;多字 少字 形近字 当前方案 文本纠错思路 简单&#xff1a; 一、构建自定义词典&#xff0c;提高分词正确率。不在词典中&#xff0c;也不是停用词&#xff0c;分成单字的数据极有可能是错字&#xff08;少部分可能是新词&#xff09;。错字与前后的…

webapi-元素的属性设置-图片切换的案例

元素的属性设置 1.目标 ​ 掌握图片的src属性的设置 在页面使用img标签显示一张图片, 点击这个图片更换一张新的图片 2.实现思路 使用img 指定src “路径” 指定id“one”获取img标签&#xff0c; 添加onclick 点击事件在事件处理程序函数体中修改图片的src的值 3.代码实…

uniapp设置不显示顶部返回按钮

一、pages文件中&#xff0c;在相应的页面中设置 "titleNView": {"autoBackButton": false} 二、对应的页面文件设置隐藏元素 document.querySelector(.uni-page-head-hd).style.display none

【Git】三棵“树”介绍

Git是一种分布式版本控制系统&#xff0c;它使用了三树原理来管理代码的变化和版本。 三树原理包括工作区树&#xff08;Working Tree&#xff09;、暂存区树&#xff08;Staging Area/Index&#xff09;和版本库树&#xff08;Commit/HEAD&#xff09;。 工作区树&#xff08…

计算机网络实验四

实验四 VLAN划分与配置 1、实验目的 • 理解并掌握Port Vlan的配置方法 • 理解并掌握掌握跨交换机实现VLAN的配置方法 2、实验设备 &#xff08;1&#xff09;实验内容1&#xff1a;交换机端口隔离—Port Vlan的配置 以太网交换机一台笔记本电脑一台PC机两台配置电缆、网…

二重指数和估计难多了

单变量指数和估计有指数对方法&#xff08;1933年英国人E.Phillips创造&#xff09;&#xff0c;印度人B.R.Srinivasan在1960年代搞出的二重指数对理论&#xff08;发表在 Math.Ann.)&#xff0c;由于没用二变量同步的Weyl不等式&#xff0c;是很肤浅的&#xff0c;而且1988年德…

收藏:相当大赞的来自 Agilean产品团队的2篇关于重塑敏捷组织的绩效管理的文章

Agilean产品团队&#xff0c;是吴穹博士领导下最近在国内敏捷界很厉害的产品&#xff0c;今天看到两篇相当不错的说敏捷组织的上下篇文章&#xff0c;分享下&#xff0c;地址是&#xff1a;6个原则15项举措&#xff0c;重塑敏捷组织的绩效管理&#xff08;上&#xff09; 6个原…

星宸科技SSC8826Q 驾驶辅助(ADAS)行车记录仪方案

星宸科技SSC8826Q 驾驶辅助&#xff08;ADAS&#xff09;行车记录仪方案 一、方案描述 SSC8826Q是高度集成的行车记录仪、流媒体后视镜解决方案&#xff0c;主芯片为ARM Cortex A53&#xff0c;dual core&#xff0c;主频高达1.2GHz&#xff0c;集成了64-bit dual-core RISC 处…

Windows 版Oracle 数据库(安装)详细过程

首先到官网上去下载oracle64位的安装程序 第一步&#xff1a;将两个datebase文件夹解压到同一目录中。 当下载完成后,它里面是两个文件夹 win64_11gR2_database_1of2, win64_11gR2_database_2of2,我们需要把其中的一个database文件夹整合在一起(复制一个database文件夹到另一…

如何有效的向 AI 提问 ?

目录 〇、导言 一、Base LLM 与 Instruction Tuned LLM 二、如何提出有效的问题 &#xff1f; 1. 明确问题&#xff1a; 2. 简明扼要&#xff1a; 3. 避免二义性&#xff1a; 4. 避免绝对化的问题&#xff1a; 5. 利用引导词&#xff1a; 6. 检查语法和拼写&#xff1…

哈希加密Python实现

一、代码 from cryptography.fernet import Fernet import os import bcrypt# 密钥管理和对称加密相关 def save_key_to_file(key: bytes, key_path: str):with open(key_path, wb) as file:file.write(key)def load_key_from_file(key_path: str) -> bytes:if not os.path…

【芯片设计- RTL 数字逻辑设计入门 7 -- 同步复位与异步复位详细介绍】

文章目录 复位的类型和划分同步复位综合后电路优缺点 异步复位优缺点 异步复位的时序分析&#xff08;recovery time/removal time&#xff09;异步复位&#xff0c;同步释放综合后电路优缺点 转自&#xff1a;https://blog.csdn.net/qq_40281783/article/details/128969188 复…

docker部署笔记系统flatnotes

效果 安装 创建目录 mkdir -p /opt/flatnotes/data && cd /opt/flatnotes/ chmod -R 777 /opt/flatnotes/ 创建并启动容器(可以自己修改账户和密码) docker run -d \ --restart unless-stopped \ --name flatnotes \ -p "10040:8080" \ -v "/dat…

JavaEE企业级应用软件开发—Spring框架入门学习笔记(一)

一、认识框架 实际开发中&#xff0c;随着业务的发展&#xff0c;软件系统变得越来越复杂&#xff0c;如果所有的软件都从底层功能开始开发&#xff0c;那将是一个漫长而繁琐的过程。此外&#xff0c;团队协作开发时&#xff0c;由于没有统一的调用规范&#xff0c;系统会出现大…

Unity类银河恶魔城学习记录3-4 EnemyBattleState P50

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Enemy.cs using System.Collections; using System.Collections.Generic; …

@ResponseBody

目录 概述 用途 使用案例 用 ResponseBody 设置返回值 概述 ResponseBody注解的作用是将方法返回的对象&#xff0c;通过适当的转换器(HttpMessageConverter)转换为指定的格式之后&#xff0c;写入到response对象的body区&#xff0c;通常用来返回JSON数据或者是XML数据 用…