Rust 笔记:Rust 语言中的字符串
作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343
邮箱 :291148484@163.com
本文地址:https://blog.csdn.net/qq_28550263/article/details/130876665
【介绍】:本文介绍 Rust 语言中的字符和字符串的用法。
目 录
- 1. 概述
- 2. Rust 的 字符 类型
- 3. 不可变字符串类型
str - 4. 可变字符串类型
String - 4.1 快速入门可变字符串 String
- 4.1.1 什么是可变字符串
- 4.1.2
String类型 与str类型的区别 - 4.1.3 如何创建
String - 通过使用 String::new 方法创建
- 通过使用 String::from 方法创建
- 通过
str类型的to_string方法创建 - 通过
format!宏创建
- 4.2
String用法解析 - 4.2.1 字符串拼接
- 4.2.2 字符串的切片
- 4.2.3 clone 方法拷贝字符串
- 4.2.4 trim 方法去除两端空白字符
- 4.2.5 chars 方法及其应用
- String 的 chars 方法
- 通过 chars 方法获取 字符串首字符
- 通过 chars 方法获取 字符串尾字符
- 通过 chars 方法获取 字符串的字符数
- 通过 chars 方法 反转字符串
- 4.2.6 to_uppercase 方法将字符串统一为大写字母形式
- 4.2.7 to_lowercase 方法将字符串统一为大写字母形式
- 4.2.8 len 方法获取字符串的长度
- 4.2.9 contains 方法判断字符串是否包含指定的子串
- 4.2.10 push 方法在字符串末尾添加单个字符
- 4.2.11 push_str 方法在字符串末尾添加字符串字面量
- 4.2.12 pop 方法移除字符串末尾的字符
- 4.2.13 remove 方法移除字符串指定为序处的字符
- 4.2.14 insert 方法在字符串指定位置插入内容
- 4.2.15 replace_range 方法替换字符串指定范围内的内容
- 4.2.16 truncate 方法截断字符串
- 4.2.17 clear 方法清空字符串的内容
- 4.2.18 字符串中使用转义符、原始字符串
- 字符串中使用转义符
- 原始字符串表示
- 4.3
format! 宏与 模板字符串的使用
1. 概述
本文介绍 Rust 语言中的 字符 和 字符串。在 Rust 语言中,不仅 字符 和 字符串 是不同的类型,并且还存在着 str 和 String 两种字符串。
Rust 中的字符类型是 char,它表示 Unicode 标量值,占用 4 个字节,而字符串类型是 str 和 String。str 类型是一种不可变的字符串类型,通常使用 &str 来表示,而 String 类型是一种可变的字符串类型,通常使用 String 来表示。
2. Rust 的 字符 类型
2.1 Rust 中的 字符(char)类型
2.1.1 char 类型的概念
Rust 的 char 类型是该语言最原始的字母类型。该类型 在 Rust 表示 Unicode 标量值,它占用 4 个字节,可以使用 单引号 来表示一个 char 类型的值,例如:
let a = 'a'; // 常规的 ASCII 字符
let b = '😎'; // Unicode 表情符号
let c = '\u{1F600}'; // 同样是 Unicode 表情符号,使用 Unicode 标量值表示
2.1.2 在 char 类型 里 使用 转义字符
现代高级语言中,如 C、JavaScript、Python,都使用 转义符 来表示一些特殊的字符, Rust 也不例外,其中的转义字符使用 反斜杠 (\)来表示,例如:
let a = '\n'; // 换行符
let b = '\t'; // 制表符
let c = '\''; // 单引号
由于反斜杠被用作 转义符,这意味着只有一个反斜杠表示的不是反斜杠自身,因此如果你要使用反斜杠,则加一个反斜杠对其进行转义,也就是:
let d = '\\'; // 反斜杠
在这一小节的例子中,我们使用的都是 单引号,可知这里的转义符针对的是 字符 类型。实际上 Rust 中,也可以将其用于 字符串 类型(在后面介绍)。
2.1.3 char 类型 与其它类型的转换
Rust 语言中提供了 as 关键字,与 TypeScript 中的 as 关键字仅仅是用于 类型断言 不同,在 Rust 语言中,as 的直接将 一个类型 转换为 另一个类型,而不仅仅是视作另一个类型。
因此我们可以通过 as 将 char 类型转换为 u8 类型,或者将 u8 类型转换为 char 类型:
let a = 'a';
let b = a as u8; // char 类型转换为 u8 类型
let c = b as char; // u8 类型转换为 char 类型
或者
let d = '😀';
let e = d as u32; // char 类型转换为 u32 类型
let f = e as char; // u32 类型转换为 char 类型
2.1.4 在字符(char)实例上提供的一些方法
我们可以调用 char 原生支持的一些方法,实现某些功能。
char 类型上用于判断的相关方法
| 方法 | 描述 |
|---|---|
is_ascii | 判断是否是 ASCII 字符 |
is_alphabetic | 判断是否是字母 |
is_digit | 判断是否是十进制数字 |
is_lowercase | 判断是否是小写字母 |
is_uppercase | 判断是否是大写字母 |
例如:
let a = 'A';
let m = a.is_ascii(); // 判断是否是 ASCII 字符
let n = a.is_alphabetic(); // 判断是否是字母
let o = a.is_digit(10); // 判断是否是十进制数字
let p = a.is_lowercase(); // 判断是否是小写字母
let q = a.is_uppercase(); // 判断是否是大写字母
char 类型上用于转换的相关方法
| 方法 | 描述 |
|---|---|
| to_ascii_lowercase | 转换为小写字母 |
| to_ascii_uppercase | 转换为大写字母 |
例如:
let c = 'C';
let l = c.to_ascii_lowercase(); // 转换为对应的小写字母 => c
let s = 's'
let u = s.to_ascii_uppercase(); // 转换为对应的大写字母 => S
2.2 从字符到字符串
2.2.1 什么是字符串
顾名思义,将一串字符穿在一起就形成了 字符串。字符串是非常重要的数据类型,因为它们可以用于表示文本数据,例如文件内容、用户输入、网络数据等等。现实生活中的文本、句子都需要使用字符串而不是单个字符进行表示。
字符串还可以用于格式化输出,例如将数字转换为字符串,或将字符串转换为数字。
在Rust语言中,str类型的 字符串是一种不可变的数据类型,用于表示文本数据。字符串是 由字符组成的序列。str类型是一种不可变的字符串类型,通常使用&str来表示。String类型是一种可变的字符串类型,通常使用String来表示。
2.2.2 字符 和 字符串的异同
在 Rust 语言中,字符和字符串相比:
- 字符类型(char)是单个字符,而 字符串 (str、String)是多个字符 组成的序列;
- 字符类型(char)是不可变的,String 类型的字符串类型可以是可变的;
- 字符类型通常使用 单引号表示,字符串类型通常使用 双引号 或者S tring::from方法 创建;
- 字符 和 字符串 类型 都可以 使用一些特殊的 转义字符,如换行符、制表符等,字符串类型也支持这些转义字符。
- 字符 类型 支持的一些方法,如 is_ascii、is_alphabetic、is_digit,同样在字符串中也支持。
3. 不可变字符串类型 str
3.1 str 类型概述
在 Rust 语言中,str 类型 是一种不可变的字符串类型,通常使用 &str 来表示。创建 str 类型 的方法有很多,比如最简单的就是使用 双引号语法,该方法可以非常方便地创建 str 字面量:
let s1 = "hello world!"; // 直接使用字符串字面量创建
let s2: &str = "hello"; // 使用类型注解创建
str 也可以是通过可变字符串 String转换来的:
let s3 = String::from("world").as_str(); // 使用 String 类型的 as_str 方法创建
或者使用可变字符串 String 类型的引用创建不可变字符串 str 类型地字面量:
let s4 = &String::from("world"); // 使用 String 类型的引用创建
3.2 不可变字符串str的特点
3.2.1 不可变字符串str的优点
不可变字符串具有以下有点
- 安全性高:不可变字符串不会被意外修改,避免了一些潜在的错误。
- 性能高:不可变字符串的内存布局更加紧凑,访问速度更快。
3.2.2 不可变字符串str的不足
不可变字符串也有一些不足,比如:
- 不可变字符串无法修改,需要重新创建一个新的字符串来实现修改操作,会占用更多的内存空间。
- 不可变字符串无法直接拼接,需要使用 format! 宏 或者 String::from 方法来实现。
3.2.3 如何选用 字符串str
一般以下,可以参考以下建议选择字符串:
- 字符串不需要修改时,选用不可变字符串 str ,这样更加 安全 和 高效;
- 反之,字符串需要修改时,选用可变字符串 String。
3.3 如何判断一个值的类型为str
判断一个值是否是 str 类型可以使用类型判断语法:
fn is_str(s: &dyn std::any::Any) -> bool {s.is::<&str>()
}
例如:
let s1 = "hello";
let s2 = String::from("world");
let s3 = 123;
let s4 = vec![1, 2, 3];println!("{}", is_str(&s1)); // true
println!("{}", is_str(&s2)); // false
println!("{}", is_str(&s3)); // false
println!("{}", is_str(&s4)); // false
4. 可变字符串类型 String
4.1 快速入门可变字符串 String
4.1.1 什么是可变字符串
可变字符串的 可变 是相对于不可变字符串而言的,我们上一节使用字面量语法创建的字符串已经创建就不可以修改了,因而称之为不可变字符串。
换而言之,可变字符串的可变指的是字符串的内容可以被修改。例如,使用 push_str 方法可以在字符串末尾添加字符串字面量:
let mut s1 = String::from("hello");
s1.push_str(", world!"); // 在字符串末尾添加字符串字面量
println!("{}", s1); // 输出:hello, world!
可以看到,通过这样的方法,使得字符串的内容发生了变化。类似的方法还有很多,请参考 4.2 String 方法解析 部分。
4.1.2 String 类型 与 str 类型的区别
- str 类型是不可变的,而 String 类型是可变的。
- str 类型通常用于函数参数和返回值,而 String 类型通常用于变量和常量。
- str 类型通常使用 字符串字面量 创建,而 String 类型通常使用 String::from 方法 创建。关于创建 String 的方法,请参考下一小节
4.1.3 如何创建String
通过使用 String::new 方法创建
使用 String::new 方法可以创建一个空的 String 类型的实例,例如:
let s1 = String::new(); // 创建一个空的 String 类型
通过使用 String::from 方法创建
String::from 方法可以直接使用字符串字面量创建 String,例如:
let s2 = String::from("hello");
实际上,你也可以理解为将一个 str 转换为对应的 String。
通过 str 类型的 to_string 方法创建
不可变字符串 str 上提供了一个 to_string 方法,返回对应的 String 字符串。例如:
let s3 = "world".to_string();
通过 format! 宏创建
你还可以使用 format! 宏 来创建 String 字符串。例如:
let s4 = format!("{} {}", "hello", "world");
关于 format! 宏 ,请参考 4.3 format! 宏 与 模板字符串的使用
4.2 String 用法解析
4.2.1 字符串拼接
使用 + 操作符可以用于拼接两个字符串例如:
let s1 = String::from("Hello ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // 使用 + 运算符连接两个字符串
println!("{}", s3); // 输出:Hello world!
4.2.2 字符串的切片
所谓 切片,指的是通过指定一对起止字符在字符串中的 位序,从而获得一个子字符串的方法。和诸多编程语言一样(如Python),可以使用 [] 语法对字符串进行切片。如:
let s1 = String::from("hello");
let s2 = &s1[0..2]; // 使用切片获取字符串的一部分
println!("{}", s2); // 输出:he
4.2.3 clone 方法拷贝字符串
String 的 clone 方法从原 String 对象实例上拷贝得到一个副本,例如:
let s1 = String::from("hello");
let s2 = s1.clone(); // 使用 clone 方法复制一个字符串
println!("{}", s2); // 输出:hello
4.2.4 trim 方法去除两端空白字符
在字符串处理的时候经常需要处理掉字符串两端的空白字符,使用 String 的trim 方法即可轻松实现,例如:
例如:
let s1 = String::from("hello");
let s2 = s1.trim();
println!("{}", s9); // 输出:hello
4.2.5 chars 方法及其应用
String 的 chars 方法
String 的chars 方法用于获取字符串的字符迭代器。
例如:
let s1 = String::from("hello");
let s2 = s1.chars(); // 获取字符串的字符迭代器
for c in s23 {println!("{}", c); // 逐个输出字符串的字符
}
通过 chars 方法获取 字符串首字符
例如:
let s1 = String::from("hello");
let s2 = s1.chars().nth(0).unwrap(); // 获取字符串的第一个字符
println!("{}", s2); // 输出:h
通过 chars 方法获取 字符串尾字符
例如:
let s1 = String::from("hello");
let s2 = s1.chars().last().unwrap(); // 获取字符串的最后一个字符
println!("{}", s2); // 输出:o
通过 chars 方法获取 字符串的字符数
例如:
let s1 = String::from("hello");
let s2 = s1.chars().count(); // 获取字符串的字符数
println!("{}", s2); // 输出:5
通过 chars 方法 反转字符串
例如:
let s1 = String::from("hello");
let s2 = s1.chars().rev().collect::<String>(); // 将字符串反转
println!("{}", s2); // 输出:olleh
4.2.6 to_uppercase 方法将字符串统一为大写字母形式
例如:
let s1 = String::from("hEllo");
let s2 = s1.to_uppercase(); // 将字符串转换为大写字母形式
println!("{}", s2); // 输出:HELLO
4.2.7 to_lowercase 方法将字符串统一为大写字母形式
例如:
let s1 = String::from("heLLo");
let s2 = s1.to_lowercase(); // 将字符串转换为小写字母形式
println!("{}", s2); // 输出:hello
4.2.8 len 方法获取字符串的长度
例如:
let length = String::from("world").len(); // 5
4.2.9 contains 方法判断字符串是否包含指定的子串
例如:
let isContains = String::from("Hello").contains("llo"); // true
4.2.10 push 方法在字符串末尾添加单个字符
例如:
let mut s = String::from("Hello");
s.push('!');
println!("{}", s); // 输出:Hello!
4.2.11 push_str 方法在字符串末尾添加字符串字面量
例如:
let mut s = String::from("hello");
s.push_str(", world!");
println!("{}", s); // 输出:hello, world!
4.2.12 pop 方法移除字符串末尾的字符
例如:
let mut s = String::from("hello!");
s.pop(); // 移除字符串末尾的字符
println!("{}", s); // 输出:hello
4.2.13 remove 方法移除字符串指定为序处的字符
例如:
let mut s = String::from("hello");
s.remove(2);
println!("{}", s); // 输出:helo
4.2.14 insert 方法在字符串指定位置插入内容
内容可以是 char 和 str。
例如在字符串指定位置插入单个字符:
let mut s = String::from("helo");
s.insert(2, 'l'); //
println!("{}", s); // 输出:hello
又如在字符串指定位置插入字符串字面量:
let mut s = String::from("heo");
s.insert(1, "ll");
println!("{}", s); // 输出:hello
4.2.15 replace_range 方法替换字符串指定范围内的内容
例如:
let mut s = String::from("hello");
s.replace_range(1..3, "a");
println!("{}", s); // 输出:hallo
4.2.16 truncate 方法截断字符串
truncate 方法可以用于截断字符串,只保留指定长度的内容。例如:
let mut s = String::from("hello");
s.truncate(3);
println!("{}", s); // 输出:hel
4.2.17 clear 方法清空字符串的内容
字符串是字符的容器,清空字符串就得到一个没有任何字符的字符串,也称空字符串。
例如:
let mut s = String::from("hello");
s.clear();
println!("{}", s); // 输出:
4.2.18 字符串中使用转义符、原始字符串
字符串中使用转义符
在介绍 Rust 字符的时候我们介绍过转义符,Rust 中的字符串类型也支持转义字符,例如:
let s1 = "hello\nworld"; // 换行符
let s2 = "hello\tworld"; // 制表符
let s3 = "hello\'world"; // 单引号
let s4 = "hello\\world"; // 反斜杠
也可以使用转义符表示 Unicode 标量值,例如:
let s1 = "\u{1F600}"; // Unicode 表情符号
let s2 = "\u{1F600}\u{1F601}\u{1F602}"; // 多个 Unicode 表情符号
原始字符串表示
在 Rust 中,字符串前的 r# 表示使用原始字符串表示法,不会转义字符。例如:
let s1 = r#"hello\nworld"#;
println!("{}", s1); // 输出:hello\nworld
原始字符串表示法还支持使用多个 # 号,例如:
let s2 = r##"hello "world""##;
println!("{}", s2); // 输出:hello "world"
使用原始字符串表示法可以避免一些转义字符带来的麻烦,比如在正则表达式中使用反斜杠。例如:
let s3 = r"\d+";
println!("{}", s3); // 输出:\d+
4.3 format! 宏 与 模板字符串的使用
Rust 中的 format! 宏 用于格式化字符串,比如:
let s1 = format!("{} {}", "hello", "world"); // 使用位置占位符
let s2 = format!("{name} {age}", name = "Alice", age = 18); // 使用命名占位符
let s3 = format!("{:?}", vec![1, 2, 3]); // 将 Vec 转换为字符串
format! 宏 还支持一些高级特性,如:
let s4 = format!("{:x}", 255); // 将数字转换为十六进制字符串
let s5 = format!("{:b}", 255); // 将数字转换为二进制字符串
let s6 = format!("{:o}", 255); // 将数字转换为八进制字符串
let s7 = format!("{:.2}", 3.1415926); // 将浮点数保留两位小数
let s8 = format!("{:+}", 123); // 将数字添加正负号
let s9 = format!("{:*>10}", "hello"); // 将字符串右对齐并填充 *
let s10 = format!("{:^10}", "hello"); // 将字符串居中对齐
相关文章:
Rust 笔记:Rust 语言中的字符串
Rust 笔记 Rust 语言中的字符串 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263?spm1001.2101.3001.5343 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/article/detail…...
华为OD机试真题 Java 实现【将真分数分解为埃及分数】【牛客练习题】
一、题目描述 分子为1的分数称为埃及分数。现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数。如:8/11 = 1/2+1/5+1/55+1/110。 注:真分数指分子小于分母的分数,分子和分母有可能gcd不为1! 如有多个解,请输出任意一个。 二、输入描述 输…...
Zemax Lumerical | 二维光栅出瞳扩展系统优化
简介 本文提出并演示了一种以二维光栅耦出的光瞳扩展(EPE)系统优化和公差分析的仿真方法。 在这个工作流程中,我们将使用3个软件进行不同的工作 ,以实现优化系统的大目标。首先,我们使用 Lumerical 构建光栅模型并使用…...
Linux-0.11 文件系统read_write.c详解
Linux-0.11 文件系统read_write.c详解 模块简介 该模块实现了文件系统通用的读写的方法read/write/lseek。 根据文件类型的不同,在内部将调用不同的方法。如果是管道文件,则调用pipe.c中的读写方法,如果是字符设备,则会调用cha…...
什么是用户态和内核态?用户态切换内核态会有什么影响?
一、什么是用户态和内核态? 简单来讲,像使用java开发时,调用java中封装的普通方法程序时属于用户态,而操作内存或者cpu比如 new Thread()创建一个线程,Class.forName(xxx.class)这种属于内核态 用户态和内核态是操作系…...
探索iOS之CoreImage框架
CoreImage提供图像处理、人脸识别、图像增强、图像滤镜、图像转场。它操作的数据来自Core Graphics、Core Video、Image IO,使用CPU或GPU进行渲染。CoreImage对底层实现进行封装,为上层提供简单易用的API。 一、CoreImage框架 CoreImage框架分为&#…...
qml 使用Shape 画图形
最近在做项目的时候想这实现一个能够根据相对位置动态改变大小的进度条提示框,偶尔发现了一个很有用的组件Shape这个控件里面可以画各种线条,实线虚线矩形三角形圆角的三角形或者各种自定义形状。下面提供一个2条虚线加上一个矩形的小栗子。更多的自定义形状还是请自…...
MySQL数据库修改root账户密码
博主今天登录数据库遇到了一个问题,通过这篇文章(http://t.csdn.cn/58ECT)解决了。文中关于修改root账户密码的部分,博主觉得有必要写一篇文章总结下。 第一步:用管理员账户打开CMD 第二步:开启mysql服务 …...
基于springboot+Vue+ Element-Plus+mysql实现学生宿舍管理系统
基于springbootVue Element-Plusmysql实现学生宿舍管理系统 一、系统介绍二、功能展示1.登陆2、主页--学生3、主页--宿舍管理员4.学生管理--管理员5.宿管信息--管理员6.宿舍管理--管理员7.信息管理--管理员8.申请管理--管理员9.访客管理--管理员10.水电费管理--管理员11.卫生管…...
中国人才选拔制度演变
1、世官制 是西周时人们仍保持着牢固的宗族血缘联系,人群基本以族区分,并得到宗法封建制的制度上的保证,从而自然形成了各级宗族长同时也就是各级官长,家国一体、家国同构的统治模式、格局。换句话来讲就是我们所说的世袭制。 其…...
【JavaSE】Java基础语法(十六):抽象类
文章目录 1. 抽象类的概述2. 抽象类的特点3. 抽象类的实用价值4. 抽象类的案例 1. 抽象类的概述 当我们在做子类共性功能抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了! 在Java中,一个没有方法体的方法应该定义…...
【Kafka】超详细介绍
文章目录 概念部署方案磁盘网络CPUpartition的数量 命令查看版本找kafka和zookeeper的ip/porttopic创建 topic查看get topic 列表get topic 详情 修改topic修改分区级别参数(如增加partition) 删除topic设置消息大小上限 生产查看生产生产消息 查看消费server 查看 offset查看积…...
2023 华为 Datacom-HCIE 真题题库 07/12--含解析
多项选择题 1.[试题编号:190187] (多选题)如图所示的拓扑采用了VXLAN分布式网关,SW1上的VBDIF10配置了:arp-proxy local enable命令,则以下描述中正确的有哪些项? A、SW1收到PC1发往PC2的报文&…...
Spring的作用域和生命周期
目录 1.Bean的作用域 2.Bean的作用域的分类 3.设置作用域 4.Spring的执行流程(生命周期) 5.Bean的生命周期 1.Bean的作用域 lombok (dependency依赖) 是为了解决代码的冗余(比如说get和set方法)那些构造…...
岭回归有看点:正则化参数解密,显著性不再成问题!
一、概述 「L2正则化(也称为岭回归)」 是一种用于线性回归模型的正则化方法,它通过在模型的损失函数中添加一个惩罚项来防止过拟合。L2正则化的惩罚项是模型参数的平方和,乘以一个正则化参数λ,即: L2正则化…...
Android 12.0修改recovery 菜单项字体大小
1.概述 在Android 12.0进入recovery模式后,界面会g_menu_actions 菜单选项和 提示文字,而这些文字的大小不像上层一样是通过设置属性来表示大小的 而它确是通过字体png图片的大小来计算文字的宽和高的,然后可以修改字体大小 2. 修改recovery 菜单项字体大小的核心类 buil…...
【计算机网络】 7、websocket 概念、sdk、实现
文章目录 一、背景二、简介三、client3.1 ws 构造函数3.2 ws.readyState3.3 ws.onopen3.4 ws.onclose3.5 ws.onmessage3.6 ws.send3.7 ws.bufferedAmount3.8 ws.onerror 四、server4.1 go4.1.1 apifox client4.1.2 js client 五、范式 一、背景 已经有了 http 协议,…...
python中的常见运算符
文章目录 算数运算符赋值运算关系运算符逻辑运算符非布尔值的与或非运算条件运算符(也叫三元运算符)运算符的优先级 算数运算符 加法运算符(如果两个字符串之间进行加法运算,则会进行拼串操作) - 减法运算符 * 乘法运算符(如果将字…...
TypeScript类型
TypeScript 是什么? 是以avaScript为基础构建的语言个一JavaScript的超集。可以在任何支持JavaScript的平台中执行。TypeScript扩展了JavaScript,并添加了类型。TS不能被JS解析器直接执行,需要编译成js。 基本类型 声明完变量直赴进行赋值 let c: boo…...
Integer源码
介绍 Integer是int类型的包装类,继承自Number抽象类,实现了Comparable接口。提供了一些处理int类型的方法,比如int到String类型的转换方法或String类型到int类型的转换方法,当然也包含与其他类型之间的转换方法。 Comparable提供…...
Frida hook so层解析protobuf二进制数据实战指南
1. 这不是“hook个so那么简单”:为什么 protobuf 数据成了 Frida 调试里最隐蔽的拦路虎你有没有遇到过这种情况:用 Frida 成功 hook 到某个 so 库里的关键函数,log 打得满屏飞,参数地址、返回值、调用栈一应俱全——可当你兴冲冲地…...
响应式图像:优化不同设备的图片展示
响应式图像:优化不同设备的图片展示 什么是响应式图像? 响应式图像是指能够根据设备特性(屏幕尺寸、分辨率、网络条件等)自动选择最合适的图片版本。 为什么需要响应式图像? 性能优化:小屏幕加载小图片带宽…...
储能 PACK 与 BMS:怎么识别有真实出货的系统集成厂,避开组装贴牌
储能赛道的门槛看起来不高:买一批电芯,叫几家代工厂组装成 PACK,挂上自己的品牌,就能对外声称是"储能系统集成商"。这条路在 2021 年到 2024 年的行业高速期被走通过无数次。于是,有真实产线、真实并网项目、…...
ES 模块:JavaScript 模块化的标准方案
ES 模块:JavaScript 模块化的标准方案 什么是 ES 模块? ES 模块(ES Modules,简称 ESM)是 ECMAScript 2015(ES6)引入的官方模块化规范。 ES 模块 vs CommonJS 特性CommonJSES Modules加载方式同步…...
Alibaba组件选型与架构设计
Alibaba组件选型与架构设计 前言 本文将总结Spring Cloud Alibaba各组件的特点,并根据不同业务场景提供选型建议和架构设计指导。 一、组件对比与选型 1.1 注册中心对比 特性NacosEurekaConsulCAP模型CP/AP可切换APCP多语言支持HTTP/DNSHTTPHTTP/DNS配置管理原生支持…...
当 SonarQube 遇见 Go:从零搭建自动化代码质量检测体系
继 gofmt、golangci-lint、go test -race 之后,SonarQube 成为 Go 工程化质量保障体系的第四块拼图 在上一篇文章中,我们详细梳理了 gofmt + golangci-lint + go test -race 这套原生工具链的审查体系。这套组合拳在代码风格统一、静态分析和数据竞争检测方面表现出色,但细心…...
阿里巴巴运营/2026年阿里巴巴1688店铺效果越来越差的3个核心原因(附解决方案)
阿里巴巴运营/2026年阿里巴巴1688店铺效果越来越差的3个核心原因(附解决方案)最近很多工厂老板跟我说,小峰老师,我这1688店铺怎么越做越没效果了?明明以前还能来几个询盘,现在越来越少,是不是16…...
实际开发中 SQL 与产品的耦合与互动实践
引言 在产品开发初期,数据库 Schema(表结构)的设计是一个绕不开的核心问题。很多开发者,尤其是新手,常常会陷入一个两难境地:“Schema 需要一开始就完全确定好吗?如果后期要改动怎么办?到底要设计多少个表(Schema 数量)才算合适?” 这些问题背后,反映的是对软件工…...
【AI入门知识点】Harness 是什么?为什么 DeepSeek 要组建 Harness 团队?
最近,DeepSeek 招聘信息中出现了一个越来越高频的关键词——Harness 团队。 很多人第一反应是: Harness 是什么?一种新模型?还是某个框架?为什么 DeepSeek 专门成立团队来做这个?如果你第一次听到这个词&am…...
DeepSeek总结的从 DuckDB 迁移到 chDB基准测试
来源: https://github.com/chdb-io/cookbook/tree/main/migration-from-duckdbBENCHMARK.md 迁移基准测试 —— 深度探讨 本文是从 DuckDB 迁移到 chDB指南的配套文档。指南的第 5 节将环境/场景/结果/摘要内联呈现;本文件则包含不适合指南风格流程的部分…...
