文档章节

rust 语法概要(只适合不熟悉时快速查阅使用,不适合理解其精髓。未完待续)

捍卫机密
 捍卫机密
发布于 07/18 18:10
字数 4428
阅读 82
收藏 2

注意:本内容只适合快查,不适合理解精髓。精髓请研读

https://kaisery.github.io/trpl-zh-cn/foreword.html
rust 的核心思想是 由程序员,语法,编译器 共同 维护 程序内的变量生成,使用,复制,转移和销毁。

基本数据类型


i8,i16,i32,i64,i128 //有符号整数
u8,u16,u32,u64,u128 //无符号整数
f32,f64 //浮点数,money估计也要用到此值
char //字符类型
bool:true,false // bool 类型
String //要引用std::string::String //字符串类型
silce //切片,这是个片段引用
type Name = String; //类型别名,只是个别名不是新类型

常量变量


const MAX_POINTS: u32 = 100_000; // 静态
let x = 5;//绑定变量
let x:u32 = 5;
let mut x = 5;//声明可变绑定
let mut x:u64 = 5;

let spaces = " ";//字面值
let spaces = spaces.len();//这是重定义space,而不是设置
let mut spaces = " ";
spaces = ‘3’;//这是变更值内容
let guess: u32 = "42".parse().expect("Not a number!");//这个是转换+验证抛错
下面是字面值
Decimal 98_222;
Hex 0xff;
Octal 0o77;
Binary 0b1111_0000;
Byte (u8 only) b'A';

运算符


+-*/% 5大运算,加减乘除余

组合结构


let x: (i32, f64, u8) = (500, 6.4, 1); //元组
let a = [1, 2, 3, 4, 5]; // 数组
let mut a:[i32;5]=[1,2,3,4,5]; // 可变数组绑定 &a[0]=2后[2,2,3,4,5]
// 数组的定义写法 变量名:[类型;数组长度]

函数-方法


fn another_function() { ... } // 孤立的叫函数,impl的&self首个参数的叫方法(类似对象方法),impl内首个参数非&self的方法叫关联函数(类似静态方法)
fn another_function(x: i32, y: i32)->i32// 多参数单返回值
fn plus_one(x: i32, y: i32) -> (i32,i32)//多参数多返回值

控制结构


if number < 5 { //单个if else
} else {
}
if number % 4 == 0 { // 一堆if else if
} else if number % 3 == 0 {
} else if number % 2 == 0 {
} else {
}
let number = if condition { // if赋值,有分号的叫语句,没分号的叫表达式-含有返回
5
} else {
6
};

循环


loop { // 玩命的循环
if true { break; } //还是能退出的
}
while number != 0 { //不玩命的循环
}
for element in a.iter() { // 挨着循环
}
for number in (1..4).rev() { //倒着循环
}

函数参数-引用参数


fn calculate_length(s: &String) -> usize // 引用参数
let len = calculate_length(&s1);
// 可变引用函数
fn change(some_string: &mut String) {
let mut s = String::from("hello");
change(&mut s);

slice 切片


let s = String::from("hello world");
let hello = &s[0..5];// 注意 字符串 时 这里取的是字节,utf-8不能这样取!必死!
let world = &s[6..11];// 数组的话ok
let slice = &s[0..2]; // 开头开始取
let slice = &s[..2]; // 开头开始取,省了0
let len = s.len();
let slice = &s[3..len]; //一直取到结尾
let slice = &s[3..];
let slice = &s[0..len];
let slice = &s[..]; //全取
fn first_word(s: &String) -> &str {
&s[..] // 表达式,返回slice
}

字符串接入,字符串+操作


let mut s = String::from("lo");
s.push('l');//push接入
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // +接入
// 多个字符串组合
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3; //行但笨
let s = format!("{}-{}-{}", s1, s2, s3); // 女子
// 异类字符 slice
let hello = "Здравствуйте";
let s = &hello[0..4];// 必须双数,取得字节!
for c in "Здравствуйте".chars() { //取得字面字符
println!("{}", c);
}
for b in "Здравствуйте".bytes() { //取得字节
println!("{}", b);
}

struct 结构体


struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
let user1 = User {
username: String::from("someusername123"),
};
let mut user1 = User { // 可变更的
username: String::from("someusername123"),
};
user1.username = String::from("another");

结构-方法语法


#[derive(Debug)] //这个让结构体可被打印出来
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle { // 方法语法,在impl中叫方法,孤立的叫函数
fn area(&self) -> u32 { //注意self 和py类似
self.width * self.height
}
}
let rect1 = Rectangle { width: 30, height: 50 };
rect1.area() //用变量.成员调用

关联函数(associated functions)


不加&self 就是关联函数
impl Rectangle {
fn square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
}
Rectangle::square(100) //关联函数访问

枚举,每个值可不同类型


enum Message {
Quit,
Move { x: i32, y: i32 }, // 匿名结构体
Write(String),
ChangeColor(i32, i32, i32), //元组
}
Message::ChangeColor //访问方法
enum Option<T> { //官方一个结构用于返回错误和正常结果
Some(T),
None,
}
#[derive(Debug)] // So we can inspect the state in a minute
enum UsState {
Alabama,
// ... etc
}
enum Coin {
Dime,
Quarter(UsState),//这个枚举类型是另一个枚举
}
match coin { // match语法
Coin::Dime => 10, // 直接返回(表达式)
Coin::Quarter(state) => { // 含有函数体
println!("State quarter from {:?}!", state);
25
},
// _ => (), // 通配符匹配,匹配所有剩余项目
}
// 只匹配一个其他忽略
let some_u8_value = Some(0u8);
match some_u8_value {
Some(3) => println!("three"),
_ => (),
}
// 只匹配一个其他忽略 简化写法
if let Some(3) = some_u8_value {
println!("three");
} else { ... }
// 这是一组写法,值得学习
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None, //空返回
Some(i) => Some(i + 1), //有结果返回
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);

pub


pub //控制可见 在 fn impl mod 前面

模块引用


extern crate my_library; // 先进入模块名 同下文的 a
a::series::of::nested_modules(); //完整路径模块引用样例
use a::series::of;
of::nested_modules(); // use 简短 引用路径
use a::series::of::nested_modules;
nested_modules(); // 最深到函数
use TrafficLight::{Red, Yellow}; // 只引入两个
let red = Red;
let yellow = Yellow;
let green = TrafficLight::Green;//这个还是要完整引入
// * 语法,这称为 glob 运算符(glob operator)
use TrafficLight::*; // 全引入
::client::connect(); // 开头双冒表从根模块引用开始
super::client::connect(); // super表上一级模块开始引用,是上一级不是根!
#[cfg(test)]
mod tests {
use super::client; //在mod内部 super上一级 引入,少些好多super
#[test]
fn it_works() {
client::connect();
}
}
use mymod::mymod2::mymod3 as mm3; // use as 语法use别名 我就说肯定有类似的!

集合 vcetor


默认引入,无需use
let v: Vec<i32> = Vec::new();
let v = vec![1, 2, 3];
v.push(5); //push进去
v.push(6);
let third: &i32 = &v[2]; // 用索引访问
let third: Option<&i32> = v.get(2); // get加索引访问,注意返回类型 超界处理良好
let v = vec![100, 32, 57]; //遍历1
for i in &v {
println!("{}", i);
}
let mut v = vec![100, 32, 57]; // 可变更遍历
for i in &mut v {
*i += 50; // 使用 += 运算符之前必须使用解引用运算符(*)获取 i 中的值。
}
// 枚举 的 vector 感觉好复杂哦!!!
enum SpreadsheetCell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
SpreadsheetCell::Int(3),
SpreadsheetCell::Text(String::from("blue")),
SpreadsheetCell::Float(10.12),
];

HashMap


use std::collections::HashMap; // 要use
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
// 这是个杂交组合法,要use std::collections::HashMap;
let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];
let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect(); //这里杂交组合两个vector
// 插入值 所有权转移
let field_name = String::from("Favorite color");
let field_value = String::from("Blue");
let mut map = HashMap::new();
map.insert(field_name, field_value); // 这里插入后两个值所有权被转移到map内部了
访问map
let score = scores.get(&team_name);
for (key, value) in &scores { //遍历
println!("{}: {}", key, value);
}
scores.insert(String::from("Blue"), 25); // 覆盖
scores.entry(String::from("Blue")).or_insert(50); //没有就插入,有跳过
// 找到一个键对应的值并根据旧的值更新它
let text = "hello world wonderful world";
let mut map = HashMap::new();
for word in text.split_whitespace() {
let count = map.entry(word).or_insert(0);
*count += 1; // 为了赋值必须首先使用星号(*)解引用 count
}

异常 抛错


[profile] //cargo.toml 配置
panic = 'abort'
[profile.release] // 这是发布模式
panic = 'abort'
panic!("crash and burn");// 抛错语句
设置 RUST_BACKTRACE 环境变量来得到一个 backtrace backtrace 是一个执行到目前位置所有被调用的函数的列表。(怎么设置?还不晓得)
enum Result<T, E> { //可恢复的错误 的 枚举
Ok(T),
Err(E),
}
let f = File::open("hello.txt");
let f = match f { // 用match处理成功和失败
Ok(file) => file,
Err(error) => {
panic!("There was a problem opening the file: {:?}", error)
},
};
// 一个错误处理范例 这个范例嵌套了 match
use std::fs::File;
use std::io::ErrorKind;
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(ref error) if error.kind() == ErrorKind::NotFound => {
match File::create("hello.txt") {
Ok(fc) => fc, // 成功的处理
Err(e) => {
panic!(
"Tried to create file but there was a problem: {:?}",
e // 表达式返回了e
)
},
}
},
Err(error) => {
panic!(
"There was a problem opening the file: {:?}",
error
)
},
};
}
let f = File::open("hello.txt").unwrap(); // unwrap帮调用panic! 宏 但是无法体现具体错误
let f = File::open("hello.txt").expect("Failed to open hello.txt"); // expect可以体现不同的错误,更好

传播错误


fn read_username_from_file() -> Result<String, io::Error>{ // 返回参数是“标准库结果”
let f = File::open("hello.txt");
let mut f = match f {
Ok(file) => file,
Err(e) => return Err(e), // 返回错误
};
let mut s = String::new();
match f.read_to_string(&mut s) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}

简化的错误传播


fn read_username_from_file() -> Result<String, io::Error> { // 注意 ? 关键
let mut f = File::open("hello.txt")?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?; //链式方法调用
Ok(s)
? 只能被用于返回值类型为 Result 的函数

泛型


struct Point<T> { //单泛型
x: T,
y: T,
}
struct Point<T, U> { // 多泛型
x: T,
y: U,
}
enum Option<T> { //单泛型枚举
Some(T),
None,
}
enum Result<T, E> { //多枚举泛型
Ok(T),
Err(E),
}
impl<T> Point<T> { //泛型方法定义
fn x(&self) -> &T {
&self.x
}
}
impl Point<f32> { // 特定类型方法定义
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
impl<T, U> Point<T, U> { // 双泛型 方法定义,方法中还有泛型
fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
Point {
x: self.x,
y: other.y,
}
}
}
trait 类似接口 定义共享行为
pub trait Summarizable { // 定义trait
fn summary(&self) -> String;
}
impl Summarizable for NewsArticle { // 为类型NewsArticle 实现这个trait
fn summary(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
impl Summarizable for Tweet { // 为类型 Tweet实现 Summarizable trait
fn summary(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
限制是:只能在 trait 或对应类型位于我们 crate 本地的时候为其实现 trait。换句话说,不允许对外部类型实现外部 trait。例如,不能在 Vec 上实现 Display trait,因为 Display 和 Vec 都定义于标准库中。
pub trait Summarizable { // 默认实现
fn summary(&self) -> String {
String::from("(Read more...)")
}
}
impl Summarizable for NewsArticle {} // 空impl 块,直接使用默认trait行为
pub trait Summarizable { // 默认实现可以调用未实现的 方法
fn author_summary(&self) -> String; // 这个行为 由 实现trait者去定义
fn summary(&self) -> String {
format!("(Read more from {}...)", self.author_summary()) // 调用author_summary,然后再调用特定行为
}
}
Trait Bounds 应该就是约束,实现约束,泛型实现trait约束
pub fn notify<T: Summarizable>(item: T) {
println!("Breaking news! {}", item.summary());
}
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 { //多个约束
fn some_function<T, U>(t: T, u: U) -> i32 // where方式多个约束
where T: Display + Clone,
U: Clone + Debug
{

生命周期注解语法


生命周期注解并不改变任何引用的生命周期的长短。只是个注解
&i32 // a reference
&'a i32 // a reference with an explicit lifetime
&'a mut i32 // a mutable reference with an explicit lifetime
它只是个变量生命周期的标注,通过标注来识别生命周期范围,实际不影响变量生命周期

let s: &'static str = "I have a static lifetime."; // 静态生命周期,全程序周期,字符串字面值自带
生命周期也是泛型” - 这句话让我直接炸裂!我艸,我说呢!写在<>内!
问题:泛型的生命周期呢?是不是要直接定义在泛型类型定义中?
多个生命周期定义只能通过泛型类型,或者结构体类型来定义?
生命周期也存在约束(where)?
fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &str { //这里实际上是永远都不能编译的?除非用方法语法?


测试
cargo test // 项目目录内运行此命令 就提取测试来运行了
#[cfg(test)] //测试模块 属性注解。属性(attribute)是关于 Rust 代码片段的元数据
mod tests {
use super::*; // 引用要测试的模块 为哈是super ,要测试的模块同级别
#[test] //测试方法 属性注解
fn it_works() {
assert_eq!(2 + 2, 4); // 测试 断言宏
}
}
assert! 宏由标准库提供,参数bool,false 时 assert! 调用 panic! 宏 抛错
assert_eq! 相等断言宏 和 assert_ne! 不相等断言宏
assert_eq! 和 assert_ne! 宏在底层分别使用了 == 和 !=。被比较的值必需实现了 PartialEq 和 Debug trait。
可以直接在结构体或枚举上添加 #[derive(PartialEq, Debug)] 注解。
let result = greeting("Carol");
assert!(result.contains("Carol")); // 断言结果中含有“Carol”
assert!(
result.contains("Carol"),
"Greeting did not contain name, value was `{}`", result // 这里类似重载函数,打印出明确信息
);
#[test]
#[should_panic] // 这里表示“应该抛错” 才是对的
#[should_panic(expected = "Guess value must be less than or equal to 100")] //出错信息包含expected的字符串就通过
#[ignore] // 忽略此测试
fn greater_than_100() {
Guess::new(200);
}
运行测试
cargo test -- --test-threads=1 // 单线程运行测试
cargo test -- --nocapture // 测试会输出函数中打印的内容,就是说不截获(并丢弃)屏幕输出
cargo test one_hundred // 运行含有“one_hundred”的测试
cargo test -- --ignored // 只运行忽略的测试
Rust 社区倾向于根据测试的两个主要分类来考虑问题:单元测试(unit tests)与 集成测试(integration tests)
测试模块的 #[cfg(test)] 注解告诉 Rust 只在执行 cargo test 时才编译和运行测试代码,而在运行 cargo build 时不这么做。
非pub函数可以测试
集成测试
目录中创建tests目录下放测试代码文件。
extern crate adder; // 需要导入指定模块
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
测试目录文件结构和模块一样,但子目录不被测试提取
tests/integration_test.rs // 文件中test 注解会被测试提取
tests/common/mod.rs // 文件中不会被测试提取,测试系统不考虑子模块的函数。但是上级测试方法可以调用子级
 

编写一个命令行程序


use std::env; // 环境变量功能
fn main() {
let args: Vec<String> = env::args().collect(); // 解析参数
let query = &args[1]; // 提取参数,为啥不是[0],[0]是二进制文件路径"target/debug/exename"
let filename = &args[2];
println!("{:?}", args);
}
注意 std::env::args 在其任何参数包含无效 Unicode 字符时会 panic。如果你需要接受包含无效 Unicode 字符的参数,使用 std::env::args_os 代替。这个函数返回 OsString 值而不是 String 值。
use std::env;
use std::fs::File; // std::fs::File 来处理文件
use std::io::prelude::*; // 而 std::io::prelude::* 则包含许多对于 I/O(包括文件 I/O)有帮助的 trait
let mut f = File::open(filename).expect("file not found"); // 读取文件
let mut contents = String::new();
f.read_to_string(&mut contents) // 文件内容读取到字符串变量
.expect("something went wrong reading the file");
let query = args[1].clone(); // 简单无脑的clone有一定好处,可以不用管生命周期
impl Config {
fn new(args: &[String]) -> Result<Config, &'static str> { // 静态周期 字符串
if args.len() < 3 {
return Err("not enough arguments");
}
let query = args[1].clone(); // clone
let filename = args[2].clone();
Ok(Config { query, filename }) // 返回Config结构
}
}
use std::process;//进程
let config = Config::new(&args).unwrap_or_else(|err| { // 注意 |err| 和闭包有关 将Err内部值传给闭包err参数
println!("Problem parsing arguments: {}", err); // 这就是闭包参数err,看起来类似 委托参数类似c#的(err)=>{...}
process::exit(1); //退出进程
});
line.to_lowercase().contains(&query) // 转换小写并检查是否含有&query
env::var("CASE_INSENSITIVE").is_err(); // 获取环境变量 powershell中设置环境变量:$env.CASE_INSENSITIVE=1
eprintln!("{:?}", &str1) // 标准错误输出宏

闭包(closures)


c#叫委托,c叫函数指针 ( 最好不要乱叫 免得被大神喷!)
use std::thread; // 线程
use std::time::Duration; // 时间差
fn simulated_expensive_calculation(intensity: u32) -> u32 {
thread::sleep(Duration::from_secs(2)); // 睡2秒 这个值得记住
0
}
let expensive_closure = |num, strx| { // 定义一个闭包 委托 函数指针(别瞎叫)
println!("calculating slowly..{}..", strx);
thread::sleep(Duration::from_secs(2));
num
};
let expensive_closure = |num: u32, strx:String| -> u32 {
println!("calculating slowly..{}..", strx);
thread::sleep(Duration::from_secs(2));
num
};
fn add_one_v1 (x: u32) -> u32 { x + 1 } // 这是一组对比,下面的和这个fn一致
let add_one_v2 = |x: u32| -> u32 { x + 1 }; // 指定参数类型返回类型
let add_one_v3 = |x| { x + 1 }; // 不指定类型只写函数体
let add_one_v4 = |x| x + 1 ; // 连大括号都去掉了
闭包无法同时进行两次类型推断
let example_closure = |x| x;
let s = example_closure(String::from("hello")); // 不抛错
let n = example_closure(5); // 抛错 类型不对,已经 被推断过了。
存放了闭包和一个 Option 结果值的 Cacher 结构体的定义
struct Cacher<T>
where T: Fn(u32) -> u32 // T就是个闭包,T 的 trait bound 指定了 T 是一个使用 Fn 的闭包。
{
calculation: T,
value: Option<u32>,
}
fn main() { // 内部函数
let x = 4;
fn equal_to_x(z: i32) -> bool { z == x } // 这里 报错 不能使用 x 函数不能上下文用外部值,闭包可以
let equal_to_x = |z| z == x; // 这就可以,捕获其环境并访问其被定义的作用域的变量
let y = 4;
assert!(equal_to_x(y));
}
fn main() {
let x = vec![1, 2, 3];
let equal_to_x = move |z| z == x; // x 被移动进了闭包,因为闭包使用 move 关键字定义。闭包获取了 x 的所有权,main 不再允许使用 x 。去掉 println! 即可。
println!("can't use x here: {:?}", x);
let y = vec![1, 2, 3];
assert!(equal_to_x(y));
}

迭代器(iterator)


负责遍历序列中的每一项和决定序列何时结束的逻辑。
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
for val in v1_iter {
println!("Got: {}", val);
}
trait Iterator { 迭代器都实现了这个trait特性
type Item;
fn next(&mut self) -> Option<Self::Item>; // methods with default implementations elided
}
let mut v1_iter = v1.iter(); // v1_iter 需要是可变的
assert_eq!(v1_iter.next(), Some(&1)); //next之后处理结果
如果我们需要一个获取 v1 所有权并返回拥有所有权的迭代器,则可以调用 into_iter 而不是 iter。
如果我们希望迭代可变引用,则可以调用 iter_mut 而不是 iter。
调用 next 方法的方法被称为 消费适配器(consuming adaptors)
let v1_iter = v1.iter();
let total: i32 = v1_iter.sum(); // 调用 sum 之后不再允许使用 v1_iter 因为调用 sum 时它会获取迭代器的所有权。
let v1: Vec<i32> = vec![1, 2, 3];
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect(); // 闭包+1后返还给Vec<...> v2
// collect 方法。这个方法消费迭代器并将结果收集到一个数据结构中。

部分源代码
https://gitee.com/raddleoj/rust_learn
 

© 著作权归作者所有

共有 人打赏支持
捍卫机密
粉丝 5
博文 126
码字总数 45015
作品 0
成都
程序员
自己收集的golang书籍

自己在学习golang时,收集到不少的书籍,在此记录下来。其中绝大部分是电子版,全部来源于网上。并对其中自己读过的作以简短的评论,未读过的则不作。 1、《Go语言圣经》 对于基础部分有详细...

Cyberpunk_ZYM
2017/04/12
0
0
自己收集的golang书籍

自己在学习golang时,收集到不少的书籍,在此记录下来。其中绝大部分是电子版,全部来源于网上。并对其中自己读过的作以简短的评论,未读过的则不作。 1、《Go语言圣经》 对于基础部分有详细...

Cyberpunk_ZYM
2017/04/13
0
0
2018 年 Rust 走向如何?社区说了算!

2017 年对 Rust 系统程序语言来说具有特别的意义。Rust 开源项目的成员正积极汇整去年的成果(使 Rust 变得更易学易用),并准备发表 Rust 自 2015 年发布以来第一波的重大更新。 「我们要把...

火狐
04/13
0
0
Rust 1.27 发布,众多 API 已稳定

Rust 1.27 已发布,Rust 是一门专注于安全性,速度和并发性的系统编程语言。 如果你已安装过 Rust,升级至 Rust 1.27 非常方便 $ rustup update stable 亮点包括: x86 / x8664 上的 SIMD(单...

clouddyy
06/26
0
11
Rust 1.2.0 翻译官网总结(一)

介绍 Rust 编程语言 欢迎学习本教程!本教程将教你如何使用 Rust 编程语言。Rust 是一门强调安全、性能和并发性的系统编程语言。它为了达到这几个目的,甚至没有一个垃圾收集器。这也使 Rust...

起名字凡人
2015/09/14
107
0

没有更多内容

加载失败,请刷新页面

加载更多

windows下Git BASH安装

1.从git官网下载一个git安装包,官网下载地址https://www.git-scm.com/downloads 2.双击安装程序,进入欢迎界面点击【Next >】...》finish 3.空白处点击鼠标右键选择Git Bash Here或点击开始...

15834278076
30分钟前
2
0
strpos

一、前方有坑 php某些自带函数,如果使用不当,也会坑得你人仰马翻。比如:strpos() 先了解一下strpos()函数是干啥的。 strpos — 查找字符串首次出现的位置 用法: int strpos ( string $hay...

dragon_tech
33分钟前
1
0
Spark DAG概述

一、 DAG定义 DAG每个节点代表啥?代表的一个RDD 这里再次复习RDD的5大特性 一组分片(Partition),即数据集的基本组成单位。对于RDD来说,每个分片都会被一个计算任务处理,并决定并行计算...

张泽立
33分钟前
0
0
防抖和节流

浏览器的一些事件,如:resize,scroll,keydown,keyup,keypress,mousemove等。这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用。会加重浏览器的负担,导致用户体验...

tianyawhl
43分钟前
1
0
mysql出现Waiting for table metadata lock的解决方法

查询某一个表时,一直没有显示数据,于是就show processlist; 发现有表已经被锁了,关掉了之前的查询语句可以看到 这时候需要查看未提交的事务 select trx_state, trx_started, trx_mysql_t...

bobway
43分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部