我尝试在服务启动时从系统环境加载密码和敏感数据。我尝试了多种不同的方法,但似乎无法找出在 Rust 中执行此操作的正确方法。
const PASSWORD: String = var("PASSWORD").unwrap();
不起作用,因为
method calls in constants are limited to constant inherent methods
。这同样适用于 static
(显然,错误表示静态)。
我见过的另一种方法是
const PASSWORD: &'static str = env!("PASSWORD");
但问题是它将在编译时定义为
env!
是一个宏(至少这是我的理解)。
我还考虑过简单地将对
var("...").unwrap()
的调用包装在一个函数中,但该解决方案并不适合我,并且还允许值在整个运行时更改,并且在服务启动时不验证它们。
正如你所知,我是 Rust 新手。如果在您的回答中您不仅能解释如何在运行时加载 const/static,还能解释为什么我所做的事情是愚蠢和错误的:)
,我真的很感激const
和 static
在 Rust 中扮演不同的角色。
const
不仅意味着一个常量,它还意味着一个编译时常量,一个在编译时确定并记录在程序只读存储器中的值。它不适合您的用例。
static
表示全局变量,其生命周期将跨越整个程序。它可能是可变的,在这种情况下它必须是
Sync
以避免并发修改。 static
变量必须从常量初始化,以便在程序启动时可用。那么,如何在运行时读取变量并使其可用呢?好吧,一个干净的解决方案是完全避免全局变量......
...但是因为它很方便,所以有一个板条箱:
。
use std::env::var;
use lazy_static::lazy_static;
lazy_static! {
static ref PASSWORD: String = var("PASSWORD").unwrap();
}
fn main() {
println!("{:?}", *PASSWORD);
}
首次访问变量时,执行表达式以加载其值,然后该值被记忆并可用,直到程序结束。
而不是
lazy_static
:use std::sync::OnceLock;
use std::env::var;
fn password() -> &'static str {
static PASSWORD: OnceLock<String> = OnceLock::new();
PASSWORD.get_or_init(|| {
var("PASSWORD").unwrap()
})
}
一旦稳定或每晚您可以简化为
LazyLock
:
#![feature(lazy_cell)]
use std::sync::LazyLock;
use std::env::var;
static PASSWORD: LazyLock<String> = LazyLock::new(|| {
var("PASSWORD").unwrap()
});