当前位置:首页>java>Rust宏编程完全指南:用元编程解锁Rust的终极力量

Rust宏编程完全指南:用元编程解锁Rust的终极力量

  • 2026-02-07 00:05:57
Rust宏编程完全指南:用元编程解锁Rust的终极力量

"宏就像是编译器的魔法棒,挥一挥,重复的代码就消失了。" —— 某位深夜 debug 的 Rustacean

目录

  • Why:为什么需要宏?[1]
  • What:宏是什么?[2]
  • How:如何使用宏?[3]
    • 声明宏 (macro_rules!)[4]
    • 派生宏 (Derive Macros)[5]
    • 属性宏 (Attribute Macros)[6]
    • 函数式宏 (Function-like Macros)[7]
  • 最佳实践[8]
  • 常见误区[9]
  • 总结[10]

Why:为什么需要宏?

想象一下,你正在写一个 Web 框架,需要为 50 个不同的结构体实现相同的序列化逻辑。如果用函数,你会发现自己陷入了"复制粘贴地狱"。如果用泛型,又会因为 Rust 严格的类型系统而撞墙。这时候,宏就像超级英雄一样闪亮登场了!

宏解决的核心问题

1. 消除重复代码(DRY 原则的终极武器)

// 没有宏之前,你可能要写:implToStringfor User { /* ... */ }implToStringfor Product { /* ... */ }implToStringfor Order { /* ... */ }// 写到第 50 个的时候,你已经怀疑人生了// 有了宏:#[derive(ToString)]structUser { /* ... */ }// 搞定!

2. 编译时计算(零运行时开销)

宏在编译期展开,这意味着:

  • 没有运行时性能损失
  • 错误在编译时就能发现
  • 生成的代码可以被编译器完全优化

3. 创建 DSL(领域特定语言)

// 比如 vec! 宏让你写出这样优雅的代码:let v = vec![12345];// 而不是:letmut v = Vec::new();v.push(1);v.push(2);v.push(3);v.push(4);v.push(5);

4. 超越泛型的抽象能力

泛型很强大,但它有局限:

  • 泛型要求类型在运行时已知
  • 泛型受 trait bounds 约束
  • 宏可以操作任意语法,甚至可以生成新的类型

What:宏是什么?

在 Rust 中,宏是编写生成代码的代码(元编程)。但与 C 语言的简单文本替换不同,Rust 的宏操作的是抽象语法树(AST),这让它们既强大又安全。

Rust 宏的家族树

Rust 宏├── 声明宏 (Declarative Macros)│   └── macro_rules! - 基于模式匹配的宏└── 过程宏 (Procedural Macros)    ├── 派生宏 (Derive Macros) - #[derive(Trait)]    ├── 属性宏 (Attribute Macros) - #[attribute]    └── 函数式宏 (Function-like Macros) - macro!(...)

核心概念:TokenStream

宏的输入和输出都是 TokenStream(标记流),它是 Rust 代码的抽象表示:

// 这段代码对编译器来说是一个 TokenStreamlet x: i32 = 42;// 分解成 tokens:// [let] [x] [:] [i32] [=] [42] [;]

How:如何使用宏?

1. 声明宏 (macro_rules!)

声明宏是最容易入门的宏类型,它使用模式匹配语法,就像一个超级版的 match 表达式。

1.1 基础语法

macro_rules! say_hello {// () 表示宏不接受参数    () => {println!("Hello, Rustacean!");    };}fnmain() {    say_hello!(); // 输出: Hello, Rustacean!}

1.2 接受参数

宏使用片段说明符(fragment specifiers)来匹配不同类型的语法元素:

说明符
匹配内容
示例
expr
表达式
1 + 2
foo()
ident
标识符
x
my_var
ty
类型
i32
Vec<String>
pat
模式
Some(x)
_
stmt
语句
let x = 5;
block
代码块
{ /* ... */ }
item
fn foo() {}
struct Bar;
tt
Token树
任何标记

实例:创建一个 HashMap 初始化宏

macro_rules! hashmap {// 匹配 key => value 对,逗号分隔    ($($key:expr => $value:expr),* $(,)?) => {        {letmut map = ::std::collections::HashMap::new();            $(                map.insert($key, $value);            )*            map        }    };}fnmain() {let scores = hashmap! {"Alice" => 95,"Bob" => 87,"Charlie" => 92,    };println!("{:?}", scores);}

语法分析:

  • $( ... )* - 零次或多次重复
  • $(,)? - 可选的尾随逗号
  • $key:expr - 捕获一个表达式并命名为 key

1.3 多模式匹配

macro_rules! calculate {// 加法    (add $a:expr, $b:expr) => {        $a + $b    };// 乘法    (mul $a:expr, $b:expr) => {        $a * $b    };// 多个数字求和    (sum $($num:expr),+) => {        {letmut total = 0;            $(                total += $num;            )+            total        }    };}fnmain() {println!("{}", calculate!(add 1020));        // 30println!("{}", calculate!(mul 56));          // 30println!("{}", calculate!(sum 12345)); // 15}

1.4 实战案例:类型安全的单位转换

macro_rules! unit_converter {    ($value:expr, $from:ident to $to:ident) => {match (stringify!($from), stringify!($to)) {            ("meters""feet") => $value * 3.28084,            ("feet""meters") => $value / 3.28084,            ("kg""pounds") => $value * 2.20462,            ("pounds""kg") => $value / 2.20462,            _ => panic!("不支持的单位转换: {} to {}"stringify!($from), stringify!($to)),        }    };}fnmain() {let height_m = 1.75;let height_ft = unit_converter!(height_m, meters to feet);println!("{}米 = {:.2}英尺", height_m, height_ft);}

2. 派生宏 (Derive Macros)

派生宏是最常用的过程宏类型,你肯定用过 #[derive(Debug, Clone)]

2.1 工作原理

派生宏:

  1. 接收结构体/枚举的 TokenStream
  2. 分析其字段和类型
  3. 生成 trait 实现代码
  4. 不修改原始类型,只添加新代码

2.2 创建自定义派生宏

步骤 1:创建过程宏 crate

# Cargo.toml[package]name = "my_derive"version = "0.1.0"edition = "2021"[lib]proc-macro = true  # 关键:声明这是过程宏 crate[dependencies]syn = { version = "2.0", features = ["full"] }quote = "1.0"proc-macro2 = "1.0"

步骤 2:实现派生宏

// src/lib.rsuse proc_macro::TokenStream;use quote::quote;use syn::{parse_macro_input, DeriveInput};#[proc_macro_derive(Builder)]pubfnderive_builder(input: TokenStream) -> TokenStream {// 解析输入的结构体let input = parse_macro_input!(input as DeriveInput);let name = &input.ident;let builder_name = syn::Ident::new(        &format!("{}Builder", name),         name.span()    );// 提取字段let fields = iflet syn::Data::Struct(data) = &input.data {iflet syn::Fields::Named(fields) = &data.fields {            &fields.named        } else {panic!("Builder 只支持命名字段的结构体");        }    } else {panic!("Builder 只能应用于结构体");    };// 生成 builder 字段(都是 Option)let builder_fields = fields.iter().map(|f| {let name = &f.ident;let ty = &f.ty;        quote! {            #nameOption<#ty>        }    });// 生成 setter 方法let setters = fields.iter().map(|f| {let name = &f.ident;let ty = &f.ty;        quote! {pubfn #name(mutself#name#ty) -> Self {self.#name = Some(#name);self            }        }    });// 生成 build 方法let build_fields = fields.iter().map(|f| {let name = &f.ident;        quote! {            #nameself.#name.ok_or(concat!("字段 "stringify!(#name), " 未设置")            )?        }    });// 使用 quote! 生成最终代码let expanded = quote! {pubstruct #builder_name {            #(#builder_fields,)*        }impl #builder_name {            #(#setters)*pubfnbuild(self) -> Result<#name, &'staticstr> {Ok(#name {                    #(#build_fields,)*                })            }        }impl #name {pubfnbuilder() -> #builder_name {                #builder_name {                    #(#nameNone,)*                }            }        }    };    TokenStream::from(expanded)}

步骤 3:使用派生宏

use my_derive::Builder;#[derive(Builder)]structUser {    username: String,    email: String,    age: u32,}fnmain() {let user = User::builder()        .username("rustacean".to_string())        .email("rust@example.com".to_string())        .age(25)        .build()        .unwrap();println!("{} ({}岁): {}", user.username, user.age, user.email);}

2.3 处理泛型和生命周期

派生宏的一个常见陷阱是忘记处理泛型参数:

// 这个结构体有泛型参数#[derive(Builder)]structContainer<T> {    value: T,}// 你的派生宏需要提取并保留泛型信息let generics = &input.generics;let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();let expanded = quote! {impl #impl_generics #name #ty_generics #where_clause {// ...    }};

3. 属性宏 (Attribute Macros)

属性宏可以附加到几乎任何 Rust 项上,并且可以修改或增强该项。

3.1 基础结构

#[proc_macro_attribute]pubfnroute(attr: TokenStream, item: TokenStream) -> TokenStream {// attr: 属性参数(如 #[route(GET, "/users")] 中的 GET, "/users")// item: 被装饰的项(如函数定义)// 返回:替换后的代码}

3.2 实战:创建一个计时宏

use proc_macro::TokenStream;use quote::quote;use syn::{parse_macro_input, ItemFn};#[proc_macro_attribute]pubfntimed(_attr: TokenStream, item: TokenStream) -> TokenStream {let input = parse_macro_input!(item as ItemFn);let fn_name = &input.sig.ident;let fn_block = &input.block;let fn_sig = &input.sig;let fn_vis = &input.vis;let output = quote! {        #fn_vis #fn_sig {let _start = std::time::Instant::now();// 执行原始函数体let result = (|| #fn_block)();let _duration = _start.elapsed();println!("函数 {} 执行耗时: {:?}"stringify!(#fn_name), _duration);            result        }    };    TokenStream::from(output)}

使用示例:

#[timed]fnslow_computation() -> u64 {    std::thread::sleep(std::time::Duration::from_secs(2));42}fnmain() {let result = slow_computation();// 输出: 函数 slow_computation 执行耗时: 2.00sprintln!("结果: {}", result);}

3.3 高级案例:带参数的属性宏

#[proc_macro_attribute]pubfncache(attr: TokenStream, item: TokenStream) -> TokenStream {let cache_size: usize = syn::parse_str(&attr.to_string())        .expect("cache 参数必须是数字");let input = parse_macro_input!(item as ItemFn);// 生成带缓存功能的函数let expanded = quote! {// 使用 lazy_static 创建全局缓存        lazy_static::lazy_static! {staticref CACHE: std::sync::Mutex<                lru::LruCache<StringString>            > = std::sync::Mutex::new(                lru::LruCache::new(                    std::num::NonZeroUsize::new(#cache_size).unwrap()                )            );        }        #input  // 保留原函数// 生成带缓存的包装函数// ... (实现细节)    };    TokenStream::from(expanded)}

使用:

#[cache(100)]// 缓存最多 100 个结果fnexpensive_api_call(query: &str) -> String {// 昂贵的计算...}

4. 函数式宏 (Function-like Macros)

函数式宏看起来像函数调用,但实际上是在编译时展开。

4.1 基础示例

#[proc_macro]pubfnsql(input: TokenStream) -> TokenStream {let query = input.to_string();// 在编译时验证 SQL 语法!    validate_sql(&query).expect("无效的 SQL 语句");// 生成优化的查询执行代码let expanded = quote! {        {let query = #query;            execute_query(query)        }    };    TokenStream::from(expanded)}

使用:

fnmain() {let users = sql!(SELECT * FROM users WHERE age > 18);// 如果 SQL 语法错误,编译就会失败!}

4.2 实战:HTML 模板宏

macro_rules! html {// 匹配单个标签    (<$tag:ident>$($content:tt)*</$close:ident>) => {        {assert_eq!(stringify!($tag), stringify!($close), "标签不匹配"            );format!("<{}>{}</{}>"stringify!($tag),                     html!($($content)*), stringify!($tag))        }    };// 匹配文本内容    ($text:expr) => {        $text.to_string()    };}fnmain() {let page = html!(        <html>            <body>                <h1>"欢迎来到 Rust 世界!"</h1>            </body>        </html>    );println!("{}", page);}

最佳实践

1. 命名规范

// ✅ 好的命名macro_rules! create_user { /* ... */ }        // 清晰的动词#[derive(Serialize)]// 名词形式的 trait#[validate(email)]// 描述性的属性// ❌ 避免macro_rules! x { /* ... */ }                  // 太短#[do_stuff]// 不明确

2. 错误处理

// ✅ 提供有用的错误信息macro_rules! require_fields {    ($struct_name:ident { $($field:ident),* }) => {        compile_error!(concat!("结构体 "stringify!($struct_name), " 缺少必需字段: ",            $(stringify!($field), ", "),*        ));    };}// ✅ 在过程宏中使用 panic! 或 syn::Error#[proc_macro_derive(MyMacro)]pubfnmy_macro(input: TokenStream) -> TokenStream {let input = match syn::parse(input) {Ok(syntax_tree) => syntax_tree,Err(err) => return err.to_compile_error().into(),    };// ...}

3. 卫生性(Hygiene)

过程宏是非卫生的(unhygienic),这意味着它们可能与周围代码发生命名冲突:

// ❌ 危险:可能与用户代码冲突quote! {let result = compute();}// ✅ 使用绝对路径quote! {let __internal_result = ::my_crate::compute();}// ✅ 或使用 fully qualified syntaxquote! {let result = <Type as Trait>::method();}

4. 文档化你的宏

/// 创建一个 HashMap 并初始化键值对////// # 示例////// ```/// let map = hashmap! {///     "key1" => "value1",///     "key2" => "value2",/// };/// ```#[macro_export]macro_rules! hashmap {// ...}

5. 测试宏

#[cfg(test)]mod tests {use super::*;#[test]fntest_hashmap_macro() {let map = hashmap! {"a" => 1,"b" => 2,        };assert_eq!(map.get("a"), Some(&1));    }// 使用 trybuild 测试编译错误#[test]fntest_compile_errors() {let t = trybuild::TestCases::new();        t.compile_fail("tests/invalid_usage.rs");    }}

6. 性能考虑

// ✅ 宏在编译时展开,没有运行时开销let v = vec![12345];// ✅ 但要注意宏展开可能增加二进制大小// 如果宏在很多地方调用且生成大量代码,考虑改用函数

常见误区

误区 1:宏可以做任何事

现实: 宏有明确的限制。

// ❌ 无法生成新的标识符名称(除非使用 paste 等技巧)macro_rules! create_function {    ($name:ident) => {fn $name_generated() {}  // 错误!不能拼接标识符    };}// ✅ 需要使用 paste! crateuse paste::paste;macro_rules! create_function {    ($prefix:ident) => {        paste! {fn [<$prefix _generated>]( "<$prefix _generated>") {}  // OK!        }    };}

误区 2:忽略宏的顺序依赖

// ❌ 错误:宏还未定义fnmain() {    my_macro!();}macro_rules! my_macro {    () => { println!("Hello!"); };}// ✅ 正确:先定义宏macro_rules! my_macro {    () => { println!("Hello!"); };}fnmain() {    my_macro!();}

误区 3:过度使用宏

问题代码:

// ❌ 这个可以用简单函数实现macro_rules! add_two {    ($x:expr) => {        $x + 2    };}// ✅ 更好的选择constfnadd_two(x: i32) -> i32 {    x + 2}

何时使用宏 vs 函数:

使用宏
使用函数
需要操作语法(如生成 trait 实现)
简单的值计算
需要在编译时验证某些条件
运行时逻辑
需要可变数量的参数类型
固定的参数类型
实现 DSL
普通业务逻辑

误区 4:不处理边界情况

// ❌ 没有处理空列表macro_rules! first {    ($($x:expr),+) => {        $x  // 错误:哪个 $x?    };}// ✅ 明确处理macro_rules! first {    ($first:expr $(, $rest:expr)*) => {        $first    };}

误区 5:忘记递归限制

// ❌ 可能触发递归限制macro_rules! recurse {    () => {        recurse!()  // 无限递归!    };}// ✅ 如果需要深层递归,增加限制#![recursion_limit = "256"]

调试技巧

1. 查看宏展开结果

# 使用 cargo expand(需要先安装)cargo install cargo-expand# 查看完整的宏展开cargo expand# 查看特定模块cargo expand module_name

2. 使用 dbg! 宏

macro_rules! debug_macro {    ($($x:expr),*) => {        {            $(                dbg!($x);  // 在宏内部调试            )*        }    };}

3. 编译时打印

// 在过程宏中打印调试信息eprintln!("Processing: {:?}", tokens);

实战综合案例:创建一个状态机宏

这个案例综合运用了多种宏技术:

// 定义状态机语法macro_rules! state_machine {    (        $name:ident {            states: [ $($state:ident),* $(,)? ]            transitions: {                $($from:ident => $to:ident on $event:ident),* $(,)?            }        }    ) => {// 定义状态枚举#[derive(Debug, Clone, Copy, PartialEq)]enum $name {            $($state),*        }// 定义事件枚举        paste::paste! {#[derive(Debug)]enum [<$name Event>] {                $($event),*            }        }// 实现状态转换impl $name {fntransition(&self, event: &paste::paste!{[<$name Event>]}) -> Option<Self> {match (self, event) {                    $(                        (Self::$from, paste::paste!{[<$name Event>]::$event}) => {Some(Self::$to)                        }                    )*                    _ => None,                }            }        }    };}// 使用状态机宏state_machine! {    TrafficLight {        states: [Red, Yellow, Green]        transitions: {            Red => Green on TimerExpired,            Green => Yellow on TimerExpired,            Yellow => Red on TimerExpired,        }    }}fnmain() {letmut light = TrafficLight::Red;println!("初始状态: {:?}", light);    light = light.transition(&TrafficLightEvent::TimerExpired).unwrap();println!("转换后: {:?}", light);  // Green}

总结

宏是 Rust 的超能力,但也需要谨慎使用。记住这些要点:

✅ 使用宏的好时机

  • 消除大量重复代码
  • 创建 DSL 让代码更简洁
  • 在编译时验证或生成代码
  • 实现无法用泛型表达的抽象

❌ 避免使用宏的情况

  • 简单的值计算(用函数)
  • 普通的类型抽象(用泛型)
  • 会让代码难以理解的地方

🎯 学习路径建议

  1. 初学者:从 macro_rules! 开始,理解模式匹配
  2. 进阶者:学习派生宏,理解 syn 和 quote
  3. 高级开发者:掌握属性宏和函数式宏,创建 DSL

📚 推荐资源

  • The Rust Book - Macros[11]
  • The Little Book of Rust Macros[12]
  • dtolnay/proc-macro-workshop[13] - 实践练习

最后的忠告: 宏就像辣椒酱,适量使用能让你的代码美味可口,但过量使用会让人难以下咽。在写宏之前,问问自己:"这个真的需要宏吗?" 如果答案是肯定的,那就大胆地挥舞你的元编程魔法棒吧!🪄✨

Happy macro coding, Rustaceans! 🦀

Reference
[1] 

Why:为什么需要宏?: #why为什么需要宏

[2] 

What:宏是什么?: #what宏是什么

[3] 

How:如何使用宏?: #how如何使用宏

[4] 

声明宏 (macro_rules!): #1-声明宏-macro_rules

[5] 

派生宏 (Derive Macros): #2-派生宏-derive-macros

[6] 

属性宏 (Attribute Macros): #3-属性宏-attribute-macros

[7] 

函数式宏 (Function-like Macros): #4-函数式宏-function-like-macros

[8] 

最佳实践: #最佳实践

[9] 

常见误区: #常见误区

[10] 

总结: #总结

[11] 

The Rust Book - Macros: https://doc.rust-lang.org/book/ch20-05-macros.html

[12] 

The Little Book of Rust Macros: https://danielkeep.github.io/tlborm/book/

[13] 

dtolnay/proc-macro-workshop: https://github.com/dtolnay/proc-macro-workshop

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-07 23:51:51 HTTP/2.0 GET : https://f.mffb.com.cn/a/467551.html
  2. 运行时间 : 0.166443s [ 吞吐率:6.01req/s ] 内存消耗:4,677.55kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=66326b68d357be02d5b02a9f87fe153f
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000482s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000720s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.003481s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000271s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000545s ]
  6. SELECT * FROM `set` [ RunTime:0.000215s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000613s ]
  8. SELECT * FROM `article` WHERE `id` = 467551 LIMIT 1 [ RunTime:0.007299s ]
  9. UPDATE `article` SET `lasttime` = 1770479511 WHERE `id` = 467551 [ RunTime:0.002941s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 65 LIMIT 1 [ RunTime:0.000430s ]
  11. SELECT * FROM `article` WHERE `id` < 467551 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.012332s ]
  12. SELECT * FROM `article` WHERE `id` > 467551 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.007285s ]
  13. SELECT * FROM `article` WHERE `id` < 467551 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.013081s ]
  14. SELECT * FROM `article` WHERE `id` < 467551 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.024837s ]
  15. SELECT * FROM `article` WHERE `id` < 467551 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.027344s ]
0.168082s