You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中创建编译期求值的只读线程安全全局静态变量?

解决方案:编译期构造只读静态H160变量

核心思路

既然H160底层是[u8;20]且支持Copy,而数组字面量可以在编译期直接求值,我们可以提前将十六进制地址转换为字节数组,再用H160的const构造函数直接创建静态变量,完全规避运行时解析字符串的开销。


方案1:手动转换字节数组(最简)

直接把目标地址的十六进制字符串拆解为字节数组,编译期即可完成初始化:

use primitive_types::H160;

// 编译期求值的只读静态变量,线程安全,无任何运行时开销
const ADDR: H160 = H160([
    0xda, 0xc1, 0x7f, 0x95, 0x8d, 0x2e, 0xe5, 0x23, 0xa2, 0x20,
    0x62, 0x06, 0x99, 0x45, 0x97, 0xc1, 0x3d, 0x83, 0x1e, 0xc7,
]);

fn main() {
    // 直接访问,无需unsafe,性能和复制原生数组一致
    let addr = ADDR;
    println!("地址:{}", addr);
}

优势:

  • 完全编译期完成初始化,无运行时成本
  • 天生线程安全,只读属性由编译器保证
  • 访问时无需任何unsafe包裹,代码简洁
  • 复制性能和你基准测试中的address_copy_static完全一致

方案2:用build.rs自动生成(适合多地址场景)

如果不想手动转换字节数组,可以通过build.rs在编译期自动解析十六进制字符串并生成const变量代码,避免手动输入错误:

  1. 项目根目录创建build.rs:
use std::fs::File;
use std::io::Write;
use std::path::Path;

fn main() {
    // 目标地址字符串
    let addr_str = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
    // 移除0x前缀并解码为字节数组
    let hex_str = addr_str.strip_prefix("0x").unwrap();
    let bytes = hex::decode(hex_str).unwrap();
    let bytes_array: [u8; 20] = bytes.try_into().unwrap();

    // 生成包含const变量的Rust代码文件
    let out_dir = std::env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("addr_const.rs");
    let mut file = File::create(&dest_path).unwrap();

    writeln!(file, "use primitive_types::H160;").unwrap();
    writeln!(
        file,
        "pub const ADDR: H160 = H160([{}]);",
        bytes_array
            .iter()
            .map(|b| format!("0x{:02x}", b))
            .collect::<Vec<_>>()
            .join(", ")
    )
    .unwrap();
}
  1. 在Cargo.toml中添加hex依赖:
[dependencies]
primitive_types = "0.12.1"
hex = "0.4.3"
  1. 在src/main.rs或src/lib.rs中引用生成的代码:
include!(concat!(env!("OUT_DIR"), "/addr_const.rs"));

fn main() {
    println!("自动生成的地址:{}", ADDR);
}

优势:

  • 无需手动转换字节数组,避免人为错误
  • 仍然是编译期生成代码,无任何运行时开销
  • 适合需要批量处理多个地址的场景

为什么不选其他方案?

  • unsafe静态变量:需要手动初始化,每次访问都要unsafe包裹,且存在线程安全风险(初始化阶段多线程访问会导致UB)
  • lazy_static:每次访问都会触发初始化检查(即使已经初始化完成),会带来额外的性能开销,不符合你的性能要求

内容的提问来源于stack exchange,提问作者theflash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:53:15