std/env
Environment variable access.
from "std/env" import { Env }Example
match Env.get("HOME") {
Some(home) => print(home),
None => print("HOME not set"),
}
let port = Env.getOr("PORT", "8080")
let _ = Env.set("RUST_LOG", "debug")Env.set and Env.remove change this process's environment, and they are not thread-safe: set the environment during startup, before spawning anything. See Env.set below for the details.
API reference
Env
pub struct EnvProcess environment operations grouped for discoverability.
Env.get
fn Env.get(name: string): Option<string>Look up an environment variable. None if it is unset.
Env.getOr
fn Env.getOr(name: string, defaultVal: string): stringLook up an environment variable, or defaultVal if it is unset: Env.getOr("PORT", "8080").
Env.remove
fn Env.remove(name: &string): Result<Unit, EnvError>Remove name from THIS process's environment. Removing a name that is not set succeeds. Carries the same thread-safety caveat as set — see there.
Env.set
fn Env.set(name: &string, value: &string): Result<Unit, EnvError>Set name to value in THIS process's environment, replacing any current value. Children spawned afterwards inherit it; the parent shell never sees it.
NOT thread-safe, and the platform gives no way to make it so. C's setenv may free the block a concurrent getenv is reading, so a getenv on another OS thread can read freed memory — a real crash, not a stale read. What Milo does and does not promise:
- Safe from a single-threaded program, and from anywhere in a program whose green tasks all run on the scheduler's one OS thread: green tasks only switch at await points, and this call contains none.
- NOT safe concurrently with Promise.blocking work, which runs on real OS threads and may call Env.get (or any C library that calls getenv) at the same instant.
- Env.get itself copies the value out before returning, so a value already read is never invalidated; the window is only the read in progress.
The safe pattern is the one Go and Rust also recommend: set the environment during startup, before spawning anything.
To give one child a variable without changing your own environment, use Command.env in std/process instead.
EnvError
pub enum EnvErrorWhy a mutation can fail. No catch-all variant: these are the only two outcomes libc distinguishes for setenv/unsetenv.
Variants:
InvalidName: Empty name, or a name containing '='. libc reports EINVAL; the check is done here so the reason is the same on every platform.Failed: The C call refused it — in practice out of memory.