LZ 是一名在职的 Java boy ,花了上周一周的时间入门了 Rust 。周末使用 axum 写了个 web 项目,模拟了 SpringMVC 的架构。
均在我 mac 笔记本中进行测试
这里可能不太公平。
Java 项目用了我之前的开源项目,虽然是个完整的项目但是也不是很大。没有打包成 jar ,使用 idea 启动,通过活动检测器根据 pid 查找发现占用内存494.2MB,JVM 配置:-Xms256m -Xmx4g 。
Rust 启动后发现内存占用为 2.0MB!!! 我人都傻了,虽然说是个很简单的项目,但是项目中必要的功能都有。
为了进一步的看到差距,我开始了压测,代码如下。为了减少变量,没有加入 IO 操作,但也是正常的业务功能。
JAVA
@Override public AiUserVO loginTest(AiUserReq userReq) { CommonUtils.checkArgs(userReq.getAccountNo(),userReq.getPassword()); AiUser user = AiUser.builder().accountNo("admin").password("admin").name("admin").build(); user.setId(1941040891798581249L); //校验登录 // checkLogin(user,userReq); AiUserVO result = ConvertUtils.beanProcess(user, AiUserVO.class); //处理用户角色 // processUserRole(user,result); //生成 token String token = genToken(user); result.setToken(token); //放入 redis String key = CacheKeyEnum.format(CacheKeyEnum.ADMIN_LOGIN_KEY,user.getId(),token); SysCacheUserDto sysCacheUserDto = ConvertUtils.beanProcess(result, SysCacheUserDto.class); //删除原始 token // removeToken(user.getId()); // redisCacheComponent.set(key,JSONObject.toJSONString(sysCacheUserDto),TimeConstant.ONE_DAY * 12); return result; }
RUST
pub async fn login(user:UserReq)->Res<UserVO> { // 查询逻辑 let user_do = match query_user(&user.account_no, &user.password).await { Some(user_do) => user_do, NOne=> return Res::build(FAIL), }; let mut user_vo:UserVO = user_do.into(); //加密 let token = match security_utils::aes_encrypt(&user_vo.id.to_string()) { Ok(token) => token, Err(_) => return Res::build(FAIL), }; user_vo.token = token; let key = SYSTEM_USER.key().format(&[&user_vo.id.to_string()]); //删除缓存 GlobalCache::del(&key); //放入缓存 GlobalCache::set(key,serde_json::to_string(&user_vo).unwrap()); Res::success(user_vo) } /** * 查询用户 */ async fn query_user(account_no:&str,pwd:&str)->Option<UserDO> { let user = UserDO{ id:1912753992656158721, name:"admin".to_string(), account_no:"admin".to_string(), status:true, }; Some(user) }
压测配置如下
Name: 线程组-30 Number of Threads: 200 Ramp-Up Period: 30 Loop Count: 1 Scheduler: Duration: 90 Name: 线程组-90 Number of Threads: 200 Ramp-Up Period: 30 Loop Count: 1 Scheduler: Startup Delay: 90 Duration: 90
压测流程如下
阶段一:0~30 秒启动 200 线程 → 持续到第 90 秒 阶段二:从第 90 秒开始,30 秒内启动 300 线程 → 持续到第 180 秒
指标 | RUST | JAVA | 差异 |
---|---|---|---|
平均响应时间 | 3~4 ms | 6~8 ms | ↑ 上升 50%~100% |
最大响应时间 | 17 ms | 26 ms | ↑ 上升 53% |
99% 百分位 | 11~15 ms | 15~20 ms | ↑ 上升 30%~45% |
吞吐量 | 6.7 → 10.0 req/sec | 6.7 → 10.0 req/sec | ✅ 相同 |
异常率 | 0% | 0% | ✅ 相同 |
数据包大小 | 294 B | 489 B | ↑ 增加 66% |
想起它骨子里的坚定,克制,却又锋利
我敬畏,但也安心
它有清晰的边界感,每一个指针都有归属,每一次借用都遵循秩序
它不给我侥幸,却给我前所未有的安全
它的世界里没有野蛮的随意,没有未定义的空洞,只有规则下的极致自由
它能在不失控的前提下奔跑到极限,并发如风,却稳若磐石
Rust ,我想你了
]]>https://github.com/auv-sh/avav
av top av list avavavaavavavavavavavavavavavavavavavaavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavavavaavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavavavaavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavavvavavavavavavavav
]]>详情见: https://github.com/chunhuitrue/nsave
Nsave 是一个抓取并保存数据包的工具。它持续不断地抓取数据包,并保存到本地。可以根据条件查询链接、数据包并导出成 pcap 文件。可以通过 pcap 或者 af_xdp 来捕获数据包。主要特点是它不基于单个数据包,而是基于流来作索引,可以大幅减少索引所占的磁盘空间。
WASM 计算器 - 使用 WebAssembly 和 Rust 技术构建的高性能在线计算器应用,支持基础运算、百分比计算,界面美观,运行速度快,是您日常计算的理想选择。
地址👉: 在线地址
学习 wasm 的练手项目,新手上路,轻拍
]]>使用软件的人,应该不太关心软件使用什么语言开发的吧?
]]>667.3 = note: "cc" "-m64" "/tmp/rustcXFCL9g/symbols.o" "<1 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/tmp/rustcXFCL9g/{libv8-dbef52e4bc4b6f8f.rlib,libskia_bindings-279c509e56943a3f.rlib,libzstd_sys-356ea57c902a259b.rlib}.rlib" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-ldl" "-ldl" "-lssl" "-lcrypto" "-ldav1d" "-lstdc++" "-lfontconfig" "-lfreetype" "-lEGL" "-lGL" "-lwayland-egl" "-lGLESv2" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/usr/lib" "-L" "/usr/local/lib/x86_64-linux-gnu" "-L" "/home/app/target/release/build/skia-bindings-60ededebb9dd8e7e/out/skia" "-L" "/home/app/target/release/build/zstd-sys-e9bd7677eed9b254/out" "-L" "/home/app/target/release/gn_out/obj" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/app/target/release/deps/render_http-e7adb05509d015b0" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-Wl,--strip-debug" "-nodefaultlibs" 667.3 = note: some arguments are omitted. use `--verbose` to show all linker arguments 667.3 = note: /usr/bin/ld: /tmp/rustcXFCL9g/libskia_bindings-279c509e56943a3f.rlib(libicu.uloc.o): in function `ulocimp_getParent': 667.3 uloc.cpp:(.text.ulocimp_getParent+0x0): multiple definition of `ulocimp_getParent'; /tmp/rustcXFCL9g/libv8-dbef52e4bc4b6f8f.rlib(uloc.o):./../../../../third_party/icu/source/common/uloc.cpp:1685: first defined here 667.3 collect2: error: ld returned 1 exit status
有没有大佬提供帮助
]]>写到一半的时候发现还是有很多内容不熟悉,看文档的时候都知道是咋回事,真正自己上手写的时候就懵逼
这种感觉真的太受挫了!
]]>如果 web 项目用到 gRpc 的话,通过 protoc 创建的这些服务,只能通过 layer 贯穿到整个服务中吗??
那正常的一个项目假如有几十上百个服务的话,那不是这个.layer(Extension(Arc::new(model::AppState::new(cate, topic, tera)))); 会很臃肿,因为要把这几十上百个服务都累加进去?
]]>但是我正阻塞在该对象上进行读取,又怎么可能通过 drop 该对象来触发关闭呢?
请别告诉我要非阻塞调用,或者轮询调用,或者其他解决方案,我只是觉得接口这么设计我有点无法理解。
]]>models-cat 是 ModelScope Hub 的非官方 Rust 客户端,设计灵感来自 hf-hub。models-cat 源自一个简单的需求:“编写一个 Rust 桌面端 AI APP ,需要下载模型和数据集,但是没有合适的 Rust 客户端。”
什么时候需要 models-cat 下载模型?主要有三个原因:
顺便说下,ModelScope 托管模型真香,国内下载速度贼快、稳定、免费。
同步下载:
use models_cat::{download_model_with_progress, ProgressBarWrapper}; download_model_with_progress( "BAAI/bge-small-zh-v1.5", "model.safetensors", ProgressBarWrapper::default(), ).unwrap();
异步下载:
use models_cat::asynchronous::{download_model_with_progress, ProgressBarWrapper}; download_model_with_progress( "BAAI/bge-small-zh-v1.5", "model.safetensors", ProgressBarWrapper::default(), ).await.unwrap();
异步下载需开启特性tokio
特性:
models-cat = { version = "*", features = ["tokio"] }
从 ModelScope 的托管仓库 BAAI/bge-small-zh-v1.5 下载模型到本地,默认保存在[HOME_DIR].cache/modelscope/hub/models--BAAI--bge-small-zh-v1.5/
目录下。
使用快捷函数时,可通过环境变量MODELS_CAT_CACHE_DIR
设置本地缓存路径。或者使用ModelsCat
,在初始化时传入本地缓存路径。
pub async fn list( State(state): State<ArcAppState>, Query(frm): Query<form::subject::ListForAdmin>, ) -> Result<resp::JsonResp<model::subject::SubjectPaginate>> { let handler_name = "admin/subject/list"; let p = get_pool(&state); let subjects = model::subject::Subject::list( &*p, &model::subject::SubjectListFilter { pq: model::subject::SubjectPaginateReq { page: frm.pq.page(), page_size: frm.pq.page_size(), }, order: None, is_del: frm.is_del(), status: frm.status, name: frm.name, slug: frm.slug, }, ) .await .map_err(Error::from) .map_err(log_error(handler_name))?; Ok(resp::ok(subjects)) } #[derive(Debug, Default, Deserialize, Serialize, sqlx::FromRow, Db)] #[db(table = subjects, pk = id, del_field = is_del)] pub struct Subject { #[db(find)] #[db(skip_update)] pub id: String, #[db(list_opt)] #[db(list_opt_like)] pub name: String, #[db(find)] #[db(exists)] #[db(list_opt)] #[db(list_opt_like)] pub slug: String, pub summary: String, #[db(find_opt)] #[db(list_opt)] pub is_del: bool, pub cover: String, #[db(list_opt)] pub status: Status, pub price: Decimal, pub pin: i32, }
作为 Java 开发,看到这个 list 方法本能的想跳转过去看下这个 model::subject::Subject::list 方法的实现咋写的,但是跳转过去是宏? 那我咋知道最后是咋写的呢?
实在是懵逼~
]]>axum:web framwork sqlx:sqlboy
写着写着感觉用 rust 写 web 项目总感觉哪里味不对,一直在反思这 rust 写 web 应用真是适合吗?
就目前 orm 框架 sqlx 、seaorm 、diesel 都还在讨论哪个牛逼~
不像 Java ,mybatis 用起来那么爽~ 我既想要 orm 的字段映射到对象,也想要自定义查询的灵活~
]]>Client 是基于 reqwest 的分支,修复了 HTTP 版本协商问题,并增强了对 WebSocket ( HTTP1/HTTP2 )的支持,同时优化了常用 API 和连接池的性能。
完美模仿 Chrome/Safari/Firefox 的 TLS/HTTP2 指纹配置。
TLS 后端使用 BoringSSL ,该分支像 Golang utls 一样访问低级 TLS 配置功能,同时避免了 utls 的致命缺陷:utls issue #274。
HTTP2 后端在原 h2 分支基础上实现了对低级 Priority/Headers frame 及 pseudo-header
排列的访问。
salvo
和 axum
框架,并同时支持创建「单应用」和「多应用」 Cargo install yiirs
其实中说 FnOne 是至少调用一次。
还有 Rust 圣经中也同样这么说。 内容如下:
所有的闭包都自动实现了 FnOnce 特征,因此任何一个闭包都至少可以被调用一次
但 Kimi 的解释是:
FnOnce 的设计目标是确保闭包在调用时可以安全地消耗变量的所有权,而不是强制要求闭包必须被调用。换句话说:
“只能调用一次”:闭包被设计为只能调用一次,以避免多次调用导致的错误。 “至少调用一次”:这不是 FnOnce 的要求。闭包可以选择不被调用,但一旦调用,就不能再次调用。
大致意思就是“只能调用一次”
我的理解也是只能调用一次。
ps: 前几天看到有个推荐 Rust 教程的页面,说《 Rust 语言圣经》错误太多。我现在找不到出处了。请问有哪些是错误的?
]]>cargo build --target aarch64-unknown-linux-gnu -r
也试过 cargo 配置文件里加
[target.aarch64-unknown-linux-gnu] linker = "aarch64-linux-gnu-gcc" rustflags = ["-L", "/usr/lib/gcc/aarch64-linux-gnu/13.1.0/tmp/usr/lib/"]
都解决不了,放到 raspi 编译一次要很久。
]]>比如:
比较突出的特点是比同类的其他工具都更快,用起来也确实很明显。我自己主要用 C++/Python ,想拿 rust 业余玩下(主要也是做些自己用的命令行小工具吧)。有啥上手的小项目推荐吗?(上面几个粗略瞄了眼有点大)
]]>首先看书中图 5-9 的所有权树,讲了对于可变和不可变引用时的访问关系,我以为自己理解了,可是后面看到这个例子,结果又看不明白,代码是这样的:
... 也可以再次借用一个可变引用: let mut v = (136, 139); let m = &mut v; let m0 = &mut m.0; // ok:从可变引用重新借用可变引用 *m0 = 137; let r1 = &m.1; // ok:从可变引用重新借用共享引用,并且和 m0 没有重叠部分 v.1; // error:通过其他路经访问仍然是禁止的 println!("{}", r1); // r1 在这里使用
其实从第一个 ok 注释那里我就没搞明白,不是说变量只能同时存在一个可变引用吗,为什么有可变引用(“引用”为名词)m 的情况下还能从 m 那再可变引用(“引用”为动词)一个 m0 ?
然后我问 gpt ,它是这么回答的:
...
嵌套 mut 引用的场景
假设你有一个可变变量,并希望对其创建嵌套的可变引用。以下 是一些常见的情况及其分析。
情况 1:对整个变量的可变引用,然后尝试对部分值的可变引用
fn main() { let mut x = (1, 2); let r1 = &mut x; // 对整个变量 `x` 的可变引用 let r2 = &mut r1.0; // 尝试对 `x` 的一部分创建可变引用 *r2 = 42; // 修改部分值 r1.1 = 99; // 修改另一部分 }
错误原因: Rust 编译器会报错,提示 不能同时借用 x 的多个可变引用。这是因为:
r1 是对整个 x 的可变引用,它控制了 x 的独占访问权。 当你尝试对 r1.0 ( x 的某个字段)创建可变引用时,r1 的作用域依然活跃,Rust 无法区分你是否会同时操作 x 的其他部分。
错误示例的编译器消息(可能类似于):
error[E0499]: cannot borrow `r1.0` as mutable more than once at a time
...
但事实上,我尝试了类似代码,并不会报错:
fn main() { let mut v = (136, 139); let m = &mut v; let m0 = &mut m.0; *m0 = 137; m.1 = 42; println!("{:?}", v) }
其运行结果是:
(137, 42)
很多资料都没有讲解关于这种嵌套的引用会发生什么结果,也不知道什么情况是可以什么是不行,我没看过这例子时还以为压根不能创建 m0 呢,所以想着找 GPT 问问,结果告诉的内容是错的。
请问该如何解释上面书中的代码,如何更好地理解 Rust 在这种嵌套情况下创建引用的做法是否成功?请各位赐教
]]>// This function only gets compiled if the target OS is linux #[cfg(target_os = "linux")] fn 在跑 linux() { println!("你在跑 linux!"); } // And this function only gets compiled if the target OS is *not* linux #[cfg(not(target_os = "linux"))] fn 在跑 linux() { println!("你昧在跑 linux!"); } fn main() { 在跑 linux(); println!("确定?"); if cfg!(target_os = "linux") { println!("是。的确!"); } else { println!("是。不是!"); } }
]]>fn func_print(name: &str) { println!("Hello, {}!", name); } macro_rules! func_macro { ($name:expr) => { func_print($name); }; } fn main() { func_macro!("laozhu"); }
]]>闭包
fn add_one_v1 (x: u32) -> u32 { x + 1 } let add_one_v2 = |x: u32| -> u32 { x + 1 }; let add_one_v3 = |x| { x + 1 }; let add_one_v4 = |x| x + 1 ;
初看确实好理解,也能掌握,就算再加上
immutable 、mutable 、move 也能理解
但是再 加上边界 、FnOnce 、Fnmut 这些就给我整不会了,干懵逼了
impl<T> Option<T> { pub fn unwrap_or_else<F>(self, f: F) -> T where F: FnOnce() -> T { match self { Some(x) => x, NOne=> f(), } } }
我只想说 rust 是所有语言中把符号运用到极致的语言!
继续苟着看下去!
]]>这一套下来感觉比较麻烦, 有没有办法直接将这个第三方 package 嵌入我的 rust 工程? 能想到比较笨的办法是直接把这个库的源码拷贝进我的工程, 然后将它的 Cargo.toml 内容集成进我的配置文件, 它的源文件嵌入我的工程.但是这么修改破坏了原本的工程结构.
有没有这样一种办法, 以类似离线的方式引用这个库, 其它库还是在线引用, 但是这个离线库跟我自己的 rust 工程存在同一个 git 仓库, 这样我能方便修改库的代码. 相当于我的一个 git 仓库中存在 2 个独立的 rust 工程, 1 个是我的工具工程, 另一个是拷贝过来的 库 工程, 但是工具工程可以用 package 的方式引用这个库工程.
这么做可以快速把工具开发出来, 另一方面, 等库的原作者接受 PR 后, 也能方便把引用的库切换回去, 而不用调整工程结构, 只要把引用的 package 修改下, 然后从工程仓库删除修改后的 library 即可.
]]>目前了解到一个neon框架,但是社区看起来并不活跃,不知道有没有其他框架可以用?另外还有个问题就是依赖这些框架带来的维护成本会不会特别高?希望有相关实践的朋友指点一下,谢谢!
]]>#[warn(unused_parens)] fn main() { let mut a: u8 = 199; if (a > 2) // 改成 a <2 就正常了 { a += 199; } println!("{}", a); }
程序直接退出了。应该是运行时检测的,好奇是怎么实现的(如果加法都有判断的话,运行时怎么保持高性能),有木有大佬解释下?
]]>好多年前 iwannay 写了一款名为 jiacrontab 的任务调度软件,帮助到了一些同学; 开源有种魔力,总是激励着人走的更远,感谢每一位赞助过该项目的同学。
如果你是一位程序开发者,你希望能够把手头杂乱的定时任务管理起来,能够随时启动和停止,最好还能看到执行日志;
如果你是网站管理员,你希望有一个统一的 web 控制台可以管理各大云厂商的服务器,而不需要频繁切换不同的云厂商控制台去操作;
如果你是一位运维管理者,你希望有一个平台能够统一管理海量的运维脚本,实时的把各类型功能脚本推送到数以万计的实例上,并收到执行反馈;
如果你是一个自由职业者,你刚好在腾讯云买了台服务器,你想通过某个工具给家里的电脑安排一个任务,比如....;
嗯...,除了这些...
我还有一些特殊场景,我想把几个无关的任务串联起来,最好还能做些逻辑判断,比如我想先检查下我的服务器实例是否安装了 nginx ,如果没安装我就安装,安装了我就部署一个网站。最好这个流程可以开放为一个接口,我调用接口就完成了!
如果你有以上需求,jiascheduler 将是一个不错的选择。何况 jiascheduler 还提供了一个企业级的,及其好用 webssh 终端。这个要划重点。
请注意,部分功能会在后续版本实装
一个可以自动化执行的任务。
根据表现形式,可以是一个接口,一段 shell 脚本,一个可以执行的二进制命令
可以给作业添加执行计划,让作业按照预期的定时策略自动执行
根据业务场景的不同,往往需要将多个 job 组合编排为一个新的 job 。作业编排即根据不同条件,串行,并行的组合不同 job 为一个可以新 job 过程。
一个作业可以同时关联多个子任务,子任务作为批任务的形式存在,可以对批任务的输出进行自定义表达式校验,这个功能可用于巡检
在启动作业时,会选定关联的作业,和需要执行的节点,生成一份快照,这个操作被称为作业调度。我们可以根据调度记录,重新执行执行过的作业
可以实时的管理正在运行的作业,比如停止定时器,kill 进程,重新启动作业
操作便捷,功能强大,支持多页签,自定义主题,分屏,全屏,多会话批量命令,上传,下载
以上为 jiascheduler 的简单介绍,请关注 https://github.com/jiawesoft/jiascheduler 获取最新发布动态
]]>