最新要闻
- 淄博狂飙90天:烧烤降温流量下滑 大部分烧烤店不再需要排队|当前速看
- 跳河救人小哥说大家给我的太多了:我只是做了一件小事
- 95后小伙卖临期食品走红:极具性价比 也能防止浪费_天天视讯
- 余承东:除了华为和比亚迪 其他人活下来很难
- 焦点热议:小孩路边偷偷买猫 家长找商家退猫遭拒把猫摔死:网友看怒
- 83届奥斯卡获奖名单(关于83届奥斯卡获奖名单的基本详情介绍)-全球速递
- Rachio3控制用水量的智能庭院洒水器_全球最资讯
- 天天百事通!保时捷Mission_E原型车在纽伯格林上飞奔
- 一加Ace 2V大促:12+256不到2000元 无塑料支架 前沿资讯
- 大雾致航班取消 乘客骂哭机场员工
- 焦点速看:江苏常州:把惠企的公交车开到企业“家门口”
- 麻省理工学院开发出超吸水性水凝胶 具有巨大的应用潜力
- 为计划支持平稳过渡 谷歌千万域名将全部打包出售
- 网友将梅西亲笔签名纹在了手臂上 网友点评称将永远擦不掉
- 国产开放世界端游《仙剑世界》即将开启首测 研发时间超过两年
- 极兔速递正式向港交所提交上市申请书 2022年包裹量计为东南亚排名第一
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
rust 使用第三方库构建mini命令行工具
这是上一篇 rust 学习 - 构建 mini 命令行工具的续作,扩展增加一些 crate 库。这些基础库在以后的编程工作中会常用到,他们作为基架存在于项目中,解决项目中的某个问题。
(资料图)
项目示例还是以上一篇的工程为基础做调整修改ifun-grep 仓库地址
怎么去使用已发布的 crate 库
在开发ifun-grep
项目时,运行项目命令为cargo run -- hboot hello.txt
,测试项目的逻辑正确。在发布到crates.io
要如何使用呢,
在项目中使用
作为项目的一个功能函数,逻辑事务调用。在crates.io 中找到需要的库
安装已经发布的示例库ifun-grep
. 通过cargo add
添加依赖项
这里我们有一个测试示例项目rust-web
,这是在另一篇rust 基础中创建的示例项目。
$> cargo add ifun-grep
安装成功后,可以在在项目的Cargo.toml
看到依赖
[dependencies]ifun-grep = "0.1.0"
在main.rs
导入库使用,这个库包括了一个结构体Config
,三个方法find\find_insensitive\run
use ifun_grep;fn main(){ let search = String::from("let"); let config = ifun_grep::Config { search, file_path: String::from("hello.txt"), ignore_case: true, }; let result = ifun_grep::run(config); println!("{}", result.is_ok());}
执行cargo run
,可以看到输出了false
。因为文件hello.txt
不存在,在上一篇文中我们把错误处理统一放到了main.rs
文件中处理的。而我们这边作为一个 lib 库,直接调用的run
函数,所以这边没有任何的错误输出,只提示我们没有执行成功。
我们可以在项目目录下新建一个测试文件hello.txt
Let life be beautiful like summer flowers.The world has kissed my soul with its pain.Eyes are raining for her.you also miss the stars.
再次运行,可以看到打印的输出内容。Let life be beautiful like summer flowers.
可以通过cargo remove ifun-grep
从Cargo.toml
移除依赖
作为脚本命令执行
可以看到作为功能性函数调用时,只能手动去初始化函数调用。不能像执行命令一样,传递参数调用,也就不能执行main.rs
中的处理逻辑以及错误打印。
通过cargo install
安装二进制可执行文件的库
$> cargo install ifun-grep
安装完成后,就可以在全局环境中使用命令ifun-grep
了。
通过cargo uninstall ifun-grep
移除。
开发时如何测试使用
开发时只能cargo run
去执行main.rs
文件,不能直接使用ifun-grep
命令
可以通过cargo build
构建编译,在target/debug
下生成二进制文件
这样可以通过相对目录地址访问可执行文件执行命令
$> target/debug/ifun-grep Let hello.txt
如果我们的代码 存储在 github 或者 gitee 上,就可以将编译包压缩发布版本,这样需要的人不需要 cargo 就可以下载安装。
构建发布版本
$> cargo build --release
我的代码仓库在 giteeifun-grep 基础版本发布
下载压缩包后,需要把可执行文件配置到系统环境中,全局可用。也可以不用配置,直接使用文件路径地址执行命令。
还需要考虑一个问题,就是系统的兼容性,mac、windows、linux 等等,想要发布一个兼容的库,可能还需要针对性构建编译包并发布
这里演示的是 mac 系统下载发布包后,通过路径访问执行命令
clap
库解析 cli 参数
clap
库包含了对子命令、shell 完成和更好的帮助信息。
安装,参数--features
表示启动特定功能,
$> cargo add clap --features derive
clap
除了提供基础的功能之外,还可以通过--features
开启特定功能。derive
启动自定义派生功能,可以通过过程宏处理参数。
在src/main.rs
中使用
// use std::{env, process};use clap::Parser;use ifun_grep::{Config};fn main() { // let args: Vec = env::args().collect(); let config = Config::parse(); // let config = Config::build(&args).unwrap_or_else(|err| { // // println!("error occurred parseing args:{err}"); // eprintln!("error occurred parseing args:{err}"); // process::exit(1); // });}
结构体 Config
派生了一个内部函数parse
,可以直接解析参数生成实例 config
。
还需要修改src/lib.rs
,使得结构体 Config
用拥有这种能力
use clap::Parser;#[derive(Parser, Debug)]pub struct Config { #[arg(long)] pub search: String, #[arg(long)] pub file_path: String, #[arg(long)] pub ignore_case: bool,}
首先不再使用std::env
去解析 cli 参数,也不需要调用Config
的 build 方法去实例化创建 config。
通过clap::Parser
的过程式宏 Parser
去解析 cli 参数,并返回结构体Config
的实例 config
执行命令
$> cargo run
报错了,如图,首先这个错误信息很友好,告诉我们必填的参数信息
增加参数配置,调用命令执行
$> cargo run -- --search Let --file-path hello.txt
可以看到结果成功了,对比之前调用方式cargo run -- Let hello.txt
,多了一个参数名称定义--search
#[arg(long)]
参数宏是用来定义参数接受的标志,arg
还有许多其他的功能
移除掉#[arg(long)]
,执行命令 cargo run
use clap::Parser;#[derive(Parser, Debug)]pub struct Config { pub search: String, pub file_path: String, pub ignore_case: bool,}
报错了,thread "main" panicked at "Argument "ignore_case is positional, it must take a value
,意思是 ignore_case 必须要有一个值,ignore_case
是一个布尔值,隐式启动了#[arg(action = ArgAction::SetTrue)]
,所以需要设置接受标志
布尔值只需要通过设置标志,而不需要设置值,--ignore_case
就表示 true
use clap::Parser;pub struct Config { pub search: String, pub file_path: String, #[arg(short, long)] pub ignore_case: bool,}
再次执行命令cargo run
,
还需要必填的两个参数,此时不需要--
了
$> cargo run -- Let hello.txt
要想开启大小写不敏感,则需要增加--ignore-case
$> cargo run -- let hello.txt --ignore-case
需要注意的是结构体定义的下划线ignore_case
,在 clap 接受参数的标志为--ignore-case
增加命令的描述信息
通常 cli 的命令都有一个--help
功能,这可以基本说明这个脚本是干嘛的,以及怎么去使用
而这些 clap 正好有。测试一下,代码修改后需执行cargo build
$> target/debug/ifun-grep --help
可以看到对于ifun-grep
一个基本的使用方式,包括Usage、Arguments、Options
。还展示了对于结构体Config
的注释说明、例子。通过简写的-h
可以让描述更加紧凑一点。
clap 通过#[command()]
可以从Cargo.toml
获取到一些基础信息,生成 Command 实例
#[derive(Parser)]#[command(author, version, about, long_about = None)]pub struct Config { pub search: String, pub file_path: String, #[arg(short, long)] pub ignore_case: bool,}
编译后,执行--help
也可以自定义这些字段的值。
#[derive(Parser)]#[command(name = "ifun-grep")]#[command(author = "hboot ")]#[command(version = "0.2.0")]#[command(about="A simple fake grep",long_about=None)]pub struct Config { pub search: String, pub file_path: String, #[arg(short, long)] pub ignore_case: bool,}
通过执行ifun-grep -V
可以查看设置的name、version
信息
定义参数非必须
通过Option
定义字段数据类型,使得这个字段非必须
#[derive(Parser)]pub struct Config { name: Option,}
通过--help
查看参数是,必须的Arguments:
参数是
使用尖括号的;而非必须的是中括号[name]
.
如果某个参数可以接受多个,则通过集合定义类型
#[derive(Parser)]pub struct Config { name: Vec,}
在命令执行多余的参数会解析到字段 name 中。隐式的启动了#[arg(action = ArgAction::Set)]
,处理多个值。
使用标志命名参数
在之前的实例中,已经使用了#[arg(short, long)]
,它用来标识参数名称,它可以:
- 意图表达更明确
- 不用在意参数的顺序
- 使参数变的可选
#[derive(Parser)]pub struct Config { #[arg(short, long)] pub search: String, #[arg(short, long)] pub file_path: String, #[arg(short, long)] pub ignore_case: bool,}
可以通过--help
查看变化,所有的参数都变成了Options
子命令
在执行ifun-grep
时,携带子命令执行。通过#[derive(Subcommand)]
标志属性,子命令也可以有自己的版本、作者信息、参数等等
use clap::{Args, Parser, Subcommand};#[derive(Parser)]pub struct Config { #[arg(short, long)] pub search: String, #[arg(short, long)] pub file_path: String, #[arg(short, long)] pub ignore_case: bool, #[command(subcommand)] pub command: Commands,}#[derive(Subcommand)]pub enum Commands { Add(AddArgs),}#[derive(Args)]pub struct AddArgs { name: Option,}
默认值
可以通过#[arg(default_value_t)]
定义默认值,定义字段file_path
默认值
#[derive(Parser)]pub struct Config { #[arg(short, long)] pub search: String, #[arg(short, long, default_value = "hello.txt")] pub file_path: String, #[arg(short, long)] pub ignore_case: bool,}
调用命令执行时,可以不在设置该字段
$> target/debug/ifun-grep -s Let
命令执行是查询成功的.
其他的功能比如:数据校验、自定义值解析逻辑、自定义校验等等。
anyhow
处理错误
提供了一种错误类型anyhow::Error
. 处理出现的错误。
之前处理文件读取的逻辑,使用了?
pub fn run(config: Config) -> Result<(), Box> { let content = fs::read_to_string(config.file_path)?; Ok(())}
当文件不存在时,会打印出错误信息something error:No such file or directory (os error 2)
.但不知道具体哪个文件不存在。
可以通过自定义错误类型IfunError
,来构建自己的错误信息
#[derive(Debug)]pub struct IfunError(String);pub fn run(config: Config) -> Result<(), IfunError> { let file_path = config.file_path.clone(); let content = fs::read_to_string(config.file_path) .map_err(|err| IfunError(format!("could not read file {} - {}", file_path, err)))?; // ... Ok(())}
再次执行访问不存在的文件,报错信息为something error:IfunError("could not read file 1.txt - No such file or directory (os error 2)")
而anyhow
正好做了事情,可以通过 anyhow 的特征context
可以附加错误内容信息,也保留了原始错误。
安装 crate anyhow
库
$> cargo add anyhow
调整处理读取文件的函数run
,在src/lib.rs
文件中修改:
use anyhow::{Context, Result};pub fn run(config: Config) -> Result<()> { let file_path = config.file_path.clone(); let content = fs::read_to_string(config.file_path) .with_context(|| format!("could not read file {}", file_path))?; // ... Ok(())}
还需要修改src/main.rs
文件,将错误输出方式改为{:?}
fn main() { // ... if let Err(e) = run(config) { // println!("something error:{e}"); eprintln!("something error:{:?}", e); process::exit(1); }}
再次执行命令,可以看到错误更加的友好。
使用anyhow!()
宏,输出错误信息
在src/main.rs
,读取文件之前增加错误输出
fn main(){ // ... println!("{}", anyhow!("anyhow error {}", "running")); //...}
使用bail!()
宏,中断执行
调用执行返回错误,中断程序执行
在src/main.rs
,读取文件之前增加错误输出
use anyhow::{anyhow, bail};fn main() -> Result<(), anyhow::Error> { // ... println!("{}", anyhow!("anyhow error {}", "running")); bail!("permission denied for accessing {}", config.file_path) //...}
调用bail!
时,返回值必须是Result<(), anyhow::Error>
类型
bail!
同等于return Err(anyhow!())
跟踪错误栈
打印出错误信息,我们可以知道发生了错误,想知道是哪个文件、那行代码发生的错误,则需要开启错误栈追踪。
这是一个特性功能,需要指定特性启用
$> cargo add anyhow --features backtrace
然后通过设置环境变量,
RUST_BACKTRACE=1
panics
和 error 都有错误栈输出RUST_LIB_BACKTRACE=1
仅打开错误输出RUST_BACKTRACE=1
和RUST_LIB_BACKTRACE=0
仅 panic 时
在执行命令时,设置环境变量,打开错误输出时的错误追踪
$> RUST_LIB_BACKTRACE=1 cargo run -- -s let -f 1.txt
thiserror
自定义自己的错误类型
与anyhow
不同,thiserror
可以用来自定义错误类型。
通过过程式宏#[derive(Error)]
,它是由 std::error::Error
派生而来。
$> cargo add thiserror
定义一个文件不能存在的错误类型,并用于读取文件时的逻辑
use thiserror::Error;#[derive(Error, Debug)]pub enum IfunError { #[error("the file is"t exist")] FileNotExist(#[from] std::io::Error),}pub fn run(config: Config) -> Result<(), IfunError> { let content = fs::read_to_string(config.file_path)?; // ... Ok(())}
执行命令,访问不存在的文件。错误信息输出会被自定义的类型包裹:
ansi_term
更好的打印输出
ansi_term
控制台上的打印输出,包括字体样式、格式化。
安装
$> cargo add ansi_term
包括对文本的字体颜色、背景色、是否加粗、是否闪烁等等。
通过ansi_term::Colour
控制字体样式
我们将ifun-grep
的 参数打印使用颜色标记输出
use ansi_term::Colour::{Green, Yellow};fn main(){ //... println!( "will search {} in {}", Green.paint(&config.search), Yellow.paint(&config.file_path) );}
执行命令cargo run -- -s Let -f hello.txt
加粗bold()
、加下划线underline()
、背景色on()
等
use ansi_term::Colour::{Green, Yellow};fn main(){ //... println!( "will search {} in {}", Green.bold().paint(&config.search), Yellow.underline().paint(&config.file_path) );}
给程序查询出的行数据加背景色、闪烁
use ansi_term::Colour::{Red, Yellow};pub fn run(config: Config) -> Result<(), anyhow::Error> { //... for line in result { println!("{}", Red.on(Yellow).blink().paint(line)); } Ok(())}
通过ansi_term::Style
控制样式
Colour
是一个枚举类型,专门针对颜色样式处理;Style
是结构体类型,是字体样式的集合。
设置字体颜色,结构体需要实例化一个实例对象,然后再调用对应的方法。
use ansi_term::Colour::{Green, Yellow};use ansi_term::Style;fn main(){ //... println!( "will search {} in {}", Green.bold().paint(&config.search), // Yellow.underline().paint(&config.file_path) Style::new().fg(Yellow).paint(&config.file_path) );}
颜色扩展ansi_term::Colour::Fixed
除了内置枚举的颜色,还可以通过色码值设置颜色。0-255
use ansi_term::Colour::Fixed;Fixed(154).paint("other color");
也可以通过ansi_term::Colour::RGB
,设置三个不同的值
use ansi_term::Colour::RGB;RGB(154, 56, 178).paint("other color");
此外还有内置ANSIStrings
类型,可以通过to_string()
方法转换为String
;
支持格式化输出\[u8]
字节字符串,对于不知道编码的文本输出很有用。会生成ANSIByteString
类型,通过write_to
方法写入输出流中。
Green.paint("ansi_term".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
indicatif
展示进度条
处理任务时,显示任务的执行进度。会让人感觉良好,更有耐心等待执行完毕
$> cargo add indicatif
手动创建一个进度条,为了看到进度条的进度效果,可以使用std::thred
线程休眠一段时间。
use indicatif::ProgressBar;use std::{thread, time};fn main(){ let bar = ProgressBar::new(100); let ten_millis = time::Duration::from_millis(10); for _ in 0..100 { bar.inc(1); thread::sleep(ten_millis); // ... } bar.finish();}
通过ProgressBar
类型创建了一个进度条的实例对象,然后通过实例bar.inc()
逐步增加进度。完成后调用bar.finish()
表示进度完成,并保留显示进度信息。
也支持多进度条的MultiProgress
log
日志记录
一个程序运行时期的日志打印,非常重要,这对于运行监测喝解决有问题都有很到的帮助。
$> cargo add log
通常可以将日志按照登记划分,比如错误、警告、信息等。还需要一个日志输出的适配器 env_logger
,可以将日志写入终端、日志服务器等。
$> cargo add env_logger
美化输出,将接受到的参数作为信息info!()
输出,将产生的错误使用error!()
输出
env_logger
默认输出日志到终端,
use log;fn main() { env_logger::init(); // ... log::info!( "will search {} in {}", Green.bold().paint(&config.search), Style::new().fg(Yellow).paint(&config.file_path) ); // ... if let Err(e) = run(config) { log::error!("something error:{:?}", e); process::exit(1); }}
必须在程序之前初始化完毕日志环境变量配置。默认只展示error
错误类型的日志
执行cargo run -- -s Let -f 1.txt
命令访问不存在的文件,可以看到只有 error 错误输出打印。
通过设置变量RUST_LOG=info
,查看
$> RUST_LOG=info cargo run -- -s Let -f 1.txt
初始化指定信息类型
在执行命令前加上RUST_LOG=info
很麻烦,有遗忘的可能,可以通过初始化env_logger::init()
调用时,设定一个默认值
use env_logger::Env;fn mian(){ env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); // ...}
通过终端设置的变量优先级比默认值高,可以通过执行时设置变量覆盖默认值。
自定义输出模板
可以看到默认的输出打印包括了时间、类型以及模块名。可以通过改变模板自定义输出格式
use std::io::Write;fn main(){ env_logger::builder() .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args())) .init();}
输出格式改变为信息类型 - 信息
。使用默认的挺好,现在好多编辑器的日志输出都是这种格式。
测试
之前的单元测试示例都是和逻辑代码放在一起的,并用#[test]
注释。可以将这些测试放在tests
目录中
新建tests/lib.rs
用于存放单元测试用例。
use ifun_grep::{find, find_insensitive};#[test]fn case_sensitive() { let search = "rust"; let content = "\nice. rustI"m hboot.hello world.Rust"; assert_eq!(vec!["nice. rust"], find(search, content));}#[test]fn case_insensitive() { let search = "rust"; let content = "\nice. rustI"m hboot.hello world.Rust"; assert_eq!( vec!["nice. rust", "Rust"], find_insensitive(search, content) );}
通过借助第三饭库来使得测试更容易,
assert_cmd
可以处理结果进行断言;也可以测试调用命令进行测试。一起配合使用的还有predicates
用来断言布尔值类型结果值
因为测试示例只在开发阶段需要,则在安装时加参数--dev
$> cargo add assert_cmd predicates --dev
新增一个处理文件不存在的的测试示例。日志打印输出时会包含有could not read file
字符串。
use assert_cmd::prelude::*;use ifun_grep::{find, find_insensitive};use predicates::prelude::*;use std::{error::Error, process::Command};#[test]fn file_doesnt_exist() -> Result<(), Box> { let mut cmd = Command::cargo_bin("ifun-grep")?; cmd.arg("-s let").arg("-f 1.txt"); cmd.assert() .failure() .stderr(predicate::str::contains("could not read file")); Ok(())}
通过运行cargo test
,测试示例是运行成功的。
assert_fs
用于测试文件系统的断言
刚才测试了文件不存在的错误输出,还需要增加文件存在的测试,并写入内容。
$> cargo add assert_fs --dev
生成要测试的文件;断言测试生成的文件。tests/lib.rs
增加测试用例
use assert_cmd::prelude::*;use assert_fs::prelude::*;use ifun_grep::{find, find_insensitive};use predicates::prelude::*;use std::{error::Error, process::Command};#[test]fn file_content_exist() -> Result<(), Box> { let file = assert_fs::NamedTempFile::new("1.txt")?; file.write_str("hello world \n Rust-web \n good luck for you!")?; let mut cmd = Command::cargo_bin("ifun-grep")?; cmd.arg("-s good").arg("-f").arg(file.path()); cmd.assert() .success() .stderr(predicate::str::contains("good luck for you!")); Ok(())}
这样书写的单元测试用例更能直接、明了。和实际使用ifun-grep
时同样的命令操作,而不是使用开发时运行cargo run
关键词:
rust 使用第三方库构建mini命令行工具
spring-boot 项目 使用总结
淄博狂飙90天:烧烤降温流量下滑 大部分烧烤店不再需要排队|当前速看
跳河救人小哥说大家给我的太多了:我只是做了一件小事
95后小伙卖临期食品走红:极具性价比 也能防止浪费_天天视讯
余承东:除了华为和比亚迪 其他人活下来很难
焦点热议:小孩路边偷偷买猫 家长找商家退猫遭拒把猫摔死:网友看怒
83届奥斯卡获奖名单(关于83届奥斯卡获奖名单的基本详情介绍)-全球速递
Rachio3控制用水量的智能庭院洒水器_全球最资讯
【全球新视野】Linux批量文件操作——基于find-xargs
安全攻击溯源-钓鱼邮件溯源 环球滚动
天天百事通!保时捷Mission_E原型车在纽伯格林上飞奔
一加Ace 2V大促:12+256不到2000元 无塑料支架 前沿资讯
大雾致航班取消 乘客骂哭机场员工
焦点速看:江苏常州:把惠企的公交车开到企业“家门口”
环球动态:08. centos安装包方式安装nginx(推荐该方式)
nas docker安装mysql 整理
麻省理工学院开发出超吸水性水凝胶 具有巨大的应用潜力
为计划支持平稳过渡 谷歌千万域名将全部打包出售
网友将梅西亲笔签名纹在了手臂上 网友点评称将永远擦不掉
国产开放世界端游《仙剑世界》即将开启首测 研发时间超过两年
极兔速递正式向港交所提交上市申请书 2022年包裹量计为东南亚排名第一
山东一高校为毕业生举行别有滋味的龙虾宴 引发网友羡慕嫉妒
2023端午档期预售票房突破1000万 王宝强新作《八角笼中》备受期待
医生发现一男子是正常人骨密度的8倍 车祸后毫发无损
媒体曝光C罗与乔治娜曾达成“婚前协议” 若分手女友每个月可获10万欧元补贴
北方多地迎来高温天气 网友在线表演无火煎蛋
《永劫无间》胡桃1/4限量收藏级雕像即将上线 引入全彩3D仿真眼球
百度旗下萝卜快跑开展L4级无人驾驶商业化收费运营 运营时间覆盖早晚高峰
研究结果显示土星发现高浓度磷元素存在 为构成生命的六大基本元素之一
热心市民无意捡到石头竟是新石器时代遗存文物 具有不小的研究价值
快资讯:自研认知大模型 理想汽车带来“一员”真正的家庭成员
理想汽车发布城市NOA:不依赖高精地图 驾驶技术接近人类司机_全球微资讯
双黄蛋!胡歌大鹏获上海电影节影帝|当前快播
苏翊鸣回应获得清华大学保送资格消息 称未来四年将更加努力
因云南昭通突降暴雨引发山洪 135名初三学生的身份证被冲走
因影响公共秩序 冲场拥抱梅西球迷1年内被禁入赛场观看同类比赛
韩国人气女星宋慧乔全新短片曝光 身穿白色衬衫搭配咖啡色长裙且气质优雅
防治荒漠化能有多少种可能?来看看这份“中国良方”_速看料
英特尔将在波兰建造全新半导体组装和测试设施 现等待欧盟委员会批准
深圳邮局海关发现23只活体蜈蚣 其毒腺可分泌出大量毒液
环球看热讯:杀疯了!折叠屏不到4000 moto razr 40明天预售
充电进入5G时代 理想公布800V快充:充电9分半续航400公里-世界快资讯
阴阳师物语vivibear_阴阳师物语-微速讯
世界速递!【MathJax】语法总结
k8s 深入篇———— docker 是什么[一] 全球信息
英伟达RTX 40系列公版显卡今晚20点开抢:3199-12999元
售价超200万的FF 91又鸽了 贾跃亭造车梦何时能成?还差得远!
别人家的学校你羡慕了吗?山东一高校请近300名毕业生吃龙虾宴 环球即时看
618买笔记本电脑!教你看懂屏幕参数
埃安2024款AION V Plus将于6月20日上市:买五座送三排-当前热闻
图片报:拜仁关注哈弗茨,若无缘其他目标图赫尔能设想签他踢前锋
Lua 中如何实现继承
女子买1根牛肉干店员偷塞5根的量 当事人:特别气愤
世界今头条!六个口味 八喜冰淇淋3.8元/杯抄底(商超8元)
堆料不留遗憾的满血顶级非公旗舰!索泰RTX 4090 PGF OC评测:当之无愧新一代卡皇-世界头条
银河证券:通信+新基建板块有望率先预期上修 高景气度结合低估值是选股重点方向
记录--封装一个通过js调用的全局vue组件
世界讯息:Linux下常用命令
vim敲字如弹琴
我找到了阅读GitHub项目源码的最佳姿势,太舒服了!
世界短讯!玩游戏怎么选显示器?认准这几点准没错
男子发现捡回家两年的石头是文物 已无偿捐赠:网友惊叹
全球热推荐:国产GPU能否满足ChatGPT算力要求 景嘉微回应来了:还不行
环球观焦点:今年“蒸煮模式”咋提前了?专家解读
长城汽车给理想汽车起了个外号:“微博之王” 李想本人回应亮了 世界微动态
易宝支付总裁余晨出席《通用人工智能》新书发布会
腾讯太狠:40亿QQ号, 给你1G内存,怎么去重?
天天热点评!ASP.NET Core MVC 从入门到精通之Identity入门
世界今热点:对建造清代故宫影响最大的工匠,原来是这一家人!
合资品牌的无奈!奥迪之后丰田挂牌:我们也有纯电动请往里进
苹果Mac OS被指碰瓷WinXP经典壁纸:还真不是玩笑
世界快资讯:年轻人压力较大 乘联会崔东树:中国车市还得指望中老年人
又一新能源车企被申请破产!曾被称为“四小龙”之一
珠碱商品报价动态(2023-06-17)
看点:只需4年 PCIe 7.0硬盘有望追上DDR5内存:性能狂飙
人不在学校却被抬到校长面前拨穗 全场欢呼鼓掌:不想让舍友留下遗憾
嫌榴莲太臭?可它这3个好处“香”到不行!
《闪电侠》豆瓣8分:超七成观众给出4星以上好评
生来上等命,前有贵人,后有靠山,注定好运不断的星座,日后必成大器
3999元起 蔚来天穹车尾帐发布:10分钟快速搭建“一室一厅”
腾讯、网易游戏公布端午未成年人限玩时间:高考后准大学生仍被限
天天快看:中国车第一次!领克03高性能特别版首发:原厂防滚架可上路
酷睿i9-13700H VS.锐龙9 7940H全面对比:AMD仍有很长的路要走
天天热推荐:布林肯冀访华改善中美沟通避免引发冲突 中方促美尊重核心关切
今日热门!分心驾驶致5人身亡 家属质疑10个气囊全未弹开 丰田销售:后方撞击不能触发
深圳邮局海关查获23只外来毒虫!内含秘鲁巨人蜈蚣 天天通讯
宣布对西安工厂投资43亿元:消息称美光也要向印度投资10亿美元
韩方曝出:福岛核污水超标2万倍
比小米便宜一半!TCL雷鸟Mini LED电视85英寸只要7599元 焦点简讯
理想L7/8/9魔毯空气悬挂2.0实测:防刹车点头来了 _环球滚动
GPT-4满分通过MIT本科数学考试!这套提示词火了
看热讯:10万出头续航505km 江淮钇为3上市:打的就是比亚迪海豚
不靠高精地图!小鹏汽车演示北京无图区智能辅助驾驶:稳如老司机_全球今亮点
Android-JNI开发概论-动态
鲍威尔_1937~_关于鲍威尔_1937~简述_消息
全球今日讯!华为NCA智能驾驶来了!余承东:超越特斯拉FSD 这15个城市率先体验
vivo X90s跑分出炉:165万安卓性能天花板!领先20万-全球实时
从泰山弃将到亚泰宠儿,莱昂纳多逆袭霸榜,机会总留给有准备的人-每日速递
软件开发人员必须阅读的20本书_每日速看