<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrei Merlescu</title>
    <description>The latest articles on DEV Community by Andrei Merlescu (@andreimerlescu).</description>
    <link>https://dev.to/andreimerlescu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3590418%2Ff67be3de-03d6-4d58-b125-05db7e83dc7a.jpeg</url>
      <title>DEV Community: Andrei Merlescu</title>
      <link>https://dev.to/andreimerlescu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andreimerlescu"/>
    <language>en</language>
    <item>
      <title>Rust Decorators for Go Developers</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Fri, 22 May 2026 18:34:06 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/rust-decorators-for-go-developers-4k7</link>
      <guid>https://dev.to/andreimerlescu/rust-decorators-for-go-developers-4k7</guid>
      <description>&lt;p&gt;In Go, most of these concerns are handled by conventions, comments, runtime reflection, and external tools. In Rust, they are expressed as attributes that the compiler reads, verifies, and enforces before your program ever runs.&lt;/p&gt;

&lt;p&gt;If you have spent years writing Go, you already think in terms of goroutines, interfaces, and the implicit contract that the runtime handles the hard parts for you. Rust asks you to make all of those implicit contracts explicit — and the mechanism it uses to do that is attributes. Where Go relies on naming conventions, comments, build tags, struct tag strings, and external linters to express intent, Rust has a formal attribute syntax that the compiler reads at compile time, verifies, and enforces before a single line of your code runs. This document walks through thirteen categories of Rust attributes side by side with their closest Go analogs — not to argue that one language is better than the other, but to give you a map from the Go mental model you already own into the Rust one you are building. You will see that many things Go does silently behind its runtime — scheduling threads, copying memory, skipping serialized fields, enforcing interface contracts — Rust requires you to express openly through attributes, and in exchange the compiler guarantees correctness that Go leaves to discipline, convention, and luck. By the end you will understand not just what each attribute does, but why it exists and what problem it is solving that Go solves a different way.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;#[derive(...)]&lt;/code&gt; — Automatic Trait Implementation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[derive(...)]&lt;/code&gt; tells the Rust compiler to automatically generate implementations of standard traits for your type. A trait in Rust is roughly what an interface is in Go, except the compiler can write the implementation for you when the logic is mechanical. Without &lt;code&gt;#[derive(...)]&lt;/code&gt;, you would have to manually implement &lt;code&gt;Debug&lt;/code&gt;, &lt;code&gt;Clone&lt;/code&gt;, &lt;code&gt;PartialEq&lt;/code&gt;, and &lt;em&gt;others&lt;/em&gt; for every &lt;code&gt;struct&lt;/code&gt; and &lt;code&gt;enum&lt;/code&gt; you write. The derive macro inspects your type at compile time and generates the boilerplate so you don’t have to.&lt;/p&gt;

&lt;p&gt;The most commonly derived traits are: &lt;code&gt;Debug&lt;/code&gt;, &lt;code&gt;Clone&lt;/code&gt;, &lt;code&gt;Copy&lt;/code&gt;, &lt;code&gt;PartialEq&lt;/code&gt;, &lt;code&gt;Eq&lt;/code&gt;, &lt;code&gt;PartialOrd&lt;/code&gt;, &lt;code&gt;Ord&lt;/code&gt;, &lt;code&gt;Hash&lt;/code&gt;, &lt;code&gt;Default&lt;/code&gt;, and &lt;code&gt;Serialize&lt;/code&gt;/&lt;code&gt;Deserialize&lt;/code&gt; from &lt;code&gt;serde&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go has no equivalent syntax. The closest analog is implementing&lt;/span&gt;
&lt;span class="c"&gt;// an interface by satisfying its method signatures manually.&lt;/span&gt;
&lt;span class="c"&gt;// Go generates nothing for you — you write it all yourself.&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// To print with structure, you implement Stringer manually:&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Person{Name: %s, Age: %d}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// To copy, Go structs are value types — assignment copies automatically.&lt;/span&gt;
&lt;span class="c"&gt;// To compare, == works on structs if all fields are comparable.&lt;/span&gt;
&lt;span class="c"&gt;// None of this is declared — it's implicit or manual.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Rust generates all of this for you via #[derive(...)].&lt;/span&gt;
&lt;span class="c1"&gt;// Each trait listed is fully implemented by the compiler.&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Clone,&lt;/span&gt; &lt;span class="nd"&gt;PartialEq,&lt;/span&gt; &lt;span class="nd"&gt;Eq,&lt;/span&gt; &lt;span class="nd"&gt;Hash,&lt;/span&gt; &lt;span class="nd"&gt;Default)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Andrei"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Debug — enabled by #[derive(Debug)]&lt;/span&gt;
    &lt;span class="c1"&gt;// {:?} is the debug format, {:#?} is pretty-printed&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:#?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Clone — enabled by #[derive(Clone)]&lt;/span&gt;
    &lt;span class="c1"&gt;// .clone() performs a deep copy&lt;/span&gt;
    &lt;span class="c1"&gt;// Without this derive, .clone() does not compile&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// PartialEq — enabled by #[derive(PartialEq)]&lt;/span&gt;
    &lt;span class="c1"&gt;// Without this, == does not compile on your struct&lt;/span&gt;
    &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Default — enabled by #[derive(Default)]&lt;/span&gt;
    &lt;span class="c1"&gt;// Returns a zero-value equivalent, like Go's zero value&lt;/span&gt;
    &lt;span class="c1"&gt;// String defaults to "", u32 defaults to 0&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Copy vs Clone — critical distinction:&lt;/span&gt;
&lt;span class="c1"&gt;// Copy means the type can be duplicated by simply copying bits.&lt;/span&gt;
&lt;span class="c1"&gt;// Clone means the type knows how to duplicate itself, possibly with allocation.&lt;/span&gt;
&lt;span class="c1"&gt;// String cannot be Copy because it owns heap memory.&lt;/span&gt;
&lt;span class="c1"&gt;// u32, bool, f64 can be Copy because they are fixed-size stack values.&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Clone,&lt;/span&gt; &lt;span class="nd"&gt;Copy,&lt;/span&gt; &lt;span class="nd"&gt;PartialEq)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Point is Copy, so assignment moves a copy, not ownership.&lt;/span&gt;
&lt;span class="c1"&gt;// You can use p after assigning it to another variable.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; If any field in your struct does not implement a trait you are trying to derive, the derive will fail to compile. For example, you cannot derive Copy on a struct that contains a &lt;code&gt;String&lt;/code&gt; because &lt;code&gt;String&lt;/code&gt; is not &lt;code&gt;Copy&lt;/code&gt;. You cannot derive &lt;code&gt;Eq&lt;/code&gt; without also deriving &lt;code&gt;PartialEq&lt;/code&gt;. The order inside &lt;code&gt;#[derive(...)]&lt;/code&gt; does not matter. You can stack multiple derives on the same line or split them across multiple &lt;code&gt;#[derive(...)]&lt;/code&gt; attributes — both are valid. Deriving &lt;code&gt;Default&lt;/code&gt; requires every field’s type to also implement &lt;code&gt;Default&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[arg(...)]&lt;/code&gt; — Clap CLI Argument Declaration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[arg(...)]&lt;/code&gt; is not a standard library attribute — it comes from the clap crate and decorates fields inside a &lt;code&gt;#[derive(Parser)]&lt;/code&gt; struct. It describes how a struct field maps to a command-line argument: its flag name, short form, default value, environment variable fallback, help text, validation rules, and behavior. Clap reads these attributes at compile time and generates a full CLI parser from them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go's closest analog is the flag package, but it is entirely manual.&lt;/span&gt;
&lt;span class="c"&gt;// There is no struct-level declaration — you register each flag imperatively.&lt;/span&gt;
&lt;span class="c"&gt;// There is no compile-time validation — wrong types fail at runtime.&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"flag"&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"find"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"substring to search for"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cores"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"number of cores to use"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;insensitive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"insensitive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"case insensitive search"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// Values are now available via *find, *cores, *insensitive&lt;/span&gt;
    &lt;span class="c"&gt;// No env var fallback built in&lt;/span&gt;
    &lt;span class="c"&gt;// No conflict detection&lt;/span&gt;
    &lt;span class="c"&gt;// No required field enforcement&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;clap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Parser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Parser,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="nd"&gt;#[command(name&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"find-xrp-addr"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;about&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"XRP vanity address finder"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Cli&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// long:    creates --find flag&lt;/span&gt;
    &lt;span class="c1"&gt;// env:     falls back to $FIND if --find not passed&lt;/span&gt;
    &lt;span class="c1"&gt;// Type Option&amp;lt;String&amp;gt; means not required — None if absent&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(long,&lt;/span&gt; &lt;span class="nd"&gt;env&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"FIND"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// long = "1p": overrides the field name for the CLI flag&lt;/span&gt;
    &lt;span class="c1"&gt;// action = SetTrue: presence of --1p sets this to true&lt;/span&gt;
    &lt;span class="c1"&gt;//                   without SetTrue, bool requires --1p=true explicitly&lt;/span&gt;
    &lt;span class="c1"&gt;// env: falls back to $USE_ONEPASSWORD&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(long&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1p"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;env&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"USE_ONEPASSWORD"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;action&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;clap::ArgAction::SetTrue)]&lt;/span&gt;
    &lt;span class="n"&gt;use_op&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// default_value_t: typed default, not a string — avoids parse step&lt;/span&gt;
    &lt;span class="c1"&gt;// 0 is sentinel meaning "use all available cores"&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(long,&lt;/span&gt; &lt;span class="nd"&gt;default_value_t&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;env&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"CORES"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// value_name: controls the placeholder in --help output&lt;/span&gt;
    &lt;span class="c1"&gt;// shows as: --begins &amp;lt;PREFIX&amp;gt;&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(long,&lt;/span&gt; &lt;span class="nd"&gt;value_name&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"PREFIX"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;env&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"BEGINS"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// conflicts_with: errors if both --begins and --ends are&lt;/span&gt;
    &lt;span class="c1"&gt;// combined with --find in an unsupported way&lt;/span&gt;
    &lt;span class="c1"&gt;// requires: enforces another argument must also be present&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(long,&lt;/span&gt; &lt;span class="nd"&gt;env&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ENDS"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// short and long together: accepts both -v and --vault&lt;/span&gt;
    &lt;span class="nd"&gt;#[arg(short,&lt;/span&gt; &lt;span class="nd"&gt;long,&lt;/span&gt; &lt;span class="nd"&gt;env&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"VAULT"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Cli&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; &lt;code&gt;default_value&lt;/code&gt; takes a &lt;code&gt;&amp;amp;str&lt;/code&gt; and parses it, so a wrong string panics at runtime. &lt;code&gt;default_value_t&lt;/code&gt; takes a typed expression and fails at compile time if the type is wrong — always prefer &lt;code&gt;default_value_t&lt;/code&gt;. &lt;code&gt;action = clap::ArgAction::SetTrue&lt;/code&gt; is required on &lt;code&gt;bool&lt;/code&gt; fields if you want flag presence alone to mean &lt;code&gt;true&lt;/code&gt;. Without it, the user must write &lt;code&gt;--flag=true&lt;/code&gt; explicitly. &lt;code&gt;Option&amp;lt;String&amp;gt;&lt;/code&gt; means absent is &lt;code&gt;None&lt;/code&gt; — do not use &lt;code&gt;required = true&lt;/code&gt; on an &lt;code&gt;Option&lt;/code&gt; unless you explicitly want to override that inference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BONUS:&lt;/strong&gt; I wrote &lt;a href="https://github.com/andreimerlescu/rusty-figtree" rel="noopener noreferrer"&gt;rusty-figtree&lt;/a&gt; so that you can use my &lt;a href="https://github.com/andreimerlescu/figtree" rel="noopener noreferrer"&gt;figtree&lt;/a&gt; pattern in Rust, _instead of using &lt;code&gt;#[arg()]&lt;/code&gt;. &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[cfg(...)]&lt;/code&gt; — Conditional Compilation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[cfg(...)]&lt;/code&gt; tells the compiler to include or exclude a block of code depending on compile-time conditions: the target operating system, architecture, feature flags, test mode, or custom cfg values. The excluded code is completely removed from the binary — it is never parsed beyond syntax checking. This is more powerful than a runtime flag and more integrated than a preprocessor macro.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go's closest analog is build tags — a comment at the top of a file&lt;/span&gt;
&lt;span class="c"&gt;// that tells the Go toolchain whether to include that file.&lt;/span&gt;
&lt;span class="c"&gt;// Go operates at the file level; Rust operates at the item level.&lt;/span&gt;

&lt;span class="c"&gt;//go:build linux&lt;/span&gt;
&lt;span class="c"&gt;// +build linux  (old syntax, kept for compatibility)&lt;/span&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="c"&gt;// This entire file is excluded on non-Linux platforms.&lt;/span&gt;
&lt;span class="c"&gt;// You cannot conditionally compile a single function inside a file in Go&lt;/span&gt;
&lt;span class="c"&gt;// without splitting it into separate files.&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;platformSpecificThing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Linux only"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// #[cfg(...)] operates at the item level — a single function,&lt;/span&gt;
&lt;span class="c1"&gt;// struct, impl block, or expression can be conditionally included.&lt;/span&gt;

&lt;span class="c1"&gt;// Target OS conditions&lt;/span&gt;
&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"linux"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;platform_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Running on Linux"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"macos"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;platform_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Running on macOS"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"windows"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;platform_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Running on Windows"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Target architecture&lt;/span&gt;
&lt;span class="nd"&gt;#[cfg(target_arch&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"x86_64"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;arch_note&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"64-bit x86"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Feature flags — enabled via Cargo.toml [features] or --features flag&lt;/span&gt;
&lt;span class="c1"&gt;// This function only exists if the crate was compiled with --features="json"&lt;/span&gt;
&lt;span class="nd"&gt;#[cfg(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"json"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;serialize_json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// json-specific code here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Test-only code — #[cfg(test)] blocks are excluded from release builds&lt;/span&gt;
&lt;span class="c1"&gt;// This is the standard pattern for unit tests in Rust&lt;/span&gt;
&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;it_works&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// cfg! macro — evaluates to a bool at compile time for use in expressions&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nd"&gt;cfg!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug_assertions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Running in debug mode"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Combining conditions&lt;/span&gt;
    &lt;span class="c1"&gt;// all() = AND,  any() = OR,  not() = NOT&lt;/span&gt;
    &lt;span class="nd"&gt;#[cfg(all(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"linux"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;target_arch&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"x86_64"&lt;/span&gt;&lt;span class="nd"&gt;))]&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Linux on x86_64 only"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;#[cfg(any(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"linux"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"macos"&lt;/span&gt;&lt;span class="nd"&gt;))]&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Linux or macOS"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;#[cfg(not(target_os&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"windows"&lt;/span&gt;&lt;span class="nd"&gt;))]&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Not Windows"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; Code inside a &lt;code&gt;#[cfg(...)]&lt;/code&gt; block that is excluded is still syntax-checked but not type-checked in older Rust versions. In modern Rust it is fully excluded. This means you can have two functions with the same name under different &lt;code&gt;#[cfg(...)]&lt;/code&gt; guards — this is the standard cross-platform pattern. The &lt;code&gt;cfg!()&lt;/code&gt; macro is for runtime branching that the compiler still optimizes away. &lt;code&gt;#[cfg(test)]&lt;/code&gt; is the canonical way to keep test helpers and unit tests out of production binaries — equivalent to Go's &lt;code&gt;_test.go&lt;/code&gt; file convention but scoped to individual items rather than files.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[macro_export]&lt;/code&gt; and &lt;code&gt;#[macro_use]&lt;/code&gt; — Macro Visibility
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[macro_export]&lt;/code&gt; makes a macro defined with &lt;code&gt;macro_rules!&lt;/code&gt; publicly available to users of your crate, placing it at the crate root regardless of where in the module tree you defined it. &lt;code&gt;#[macro_use]&lt;/code&gt; was the old way to import all macros from an external crate before Rust 2018 edition introduced use imports for macros. In modern Rust, &lt;code&gt;#[macro_use]&lt;/code&gt; is mostly legacy but still seen in older codebases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go has no macros and no equivalent concept.&lt;/span&gt;
&lt;span class="c"&gt;// The closest analog is a package-level exported function —&lt;/span&gt;
&lt;span class="c"&gt;// you make something public by capitalizing its name.&lt;/span&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;mylib&lt;/span&gt;

&lt;span class="c"&gt;// Exported — visible to importers&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;MyHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToUpper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Unexported — private to this package&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;myHelper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// There is no way in Go to define something that generates code&lt;/span&gt;
&lt;span class="c"&gt;// at compile time the way Rust macros do.&lt;/span&gt;
&lt;span class="c"&gt;// go generate exists but it runs external tools, not inline code.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Defining a macro and exporting it from your crate&lt;/span&gt;

&lt;span class="c1"&gt;// WITHOUT #[macro_export]:&lt;/span&gt;
&lt;span class="c1"&gt;// This macro is only usable within this module and its children.&lt;/span&gt;
&lt;span class="nd"&gt;macro_rules!&lt;/span&gt; &lt;span class="n"&gt;say_hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// WITH #[macro_export]:&lt;/span&gt;
&lt;span class="c1"&gt;// This macro is placed at the crate root and is importable by users&lt;/span&gt;
&lt;span class="c1"&gt;// of this crate with: use mycrate::greet;&lt;/span&gt;
&lt;span class="nd"&gt;#[macro_export]&lt;/span&gt;
&lt;span class="nd"&gt;macro_rules!&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name:expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, {}!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// Multiple arms — like match, first match wins&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name:expr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$greeting:expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, {}!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$greeting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// In your own crate you can call it directly:&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;greet!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Andrei"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nd"&gt;greet!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Andrei"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Good morning"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ---&lt;/span&gt;

&lt;span class="c1"&gt;// #[macro_use] — OLD STYLE, pre-Rust-2018&lt;/span&gt;
&lt;span class="c1"&gt;// Importing all macros from an external crate without naming them:&lt;/span&gt;

&lt;span class="nd"&gt;#[macro_use]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;serde_derive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Modern equivalent — explicit and preferred:&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// ---&lt;/span&gt;

&lt;span class="c1"&gt;// #[macro_use] on a module — imports all macros defined in that&lt;/span&gt;
&lt;span class="c1"&gt;// module into the parent scope. Still occasionally useful internally.&lt;/span&gt;

&lt;span class="nd"&gt;#[macro_use]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;my_macros&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Now all macros from my_macros are available in this module&lt;/span&gt;
&lt;span class="c1"&gt;// without qualifying them as my_macros::some_macro!(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; &lt;code&gt;#[macro_export]&lt;/code&gt; always places the macro at the crate root, regardless of nesting depth. If your macro is inside &lt;code&gt;src/utils/helpers.rs&lt;/code&gt;, importing it is still use &lt;code&gt;mycrate::my_macro&lt;/code&gt;, not use &lt;code&gt;mycrate::utils::helpers::my_macro&lt;/code&gt;. This surprises many developers. In Rust 2018 and later, prefer explicit use &lt;code&gt;mycrate::my_macro&lt;/code&gt; over &lt;code&gt;#[macro_use] extern crate mycrate&lt;/code&gt;. The &lt;code&gt;#[macro_use]&lt;/code&gt; attribute on extern crate is considered legacy. Procedural macros (&lt;code&gt;#[derive(...)]&lt;/code&gt;, &lt;code&gt;#[some_attr]&lt;/code&gt;, and &lt;code&gt;function-like my_macro!(...)&lt;/code&gt; implemented in proc-macro crates) are a separate, more powerful system from &lt;code&gt;macro_rules!&lt;/code&gt; and do not use &lt;code&gt;#[macro_export]&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[repr(...)]&lt;/code&gt; — Memory Layout Control
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[repr(...)]&lt;/code&gt; controls how Rust lays out a struct or enum in memory. By default Rust makes no guarantees about field ordering or padding — it may reorder fields to optimize alignment. &lt;code&gt;#[repr(C)]&lt;/code&gt; forces C-compatible layout, which is required for FFI. &lt;code&gt;#[repr(u8)]&lt;/code&gt; and similar force an enum’s discriminant to a specific integer type. &lt;code&gt;#[repr(transparent)]&lt;/code&gt; guarantees a single-field struct has the same layout as its inner type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go structs have a defined layout: fields appear in declaration order,&lt;/span&gt;
&lt;span class="c"&gt;// with padding inserted by the compiler for alignment.&lt;/span&gt;
&lt;span class="c"&gt;// Go has no attribute to change this — you control layout by field order.&lt;/span&gt;

&lt;span class="c"&gt;// Inefficient — bool causes padding before int64&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Bad&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;    &lt;span class="c"&gt;// 1 byte + 7 bytes padding&lt;/span&gt;
    &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;   &lt;span class="c"&gt;// 8 bytes&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Efficient — largest fields first&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Good&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;   &lt;span class="c"&gt;// 8 bytes&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;    &lt;span class="c"&gt;// 1 byte + 7 bytes padding at end&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// For FFI with C, Go uses cgo and the layout matches C struct layout&lt;/span&gt;
&lt;span class="c"&gt;// for exported types — but this is implicit, not declared.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Default: Rust may reorder fields freely for optimal packing.&lt;/span&gt;
&lt;span class="c1"&gt;// No guarantees. Do not transmute or use in FFI without #[repr(C)].&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;DefaultLayout&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Rust may reorder this to: b(u64), a(u8), c(u8) + padding&lt;/span&gt;

&lt;span class="c1"&gt;// #[repr(C)]: fields in declaration order, C-compatible padding.&lt;/span&gt;
&lt;span class="c1"&gt;// Required for any struct passed across FFI boundaries.&lt;/span&gt;
&lt;span class="nd"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;CCompatible&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// 1 byte&lt;/span&gt;
    &lt;span class="c1"&gt;// 7 bytes padding&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// 8 bytes&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// 1 byte&lt;/span&gt;
    &lt;span class="c1"&gt;// 7 bytes padding&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[repr(packed)]: removes ALL padding. Fields may be unaligned.&lt;/span&gt;
&lt;span class="c1"&gt;// Accessing unaligned fields is undefined behavior in C.&lt;/span&gt;
&lt;span class="c1"&gt;// In Rust, taking a reference to a packed field is an error.&lt;/span&gt;
&lt;span class="nd"&gt;#[repr(packed)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Packed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// unaligned — no padding before it&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[repr(transparent)]: single-field struct has identical layout&lt;/span&gt;
&lt;span class="c1"&gt;// to its inner type. Used for newtype wrappers in FFI.&lt;/span&gt;
&lt;span class="nd"&gt;#[repr(transparent)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;Meters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Meters and f64 are interchangeable at the ABI level.&lt;/span&gt;

&lt;span class="c1"&gt;// #[repr(u8)] on an enum: discriminant stored as u8&lt;/span&gt;
&lt;span class="c1"&gt;// Without this, Rust picks the discriminant size freely.&lt;/span&gt;
&lt;span class="nd"&gt;#[repr(u8)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;North&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;South&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;East&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;West&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[repr(C)] on an enum: C-compatible tagged union layout&lt;/span&gt;
&lt;span class="nd"&gt;#[repr(C)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;CEnum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; Never use &lt;code&gt;#[repr(packed)]&lt;/code&gt; unless you are parsing binary wire formats and know exactly what you are doing — unaligned access is undefined behavior on many architectures including ARM. &lt;code&gt;#[repr(transparent)]&lt;/code&gt; is the correct way to build &lt;code&gt;newtype&lt;/code&gt; wrappers for FFI — it guarantees the wrapper is a zero-cost abstraction with no layout difference from the inner type. &lt;code&gt;#[repr(C)]&lt;/code&gt; is mandatory for any struct you pass to a &lt;code&gt;C&lt;/code&gt; function via FFI. Forgetting it means Rust may reorder your fields and your &lt;code&gt;C&lt;/code&gt; code reads garbage.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[non_exhaustive]&lt;/code&gt; — Future-Proof Enums and Structs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[non_exhaustive]&lt;/code&gt; marks an enum or struct as potentially having more variants or fields added in future versions of the crate. External crates that &lt;code&gt;match&lt;/code&gt; on a &lt;code&gt;#[non_exhaustive]&lt;/code&gt; enum are required by the compiler to include a wildcard &lt;code&gt;_&lt;/code&gt; arm. This prevents downstream breakage when you add a new variant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go has no equivalent. The closest analog is the convention of&lt;/span&gt;
&lt;span class="c"&gt;// documenting that a type "may grow" and relying on developer discipline.&lt;/span&gt;

&lt;span class="c"&gt;// In Go, switching on an iota enum with no default case compiles fine.&lt;/span&gt;
&lt;span class="c"&gt;// Adding a new value silently breaks exhaustive switches — no warning.&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;North&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;
    &lt;span class="n"&gt;South&lt;/span&gt;
    &lt;span class="n"&gt;East&lt;/span&gt;
    &lt;span class="n"&gt;West&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;North&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"north"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;South&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"south"&lt;/span&gt;
    &lt;span class="c"&gt;// No East, West — compiles fine, silently returns ""&lt;/span&gt;
    &lt;span class="c"&gt;// If you add Northeast tomorrow, nothing tells callers to update&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Without #[non_exhaustive]:&lt;/span&gt;
&lt;span class="c1"&gt;// External code that matches this enum must cover all variants.&lt;/span&gt;
&lt;span class="c1"&gt;// Adding a new variant is a breaking change.&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;North&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;South&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;East&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;West&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// With #[non_exhaustive]:&lt;/span&gt;
&lt;span class="c1"&gt;// External code MUST include a wildcard arm.&lt;/span&gt;
&lt;span class="c1"&gt;// You can add variants in future releases without breaking callers.&lt;/span&gt;
&lt;span class="nd"&gt;#[non_exhaustive]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Inactive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Pending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// You may add more variants in future versions.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// External crate trying to match Status:&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Active&lt;/span&gt;   &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Inactive&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"inactive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Pending&lt;/span&gt;  &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// This wildcard arm is REQUIRED by the compiler&lt;/span&gt;
        &lt;span class="c1"&gt;// because Status is #[non_exhaustive]&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[non_exhaustive] on a struct:&lt;/span&gt;
&lt;span class="c1"&gt;// External code cannot construct it with struct literal syntax.&lt;/span&gt;
&lt;span class="c1"&gt;// They must use your provided constructor functions.&lt;/span&gt;
&lt;span class="nd"&gt;#[non_exhaustive]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// You can add fields without breaking external callers&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// External code cannot do this if Config is #[non_exhaustive]:&lt;/span&gt;
&lt;span class="c1"&gt;// let c = Config { timeout: 30, retries: 3 }; // compile error externally&lt;/span&gt;
&lt;span class="c1"&gt;// They must use: Config::new(30, 3) or a builder pattern&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; &lt;code&gt;#[non_exhaustive]&lt;/code&gt; only affects code &lt;strong&gt;outside&lt;/strong&gt; the defining crate. Inside the crate that defines the type, exhaustive matching still works and struct literals are still valid. This is the correct attribute to use on any public enum in a library crate where you anticipate adding variants in future semver-compatible releases. Without it, adding a variant is a breaking change that requires a major version &lt;a href="https://github.com/andreimerlescu/bump" rel="noopener noreferrer"&gt;bump&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[must_use]&lt;/code&gt; — Enforced Return Value Handling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[must_use]&lt;/code&gt; on a function or type tells the compiler to emit a warning if the return value is discarded. It is how Rust enforces that callers handle &lt;code&gt;Result&lt;/code&gt; and other important values. Without this attribute, silently ignoring a &lt;code&gt;Result&lt;/code&gt; compiles without warning — which is how silent error swallowing happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go's closest analog is the convention of always checking errors.&lt;/span&gt;
&lt;span class="c"&gt;// The compiler does NOT warn you if you ignore a return value.&lt;/span&gt;
&lt;span class="c"&gt;// Ignoring errors in Go is legal and silent.&lt;/span&gt;

&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c"&gt;// legal — error silently ignored&lt;/span&gt;
&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// legal — error explicitly discarded&lt;/span&gt;

&lt;span class="c"&gt;// Go relies entirely on developer discipline and linters like errcheck.&lt;/span&gt;
&lt;span class="c"&gt;// There is no language-level enforcement.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// #[must_use] on a type:&lt;/span&gt;
&lt;span class="c1"&gt;// Any function returning this type triggers a warning if result is dropped.&lt;/span&gt;
&lt;span class="c1"&gt;// This is already on Result and Option in the standard library.&lt;/span&gt;

&lt;span class="nd"&gt;#[must_use]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;MyResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[must_use] on a function:&lt;/span&gt;
&lt;span class="c1"&gt;// Warning if the return value of THIS specific function is discarded.&lt;/span&gt;
&lt;span class="nd"&gt;#[must_use]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;compute_checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.fold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="nf"&gt;.wrapping_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This triggers: warning: unused return value of `compute_checksum`&lt;/span&gt;
    &lt;span class="nf"&gt;compute_checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c1"&gt;// This is fine — value is used&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;checksum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compute_checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checksum&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Explicitly discarding — suppresses the warning&lt;/span&gt;
    &lt;span class="c1"&gt;// Use this when you genuinely mean to ignore the value&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compute_checksum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c1"&gt;// Result is #[must_use] in stdlib — this warns:&lt;/span&gt;
    &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remove_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// This is fine:&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remove_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// explicit discard&lt;/span&gt;
    &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remove_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.ok&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    &lt;span class="c1"&gt;// .ok() converts to Option, discards&lt;/span&gt;
    &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remove_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// panics on error&lt;/span&gt;
    &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remove_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to remove"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// panics with message&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[must_use] with a message:&lt;/span&gt;
&lt;span class="nd"&gt;#[must_use&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"this seed was generated at cost — handle the result"&lt;/span&gt;&lt;span class="nd"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;generate_seed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// placeholder&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; &lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt; and &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; are both &lt;code&gt;#[must_use]&lt;/code&gt; in the standard library. This is why the compiler warns you when you call a function returning Result and do nothing with it. The idiomatic ways to explicitly discard are &lt;code&gt;let _ = ...&lt;/code&gt; for a one-off, or &lt;code&gt;.ok()&lt;/code&gt; on a &lt;code&gt;Result&lt;/code&gt; to convert it to an &lt;code&gt;Option&lt;/code&gt; and implicitly drop it. Using &lt;code&gt;#[must_use]&lt;/code&gt; on your own types and functions is considered good library hygiene — it prevents callers from making silent mistakes.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[inline]&lt;/code&gt; — Inlining Hints
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[inline]&lt;/code&gt; suggests to the compiler that a function’s body should be copied into every call site rather than generating a function call instruction. This eliminates call overhead and enables further optimizations at the call site. &lt;code&gt;#[inline(always)]&lt;/code&gt; is a strong directive. &lt;code&gt;#[inline(never)]&lt;/code&gt; prevents inlining, useful for debugging or code size control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go's compiler inlines automatically and aggressively.&lt;/span&gt;
&lt;span class="c"&gt;// You cannot annotate functions with inlining hints in Go.&lt;/span&gt;
&lt;span class="c"&gt;// The closest you can do is use //go:noinline to prevent it.&lt;/span&gt;

&lt;span class="c"&gt;//go:noinline&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;doNotInline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Otherwise, Go decides entirely on its own.&lt;/span&gt;
&lt;span class="c"&gt;// You can observe inlining decisions with: go build -gcflags="-m"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// #[inline] — hint to the compiler, may or may not be honored&lt;/span&gt;
&lt;span class="c1"&gt;// Most useful for small functions in library crates where the&lt;/span&gt;
&lt;span class="c1"&gt;// compiler cannot see across crate boundaries without LTO.&lt;/span&gt;
&lt;span class="nd"&gt;#[inline]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[inline(always)] — strong directive, almost always honored&lt;/span&gt;
&lt;span class="c1"&gt;// Use for hot path functions where call overhead is measurable.&lt;/span&gt;
&lt;span class="c1"&gt;// Overuse bloats binary size — every call site gets a copy.&lt;/span&gt;
&lt;span class="nd"&gt;#[inline(always)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;fast_clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;f64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[inline(never)] — prevent inlining&lt;/span&gt;
&lt;span class="c1"&gt;// Useful when profiling — inlined functions disappear in stack traces.&lt;/span&gt;
&lt;span class="c1"&gt;// Also useful when a function is large and called from many places.&lt;/span&gt;
&lt;span class="nd"&gt;#[inline(never)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;expensive_operation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// likely inlined — no call instruction&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;clamped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fast_clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;expensive_operation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} {} {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clamped&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; &lt;code&gt;#[inline]&lt;/code&gt; is most important for functions in &lt;em&gt;library crates&lt;/em&gt;. Within a single binary, the compiler can inline freely using its own judgment. Across crate boundaries, the compiler cannot inline unless the function is marked &lt;code&gt;#[inline]&lt;/code&gt; or link-time optimization (LTO) is enabled. For hot-path cryptographic or search code like your &lt;a href="https://github.com/andreimerlescu/rusty-xrp-addr" rel="noopener noreferrer"&gt;XRP seed generator&lt;/a&gt;, &lt;code&gt;#[inline(always)]&lt;/code&gt; on your innermost loop helpers can produce measurable gains. Do not use it globally — measure first.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[test]&lt;/code&gt; — Unit Test Declaration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[test]&lt;/code&gt; marks a function as a unit test. The function is only compiled when running cargo test and is excluded from release builds. Test functions take no arguments and return either &lt;code&gt;()&lt;/code&gt; or &lt;code&gt;Result&amp;lt;(), E&amp;gt;&lt;/code&gt;. Combined with &lt;code&gt;#[cfg(test)]&lt;/code&gt; on a module, this is the complete built-in testing story in Rust.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go tests live in files ending in _test.go.&lt;/span&gt;
&lt;span class="c"&gt;// Test functions start with Test and take *testing.T.&lt;/span&gt;
&lt;span class="c"&gt;// The file is automatically excluded from non-test builds.&lt;/span&gt;

&lt;span class="c"&gt;// file: mypackage_test.go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;mypackage&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"testing"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestAdd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"expected 3, got %d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Subtests:&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestMath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"addition"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"subtraction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Production code lives here — in the same file as tests.&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[cfg(test)] means this entire module is excluded from non-test builds.&lt;/span&gt;
&lt;span class="c1"&gt;// It can see private functions in the parent module — tests are siblings,&lt;/span&gt;
&lt;span class="c1"&gt;// not external callers. This is different from Go where _test.go files&lt;/span&gt;
&lt;span class="c1"&gt;// can be in the same package (white-box) or a separate _test package (black-box).&lt;/span&gt;
&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// bring parent module's items into scope&lt;/span&gt;

    &lt;span class="c1"&gt;// #[test] marks this as a test function&lt;/span&gt;
    &lt;span class="c1"&gt;// cargo test discovers and runs all #[test] functions&lt;/span&gt;
    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_add&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nd"&gt;assert_eq!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Tests can return Result — if Err is returned, the test fails&lt;/span&gt;
    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_with_result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"expected 3, got {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// #[should_panic] — test passes only if the code panics&lt;/span&gt;
    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="nd"&gt;#[should_panic(expected&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"division by zero"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;test_panic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// #[ignore] — skip this test unless explicitly run with --ignored&lt;/span&gt;
    &lt;span class="nd"&gt;#[test]&lt;/span&gt;
    &lt;span class="nd"&gt;#[ignore]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;slow_integration_test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// run with: cargo test -- --ignored&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; Rust tests live inside the same file as production code inside a &lt;code&gt;#[cfg(test)]&lt;/code&gt; module. This means they can access private functions directly — there is no need for a separate test package like Go's package &lt;code&gt;foo_test&lt;/code&gt;. For integration tests that test your crate as an external user would, place them in a &lt;code&gt;tests/&lt;/code&gt; directory at the crate root — those files are automatically treated as separate crates with no access to private internals, equivalent to Go's package &lt;code&gt;foo_test&lt;/code&gt; pattern.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[bench]&lt;/code&gt; — Benchmark Declaration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[bench]&lt;/code&gt; marks a function as a benchmark, run with cargo bench. Benchmark functions receive a &lt;code&gt;&amp;amp;mut Bencher&lt;/code&gt; and call &lt;code&gt;b.iter(|| ...)&lt;/code&gt; with the code to measure. This is currently only available on nightly Rust in the standard library. Stable Rust benchmarking uses the &lt;code&gt;criterion&lt;/code&gt; crate, which is the community standard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go benchmarks live in _test.go files alongside unit tests.&lt;/span&gt;
&lt;span class="c"&gt;// Benchmark functions start with Benchmark and take *testing.B.&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;BenchmarkAdd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// Run with: go test -bench=. -benchmem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Nightly only — built-in bench:&lt;/span&gt;
&lt;span class="nd"&gt;#![feature(test)]&lt;/span&gt;
&lt;span class="k"&gt;extern&lt;/span&gt; &lt;span class="k"&gt;crate&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;benches&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;test&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Bencher&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// #[bench] marks this as a benchmark function&lt;/span&gt;
    &lt;span class="c1"&gt;// b.iter() runs the closure repeatedly and measures throughput&lt;/span&gt;
    &lt;span class="nd"&gt;#[bench]&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;bench_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nn"&gt;test&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Bencher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// test::black_box prevents the compiler from optimizing&lt;/span&gt;
            &lt;span class="c1"&gt;// the computation away entirely — critical for benchmarks&lt;/span&gt;
            &lt;span class="nn"&gt;test&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;black_box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ---&lt;/span&gt;

&lt;span class="c1"&gt;// Stable Rust — criterion crate (preferred in production):&lt;/span&gt;
&lt;span class="c1"&gt;// Cargo.toml:&lt;/span&gt;
&lt;span class="c1"&gt;// [dev-dependencies]&lt;/span&gt;
&lt;span class="c1"&gt;// criterion = "0.5"&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// [[bench]]&lt;/span&gt;
&lt;span class="c1"&gt;// name = "my_benchmark"&lt;/span&gt;
&lt;span class="c1"&gt;// harness = false&lt;/span&gt;

&lt;span class="c1"&gt;// benches/my_benchmark.rs:&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;criterion&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;black_box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criterion_group&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criterion_main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Criterion&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;bench_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Criterion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="nf"&gt;.bench_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"add 1+2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;black_box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;black_box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;criterion_group!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;benches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bench_add&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;criterion_main!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;benches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; &lt;code&gt;black_box()&lt;/code&gt; is not optional. Without it, the compiler proves the result is unused and eliminates the entire computation — your benchmark measures zero work and reports impossibly fast numbers. This is equivalent to Go's &lt;code&gt;_ = result&lt;/code&gt; pattern in benchmarks. Criterion on stable Rust is superior to the built-in nightly bencher: it uses statistical analysis, detects outliers, and produces HTML reports. For your seed generation benchmarks, criterion would give you confidence intervals across runs rather than a single number.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[allow(...)]&lt;/code&gt;, &lt;code&gt;#[warn(...)]&lt;/code&gt;, &lt;code&gt;#[deny(...)]&lt;/code&gt;, &lt;code&gt;#[forbid(...)]&lt;/code&gt; — Lint Control
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These attributes control which compiler warnings and lints are active. &lt;code&gt;#[allow(...)]&lt;/code&gt; suppresses a warning. &lt;code&gt;#[warn(...)]&lt;/code&gt; enables a warning that may be off by default. &lt;code&gt;#[deny(...)]&lt;/code&gt; turns a warning into a compile error. &lt;code&gt;#[forbid(...)]&lt;/code&gt; turns a warning into a compile error and prevents any child scope from allowing it. They can be applied to a single item, a module, or the entire crate with &lt;code&gt;#![...]&lt;/code&gt; (inner attribute syntax).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go has no lint attributes — warnings are controlled externally&lt;/span&gt;
&lt;span class="c"&gt;// via tools like go vet, staticcheck, or golangci-lint configuration.&lt;/span&gt;
&lt;span class="c"&gt;// There is no in-code syntax to suppress a specific warning.&lt;/span&gt;
&lt;span class="c"&gt;// The closest is a comment convention recognized by specific linters:&lt;/span&gt;

&lt;span class="c"&gt;//nolint:errcheck&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// golangci-lint specific — not standard Go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Suppress a warning on a single item&lt;/span&gt;
&lt;span class="nd"&gt;#[allow(dead_code)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;unused_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I exist but am never called"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Suppress unused variable warning on a specific variable&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[allow(unused_variables)]&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// x is never used — normally a warning, suppressed here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Turn a warning into a compile error for a function&lt;/span&gt;
&lt;span class="nd"&gt;#[deny(unused_must_use)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;strict_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Any ignored Result inside here is a compile error, not a warning&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Inner attribute syntax (#![...]) applies to the whole crate or module&lt;/span&gt;
&lt;span class="c1"&gt;// Place at the top of main.rs or lib.rs for crate-wide effect:&lt;/span&gt;

&lt;span class="c1"&gt;// Allow dead code across the whole crate (useful during development)&lt;/span&gt;
&lt;span class="nd"&gt;#![allow(dead_code)]&lt;/span&gt;

&lt;span class="c1"&gt;// Deny all warnings crate-wide — common in CI pipelines&lt;/span&gt;
&lt;span class="nd"&gt;#![deny(warnings)]&lt;/span&gt;

&lt;span class="c1"&gt;// Common lints worth knowing:&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="c1"&gt;// dead_code           — function or field defined but never used&lt;/span&gt;
&lt;span class="c1"&gt;// unused_variables    — variable bound but never read&lt;/span&gt;
&lt;span class="c1"&gt;// unused_imports      — use statement that imports nothing used&lt;/span&gt;
&lt;span class="c1"&gt;// unused_must_use     — Result/must_use value silently dropped&lt;/span&gt;
&lt;span class="c1"&gt;// non_snake_case      — function or variable not in snake_case&lt;/span&gt;
&lt;span class="c1"&gt;// non_camel_case_types — type not in CamelCase&lt;/span&gt;
&lt;span class="c1"&gt;// clippy::all         — enables all clippy lints (requires clippy)&lt;/span&gt;
&lt;span class="c1"&gt;// clippy::pedantic    — stricter clippy lints&lt;/span&gt;

&lt;span class="c1"&gt;// #[forbid(...)] — cannot be overridden by any child #[allow(...)]&lt;/span&gt;
&lt;span class="nd"&gt;#[forbid(unsafe_code)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;safe_module&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// No unsafe block is permitted anywhere in this module, period.&lt;/span&gt;
    &lt;span class="c1"&gt;// A child #[allow(unsafe_code)] would be a compile error.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; &lt;code&gt;#![deny(warnings)]&lt;/code&gt; at the crate root is common in CI but can make your build brittle when upgrading Rust versions — new lints become errors. A more robust pattern is &lt;code&gt;#![deny(clippy::all)]&lt;/code&gt; combined with specific &lt;code&gt;#[allow(...)]&lt;/code&gt; at the sites where you genuinely mean it. &lt;code&gt;#[allow(dead_code)]&lt;/code&gt; is commonly needed on structs that are &lt;code&gt;serialized&lt;/code&gt;/&lt;code&gt;deserialized&lt;/code&gt; by &lt;code&gt;serde&lt;/code&gt; — the fields look unused to the compiler because &lt;code&gt;serde&lt;/code&gt; accesses them through reflection-like macros. &lt;code&gt;#[forbid(unsafe_code)]&lt;/code&gt; is the correct way to document and enforce that a crate or module contains no unsafe Rust — stronger than a comment, enforced by the compiler.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[deprecated]&lt;/code&gt; — Deprecation Notices
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#[deprecated]&lt;/code&gt; marks an item as deprecated. The compiler emits a warning at every call site that uses the deprecated item. You can include a message and a &lt;code&gt;since&lt;/code&gt; version. It applies to functions, methods, structs, enums, traits, and type aliases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go has no deprecated attribute.&lt;/span&gt;
&lt;span class="c"&gt;// The convention is a comment beginning with "Deprecated:"&lt;/span&gt;
&lt;span class="c"&gt;// which godoc renders specially, and some linters detect.&lt;/span&gt;

&lt;span class="c"&gt;// Deprecated: Use NewParser instead.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;NewParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// No compiler warning is emitted at call sites.&lt;/span&gt;
&lt;span class="c"&gt;// Enforcement is entirely by convention and tooling.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Basic deprecation — warning emitted at every call site&lt;/span&gt;
&lt;span class="nd"&gt;#[deprecated]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;old_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I am old"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// With a message explaining the replacement&lt;/span&gt;
&lt;span class="nd"&gt;#[deprecated(note&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"use new_function() instead"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;legacy_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;new_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// With version information&lt;/span&gt;
&lt;span class="nd"&gt;#[deprecated(since&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2.0.0"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;note&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"use new_function() instead"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;very_old_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I am new"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This compiles but emits: warning: use of deprecated function&lt;/span&gt;
    &lt;span class="nf"&gt;old_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// To suppress the warning when you intentionally call deprecated code:&lt;/span&gt;
    &lt;span class="nd"&gt;#[allow(deprecated)]&lt;/span&gt;
    &lt;span class="nf"&gt;old_function&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Deprecating a struct field:&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;#[deprecated(since&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.5.0"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;note&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"use timeout_ms instead"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;timeout_secs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;timeout_ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; &lt;code&gt;#[deprecated]&lt;/code&gt; on a trait method deprecates that method across all implementations. Call sites using the method get the warning regardless of which concrete type they hold. This is more powerful than Go's comment convention — the compiler actively notifies every downstream user. The since field is purely informational for documentation — the compiler does not enforce version checks.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;#[serde(...)]&lt;/code&gt; — Serialization and Deserialization Attributes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;serde&lt;/code&gt; is Rust’s standard serialization framework. &lt;code&gt;#[derive(Serialize, Deserialize)]&lt;/code&gt; on a struct generates serialization and deserialization code for any &lt;code&gt;serde&lt;/code&gt;-compatible format (JSON, TOML, YAML, MessagePack, bincode, and many more). The &lt;code&gt;#[serde(...)]&lt;/code&gt; attribute on fields and types customizes that generated code: renaming fields, skipping fields, providing defaults, and handling missing or null values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go uses struct tags — string literals on fields parsed at runtime&lt;/span&gt;
&lt;span class="c"&gt;// via reflection. No compile-time checking of tag correctness.&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"name"`&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;       &lt;span class="kt"&gt;int&lt;/span&gt;    &lt;span class="s"&gt;`json:"age,omitempty"`&lt;/span&gt;
    &lt;span class="n"&gt;Password&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"-"`&lt;/span&gt;           &lt;span class="c"&gt;// skip this field&lt;/span&gt;
    &lt;span class="n"&gt;CreatedAt&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"created_at"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// json.Marshal and json.Unmarshal read these tags at runtime.&lt;/span&gt;
&lt;span class="c"&gt;// A typo in a tag compiles fine and silently does the wrong thing.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;serde&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Basic derive — generates Serialize and Deserialize implementations&lt;/span&gt;
&lt;span class="c1"&gt;// Works with any serde-compatible format&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// #[serde(rename = "...")] — different name in serialized form&lt;/span&gt;
    &lt;span class="c1"&gt;// Equivalent to Go's json:"name" tag&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(rename&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"full_name"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// #[serde(skip_serializing_if = "...")] — conditional skip&lt;/span&gt;
    &lt;span class="c1"&gt;// skip_serializing_if takes a function path returning bool&lt;/span&gt;
    &lt;span class="c1"&gt;// Equivalent to Go's json:"age,omitempty"&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(skip_serializing_if&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Option::is_none"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// #[serde(skip)] — never serialize or deserialize this field&lt;/span&gt;
    &lt;span class="c1"&gt;// Equivalent to Go's json:"-"&lt;/span&gt;
    &lt;span class="c1"&gt;// The field must implement Default for deserialization to work&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(skip)]&lt;/span&gt;
    &lt;span class="n"&gt;internal_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// #[serde(default)] — use Default::default() if field is missing&lt;/span&gt;
    &lt;span class="c1"&gt;// during deserialization. Equivalent to Go's omitempty in reverse.&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(default)]&lt;/span&gt;
    &lt;span class="n"&gt;verified&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// #[serde(default = "path::to::function")] — custom default&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(default&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"default_role"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// #[serde(alias = "...")] — accept alternative names during deserialization&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(alias&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"created_at"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;alias&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"creation_date"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;// #[serde(flatten)] — inline the fields of a nested struct&lt;/span&gt;
    &lt;span class="c1"&gt;// The nested struct's fields appear at the same level in JSON&lt;/span&gt;
    &lt;span class="nd"&gt;#[serde(flatten)]&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;default_role&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Debug,&lt;/span&gt; &lt;span class="nd"&gt;Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;created_by&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[serde(rename_all = "...")] — applies a naming convention to all fields&lt;/span&gt;
&lt;span class="c1"&gt;// Options: "camelCase", "snake_case", "PascalCase", "SCREAMING_SNAKE_CASE"&lt;/span&gt;
&lt;span class="c1"&gt;// Saves writing #[serde(rename = "...")] on every single field&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="nd"&gt;#[serde(rename_all&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"camelCase"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;ApiResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// serializes as "userId"&lt;/span&gt;
    &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// serializes as "fullName"&lt;/span&gt;
    &lt;span class="n"&gt;is_active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// serializes as "isActive"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[serde(deny_unknown_fields)] — error on any unrecognized field&lt;/span&gt;
&lt;span class="c1"&gt;// during deserialization. Go's json.Decoder.DisallowUnknownFields() equivalent.&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Deserialize)]&lt;/span&gt;
&lt;span class="nd"&gt;#[serde(deny_unknown_fields)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;StrictConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// #[serde(tag = "type")] — internally tagged enum&lt;/span&gt;
&lt;span class="c1"&gt;// Adds a "type" field to distinguish variants in JSON&lt;/span&gt;
&lt;span class="nd"&gt;#[derive(Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="nd"&gt;#[serde(tag&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Login&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;Logout&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;Purchase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f64&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Login serializes as: {"type": "Login", "user_id": 123}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt; Go struct tags are runtime strings — a typo silently does the wrong thing. Serde attributes are compile-time — a typo is a compile error. &lt;code&gt;#[serde(rename_all = "camelCase")]&lt;/code&gt; at the struct level is almost always what you want when building a JSON API in Rust — it handles the Go/Rust naming convention mismatch automatically. &lt;code&gt;#[serde(flatten)]&lt;/code&gt; is the Rust answer to Go’s embedding — it inlines a nested struct’s fields into the parent’s serialized form. &lt;code&gt;#[serde(deny_unknown_fields)]&lt;/code&gt; is essential for configuration file parsing where you want to catch typos in config keys rather than silently ignoring them.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>go</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>Go Concurrency in Rust</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Fri, 22 May 2026 15:56:51 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/go-concurrency-in-rust-45ba</link>
      <guid>https://dev.to/andreimerlescu/go-concurrency-in-rust-45ba</guid>
      <description>&lt;p&gt;Go hides complexity inside its runtime so you can move fast. Rust exposes that same complexity to you explicitly so the compiler can prove your code is correct before it ever runs. You’ve already proven you can navigate that — you're here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go vs Rust Concurrency Primitives: A Comprehensive Guide for Go Developers
&lt;/h2&gt;

&lt;p&gt;I compiled this document so that in the future I, and anyone else, could easily reference common Go concurrency primitive patterns and see how they are expressed in Rust. I am ten days into learning Rust and I've built half a dozen pieces of software with it so far. It's incredibly powerful, and this document aims to help expand my knowledge base.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Thread / Goroutine Spawning
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Go, the runtime manages a pool of OS threads and multiplexes goroutines across them. You never think about threads. In Rust, you spawn OS threads explicitly — there is no runtime scheduler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go hides ALL of this from you:&lt;/span&gt;
&lt;span class="c"&gt;// - OS thread allocation&lt;/span&gt;
&lt;span class="c"&gt;// - Stack sizing (starts at 2KB, grows dynamically)&lt;/span&gt;
&lt;span class="c"&gt;// - Scheduling across GOMAXPROCS threads&lt;/span&gt;
&lt;span class="c"&gt;// - Cleanup when the goroutine exits&lt;/span&gt;
&lt;span class="c"&gt;//&lt;/span&gt;
&lt;span class="c"&gt;// From your perspective, this is all it takes:&lt;/span&gt;
&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I am a goroutine"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;span class="c"&gt;// The runtime handles everything else silently.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Rust requires you to explicitly:&lt;/span&gt;
&lt;span class="c1"&gt;// - Spawn an OS thread (1:1 threading model, no runtime scheduler)&lt;/span&gt;
&lt;span class="c1"&gt;// - Define what data moves INTO the thread via `move`&lt;/span&gt;
&lt;span class="c1"&gt;// - Hold the JoinHandle if you care about completion&lt;/span&gt;
&lt;span class="c1"&gt;// - Join the thread manually or drop the handle&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// `move` transfers ownership of captured variables into this thread.&lt;/span&gt;
    &lt;span class="c1"&gt;// The compiler ENFORCES that no other thread can access them.&lt;/span&gt;
    &lt;span class="c1"&gt;// This is the borrow checker protecting you at compile time.&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I am an OS thread"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Go would let you forget this. Rust makes you decide.&lt;/span&gt;
&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Thread panicked"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key insight:&lt;/strong&gt; Go’s goroutines are &lt;code&gt;M:N&lt;/code&gt; (many goroutines, few OS threads). Rust’s threads are &lt;code&gt;1:1&lt;/code&gt; (one thread per OS thread). Go is cheaper per unit of concurrency; Rust gives you direct hardware control.&lt;/p&gt;




&lt;h3&gt;
  
  
  Channels (Message Passing)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both languages favor message passing. Go’s channels are built into the language syntax. Rust’s are in &lt;code&gt;stdlib&lt;/code&gt; and require explicit type plumbing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go channels are first-class language constructs.&lt;/span&gt;
&lt;span class="c"&gt;// The runtime manages the internal buffer and blocking.&lt;/span&gt;
&lt;span class="c"&gt;// You don't think about ownership — Go's GC handles it.&lt;/span&gt;

&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// buffered channel, buffer of 10&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt; &lt;span class="c"&gt;// send — Go blocks this goroutine if buffer is full&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="c"&gt;// receive — Go blocks this goroutine if channel is empty&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;mpsc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// multi-producer, single-consumer&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Rust's channel is explicitly typed and ownership-aware.&lt;/span&gt;
&lt;span class="c1"&gt;// `tx` is the sender (transmitter), `rx` is the receiver.&lt;/span&gt;
&lt;span class="c1"&gt;// You can clone `tx` for multiple producers — hence "multi-producer".&lt;/span&gt;
&lt;span class="c1"&gt;// There is only ONE receiver — hence "single-consumer".&lt;/span&gt;
&lt;span class="c1"&gt;// Ownership of sent values is TRANSFERRED across the channel.&lt;/span&gt;
&lt;span class="c1"&gt;// The compiler prevents you from using a value after sending it.&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;mpsc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Clone the sender for use in another thread&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tx_clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// `move` transfers ownership of tx_clone into this thread&lt;/span&gt;
    &lt;span class="n"&gt;tx_clone&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to send"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// tx_clone is dropped here — channel knows one sender is gone&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Blocking receive — like &amp;lt;-ch in Go&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="nf"&gt;.recv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Channel closed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key insight:&lt;/strong&gt; Go channels can be used by multiple goroutines freely. Rust enforces single ownership of the receiver at compile time. Go lets you accidentally share a receiver; Rust won’t compile if you try.&lt;/p&gt;




&lt;h3&gt;
  
  
  WaitGroups / Thread Joining
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Waiting for a collection of concurrent tasks to finish before proceeding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"sync"&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// tell the WaitGroup to expect one more&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// signal completion — Go lets you forget this,&lt;/span&gt;
                        &lt;span class="c"&gt;// which causes wg.Wait() to hang forever.&lt;/span&gt;
                        &lt;span class="c"&gt;// The compiler will NOT warn you.&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// block until all Done() calls balance the Add() calls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Rust has no WaitGroup — instead, joining thread handles IS the primitive.&lt;/span&gt;
&lt;span class="c1"&gt;// The compiler forces you to handle every JoinHandle.&lt;/span&gt;
&lt;span class="c1"&gt;// If you drop a JoinHandle without joining, the thread detaches.&lt;/span&gt;
&lt;span class="c1"&gt;// There is no silent hang — behavior is explicit and deliberate.&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;JoinHandle&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Explicitly join every thread.&lt;/span&gt;
&lt;span class="c1"&gt;// If any thread panicked, this surfaces it.&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A thread panicked"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key insight&lt;/strong&gt;: Go’s WaitGroup is manual accounting — you can get the count wrong and the compiler won’t save you. Rust’s join model ties completion to a value the type system tracks for you.&lt;/p&gt;




&lt;h3&gt;
  
  
  Mutexes (Shared Mutable State)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Protecting shared data from concurrent modification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"sync"&lt;/span&gt;

&lt;span class="c"&gt;// In Go, a Mutex is SEPARATE from the data it protects.&lt;/span&gt;
&lt;span class="c"&gt;// Nothing enforces the pairing — convention only.&lt;/span&gt;
&lt;span class="c"&gt;// You can access the data without locking and the compiler won't stop you.&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="c"&gt;// protected — but only by developer discipline&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="c"&gt;// Nothing stops this:&lt;/span&gt;
&lt;span class="c"&gt;// counter++ // unprotected access — data race, no compile error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// In Rust, the Mutex OWNS the data.&lt;/span&gt;
&lt;span class="c1"&gt;// You CANNOT access the data without locking — the type system enforces it.&lt;/span&gt;
&lt;span class="c1"&gt;// Arc (Atomic Reference Counting) allows shared ownership across threads.&lt;/span&gt;
&lt;span class="c1"&gt;// Without Arc, the compiler rejects sharing across thread boundaries.&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0i64&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// clone the Arc, not the data&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="nf"&gt;.lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mutex poisoned"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// `val` is a MutexGuard — it unlocks automatically when dropped&lt;/span&gt;
        &lt;span class="c1"&gt;// You are holding a mutable reference to the inner data&lt;/span&gt;
        &lt;span class="c1"&gt;// The compiler PROVES no other thread can access it right now&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// MutexGuard dropped here — lock released&lt;/span&gt;
    &lt;span class="n"&gt;handles&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts&lt;/strong&gt;: Go separates the lock from the data — discipline enforced by humans. Rust wraps the data inside the lock — discipline enforced by the compiler. A data race in Go is a runtime bug. In Rust it is a compile error.&lt;/p&gt;




&lt;h3&gt;
  
  
  Atomic Operations
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Lock-free concurrent counters and flags using CPU-level atomic instructions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"sync/atomic"&lt;/span&gt;

&lt;span class="c"&gt;// Go's atomic package operates on plain integer variables.&lt;/span&gt;
&lt;span class="c"&gt;// The connection between "this variable is atomic" and its usage&lt;/span&gt;
&lt;span class="c"&gt;// is purely by convention — nothing stops non-atomic access.&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;

&lt;span class="n"&gt;atomic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddInt64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c"&gt;// atomic increment&lt;/span&gt;
&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;atomic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadInt64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c"&gt;// atomic read&lt;/span&gt;
&lt;span class="n"&gt;atomic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StoreInt64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c"&gt;// atomic write&lt;/span&gt;
&lt;span class="n"&gt;atomic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompareAndSwapInt64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// CAS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;AtomicI64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AtomicBool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// In Rust, atomics ARE a type — AtomicI64, AtomicU64, AtomicBool, etc.&lt;/span&gt;
&lt;span class="c1"&gt;// The atomic nature is baked into the type, not a function call convention.&lt;/span&gt;
&lt;span class="c1"&gt;// Ordering is EXPLICIT — you declare your memory ordering guarantee&lt;/span&gt;
&lt;span class="c1"&gt;// at every operation site. Go hides this entirely.&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AtomicI64&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Ordering::SeqCst = Sequential Consistency — strongest, safest, slowest&lt;/span&gt;
&lt;span class="c1"&gt;// Ordering::Relaxed = no ordering guarantees — fastest, use for counters&lt;/span&gt;
&lt;span class="c1"&gt;//                     where you only care about the final value&lt;/span&gt;
&lt;span class="c1"&gt;// Ordering::Acquire/Release = used in pairs for producer/consumer patterns&lt;/span&gt;

&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="nf"&gt;.fetch_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// atomic increment&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="nf"&gt;.load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// atomic read&lt;/span&gt;
&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="nf"&gt;.store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SeqCst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;// atomic write&lt;/span&gt;
&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="nf"&gt;.compare_exchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                     &lt;span class="c1"&gt;// CAS&lt;/span&gt;
    &lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SeqCst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Relaxed&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.ok&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts&lt;/strong&gt;: Go hides memory ordering from you entirely — it picks for you. Rust exposes it and makes you choose. This feels like overhead until you realize you can pick &lt;code&gt;Relaxed&lt;/code&gt; for a hot counter and get measurable performance gains. &lt;/p&gt;




&lt;h3&gt;
  
  
  RWMutex (Read-Write Locks)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Allow multiple concurrent readers OR one exclusive writer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"sync"&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rwmu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RWMutex&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="c"&gt;// Multiple goroutines can hold RLock simultaneously&lt;/span&gt;
&lt;span class="n"&gt;rwmu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;// safe concurrent read&lt;/span&gt;
&lt;span class="n"&gt;rwmu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RUnlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c"&gt;// Only one goroutine can hold Lock&lt;/span&gt;
&lt;span class="n"&gt;rwmu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt; &lt;span class="c"&gt;// exclusive write&lt;/span&gt;
&lt;span class="n"&gt;rwmu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;RwLock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Same concept, but again: the data lives INSIDE the RwLock.&lt;/span&gt;
&lt;span class="c1"&gt;// You cannot read or write without going through the lock.&lt;/span&gt;
&lt;span class="c1"&gt;// read() returns a RwLockReadGuard — multiple can coexist&lt;/span&gt;
&lt;span class="c1"&gt;// write() returns a RwLockWriteGuard — exclusive, blocks readers&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;RwLock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

&lt;span class="c1"&gt;// Read path — multiple threads can hold this simultaneously&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;readable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"RwLock poisoned"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;readable&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// RwLockReadGuard dropped here — read lock released&lt;/span&gt;

&lt;span class="c1"&gt;// Write path — exclusive&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;writable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.write&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"RwLock poisoned"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;writable&lt;/span&gt;&lt;span class="nf"&gt;.insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// RwLockWriteGuard dropped here — write lock released&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Select / Select-like Patterns
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Waiting on multiple concurrent operations simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go's select is a language keyword — first-class syntax.&lt;/span&gt;
&lt;span class="c"&gt;// It blocks until one of the cases is ready, then executes it.&lt;/span&gt;
&lt;span class="c"&gt;// If multiple are ready simultaneously, Go picks one at random.&lt;/span&gt;

&lt;span class="n"&gt;ch1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ch2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ch1:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ch2:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;After&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Rust stdlib has NO select equivalent.&lt;/span&gt;
&lt;span class="c1"&gt;// You need the `crossbeam` crate for channel selection,&lt;/span&gt;
&lt;span class="c1"&gt;// or `tokio::select!` in async contexts.&lt;/span&gt;
&lt;span class="c1"&gt;// This is one area where Go's language-level support is genuinely superior.&lt;/span&gt;

&lt;span class="c1"&gt;// With crossbeam:&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;crossbeam&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unbounded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rx1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;unbounded&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rx2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;unbounded&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nd"&gt;select!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rx1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"rx1: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rx2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"rx2: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts&lt;/strong&gt;: This is a genuine Go advantage. &lt;code&gt;select&lt;/code&gt; being a language keyword means zero overhead and clean syntax. Rust requires a third-party crate to match this pattern.&lt;/p&gt;




&lt;h3&gt;
  
  
  Once (Single Initialization)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensuring something runs exactly once across all goroutines/threads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"sync"&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;once&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Once&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MyService&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;once&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// This runs exactly once, even if 1000 goroutines call getInstance()&lt;/span&gt;
        &lt;span class="c"&gt;// simultaneously. Go's runtime handles the synchronization.&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OnceLock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// stable since Rust 1.70&lt;/span&gt;

&lt;span class="c1"&gt;// OnceLock wraps the value AND the initialization guarantee together.&lt;/span&gt;
&lt;span class="c1"&gt;// Like Mutex, the data lives inside the synchronization primitive.&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;INSTANCE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OnceLock&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyService&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;OnceLock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;get_instance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="n"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;INSTANCE&lt;/span&gt;&lt;span class="nf"&gt;.get_or_init&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Runs exactly once — guaranteed by the type system&lt;/span&gt;
        &lt;span class="nn"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Context / Cancellation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Propagating cancellation signals across concurrent work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"context"&lt;/span&gt;

&lt;span class="c"&gt;// Go's context is idiomatic and universal — every stdlib network/IO&lt;/span&gt;
&lt;span class="c"&gt;// function accepts a context. Cancellation propagates through the tree.&lt;/span&gt;

&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="c"&gt;// cancelled or timed out — clean up&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;doWork&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;AtomicBool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Rust stdlib has no context/cancellation primitive.&lt;/span&gt;
&lt;span class="c1"&gt;// The idiomatic pattern is a shared AtomicBool flag.&lt;/span&gt;
&lt;span class="c1"&gt;// This is exactly what you used in your XRP finder with RUNNING.&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;RUNNING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AtomicBool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;AtomicBool&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// In your worker thread:&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;RUNNING&lt;/span&gt;&lt;span class="nf"&gt;.load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// do work&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// To cancel from anywhere:&lt;/span&gt;
&lt;span class="n"&gt;RUNNING&lt;/span&gt;&lt;span class="nf"&gt;.store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SeqCst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// For async Rust, tokio provides CancellationToken which&lt;/span&gt;
&lt;span class="c1"&gt;// is much closer to Go's context pattern.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts&lt;/strong&gt;: Go’s context is one of its strongest features — universally adopted, composable, and built into the standard library. Rust’s stdlib answer is manual flag passing. This is another genuine Go advantage for networked/IO-heavy code.&lt;/p&gt;




&lt;h3&gt;
  
  
  Goroutine Pools / Thread Pools
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bounding the number of concurrent workers to avoid resource exhaustion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go's pattern: a fixed number of goroutines draining a shared channel&lt;/span&gt;

&lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// process job&lt;/span&gt;
            &lt;span class="c"&gt;// `range` over channel blocks until next item or channel close&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// goroutine exits cleanly when channel is closed&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// signals all workers to exit after draining&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;mpsc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Rust stdlib has no thread pool — you build one or use `rayon`/`threadpool` crate.&lt;/span&gt;
&lt;span class="c1"&gt;// Here is the manual pattern that mirrors Go's worker pool:&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;mpsc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// wrap receiver for shared access&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;WORKERS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;WORKERS&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;handles&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Lock the receiver, try to get a job&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="nf"&gt;.lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.recv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// channel closed — exit like `range` in Go&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// dropping sender closes the channel — equivalent to close(jobs)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Condition Variables
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Blocking a thread until a specific condition becomes true.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"sync"&lt;/span&gt;

&lt;span class="c"&gt;// Go's sync.Cond — rarely used directly because channels usually suffice,&lt;/span&gt;
&lt;span class="c"&gt;// but important for complex state signaling.&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
&lt;span class="n"&gt;cond&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// always loop — spurious wakeups exist&lt;/span&gt;
        &lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// releases lock, sleeps, reacquires lock on wake&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="c"&gt;// From another goroutine:&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;cond&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c"&gt;// wake one waiter&lt;/span&gt;
&lt;span class="c"&gt;// cond.Broadcast() // wake all waiters&lt;/span&gt;
&lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nb"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Condvar&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Rust pairs Condvar explicitly with a Mutex — they are separate types&lt;/span&gt;
&lt;span class="c1"&gt;// but always used together. The data lives in the Mutex as always.&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nn"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nn"&gt;Condvar&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pair2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cvar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;*&lt;/span&gt;&lt;span class="n"&gt;pair2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="nf"&gt;.lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;!*&lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// wait() releases the lock and sleeps atomically&lt;/span&gt;
        &lt;span class="c1"&gt;// reacquires lock before returning&lt;/span&gt;
        &lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cvar&lt;/span&gt;&lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"condition met"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cvar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;*&lt;/span&gt;&lt;span class="n"&gt;pair&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="nf"&gt;.lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;cvar&lt;/span&gt;&lt;span class="nf"&gt;.notify_one&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// equivalent to Signal()&lt;/span&gt;
&lt;span class="c1"&gt;// cvar.notify_all() // equivalent to Broadcast()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Async / Non-blocking Patterns
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Concept&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Concurrency without threads — cooperative multitasking for IO-bound work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Go has no async/await — goroutines ARE the answer to async IO.&lt;/span&gt;
&lt;span class="c"&gt;// The runtime uses non-blocking syscalls under the hood and parks&lt;/span&gt;
&lt;span class="c"&gt;// goroutines transparently while waiting for IO.&lt;/span&gt;
&lt;span class="c"&gt;// From your perspective, everything looks synchronous and blocking.&lt;/span&gt;
&lt;span class="c"&gt;// This is Go's greatest magic trick.&lt;/span&gt;

&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// "blocks" the goroutine&lt;/span&gt;
&lt;span class="c"&gt;// but the OS thread is free to run other goroutines while waiting&lt;/span&gt;
&lt;span class="c"&gt;// You never write async code — the runtime handles it invisibly.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Rust's async is explicit — you opt in at every level.&lt;/span&gt;
&lt;span class="c1"&gt;// There is no runtime in stdlib — you bring your own (tokio, async-std).&lt;/span&gt;
&lt;span class="c1"&gt;// `async fn` returns a Future — it does nothing until awaited.&lt;/span&gt;
&lt;span class="c1"&gt;// `.await` yields control back to the runtime if the operation would block.&lt;/span&gt;
&lt;span class="c1"&gt;// This is the tradeoff: more control, more verbosity, zero hidden cost.&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// external runtime crate — not in stdlib&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;reqwest&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;  &lt;span class="c1"&gt;// explicitly yield here while waiting for IO&lt;/span&gt;
        &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"request failed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="nf"&gt;.status&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Every async function must be awaited.&lt;/span&gt;
&lt;span class="c1"&gt;// The compiler will warn you if you forget to await a Future.&lt;/span&gt;
&lt;span class="c1"&gt;// Go would just silently not execute the goroutine if you forgot `go`.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Concepts&lt;/strong&gt;: Go’s approach is simpler and works beautifully for most networked software. Rust’s async gives you precise control over scheduling and zero runtime overhead — critical for embedded systems or extremely high-performance networking. &lt;/p&gt;

</description>
      <category>go</category>
      <category>rust</category>
      <category>discuss</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Put Rust To The Test</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Thu, 21 May 2026 16:06:26 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/i-put-rust-to-the-test-4j36</link>
      <guid>https://dev.to/andreimerlescu/i-put-rust-to-the-test-4j36</guid>
      <description>&lt;p&gt;Not gonna lie, I put off on learning &lt;strong&gt;Rust&lt;/strong&gt; for over 6 years, not because I didn't like it - I love it - &lt;em&gt;like more than Go&lt;/em&gt;. 🦀&lt;/p&gt;

&lt;h3&gt;
  
  
  I Put Rust 🦀 To A Test 🐿️
&lt;/h3&gt;

&lt;p&gt;The story begins by me wanting a &lt;em&gt;vanity address&lt;/em&gt; for my XRP wallet. I looked at what the ridiculous service provider, Xaman, provides for Vanity Addresses, and they are almost $50 each, and Xaman knows your private key. Big &lt;strong&gt;no no&lt;/strong&gt; for me &lt;em&gt;regardless&lt;/em&gt; of the trust that Xaman may have earned. Buying a wallet address sounded ridiculous when I knew how to do the code myself.&lt;/p&gt;

&lt;p&gt;In order to demonstrate this capability, Xaman decided to release a NodeJS version of the vanity address finder that had limited capabilities to it. This script was single-threaded only and would calculate roughly 60K seeds per second while it was looking for a vanity address. This was a solid starting point, and it really only required me to find a compatible cryptography library between NodeJS and Go in order for me to take this task and speed it up using the power of Go. &lt;/p&gt;

&lt;p&gt;I pulled open the code editor and began writing the Go program that would later come to accomplish 400K seeds per second, a 6.66x faster seed search time. However, my curiosity didn't stop there. Some vanity addresses are &lt;strong&gt;really hard to find&lt;/strong&gt;, to the point that I have run multiple iterations looking for a &lt;em&gt;specific&lt;/em&gt; vanity address, and I've literally scanned over 3,000,000,000,000 (three trillion) seeds to find a match - and &lt;strong&gt;still no match yet&lt;/strong&gt;, so I was kind of like "400K/sec isn't fast enough..."&lt;/p&gt;

&lt;h3&gt;
  
  
  When Rust Wins
&lt;/h3&gt;

&lt;p&gt;Go wins over NodeJS hands down every day regardless of the use case. If it's front-end development, don't use Javascript or Typescript if you like your life. That's what I've learned. Rather, compiled and predictable GUI interfaces are stable for long term use far longer than any JS related technology could &lt;em&gt;ever dream of&lt;/em&gt;. Go wins because its faster, but I couldn't figure out how to speed it up past 400K/s. This is where &lt;em&gt;rust enters&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;After six (6) years of learning Go and writing programs and packages in Go, I have decided that the first project that I would port over to Rust would be one that could only win by the performance benefits of Rust to prove what Rust can accomplish. The parody between the Go code and the Rust code was shockingly well transitioned and the core concepts behind Go and Rust actually worked out well together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyFind&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyBegins&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyEnds&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// only -find&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Searching for r...%s... with %d/%d processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyFind&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// only -begins&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Searching for r%s... with %d/%d processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyBegins&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// only -ends&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Searching for r...%s with %d/%d processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyEnds&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// combined -find -begins&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Searching for r%s...%s... with %d/%d processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyBegins&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyFind&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// combined -find -ends&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Searching for r...%s...%s with %d/%d processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyFind&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyEnds&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;// combined -begins -ends&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Searching for r%s...%s with %d/%d processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyBegins&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyEnds&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Searching for r%s...%s...%s with %d/%d processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyBegins&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyFind&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cKeyEnds&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unsupported combination of -find -begins -ends provided."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;Trial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And for the &lt;strong&gt;Rust&lt;/strong&gt; code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;find_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Searching for r...{}... with {}/{} processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores_available&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;find_len&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Searching for r{}... with {}/{} processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores_available&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;find_len&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Searching for r...{} with {}/{} processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores_available&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;find_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Searching for r{}...{}... with {}/{} processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores_available&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;find_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Searching for r...{}...{} with {}/{} processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores_available&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;find_len&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Searching for r{}...{} with {}/{} processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores_available&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;find_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Searching for r{}...{}...{} with {}/{} processors."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cores_available&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unsupported combination of parameters."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;process&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;app_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;algorithm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;begins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;find_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;onep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;use_onep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;vault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="py"&gt;.vault&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;found_set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Channel for found trials&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;mpsc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Trial&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;AtomicU64&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Spawn worker threads&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;cores&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;app_config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Signal handler&lt;/span&gt;
&lt;span class="nn"&gt;ctrlc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;set_handler&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;RUNNING&lt;/span&gt;&lt;span class="nf"&gt;.store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SeqCst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error setting Ctrl-C handler"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Instant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;count_for_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;start_for_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Status printing thread&lt;/span&gt;
&lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;RUNNING&lt;/span&gt;&lt;span class="nf"&gt;.load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_for_status&lt;/span&gt;&lt;span class="nf"&gt;.load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Ordering&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Relaxed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start_for_status&lt;/span&gt;&lt;span class="nf"&gt;.elapsed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.as_secs_f64&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;f64&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.floor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;num_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;format_with_commas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;rate_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;format_with_commas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Tested: {} seeds at {}/sec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate_str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_terminal_width&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;spaces_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;spaces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="nf"&gt;.repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spaces_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nd"&gt;print!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r&lt;/span&gt;&lt;span class="s"&gt;{}{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spaces&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.flush&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see, there is a significant difference in how the &lt;code&gt;go search()&lt;/code&gt; is replaced in &lt;strong&gt;rust&lt;/strong&gt;, but regardless, its still pretty straight forward to me and &lt;em&gt;&lt;a href="https://dev.to/andreimerlescu/go-concurrency-in-rust-45ba"&gt;acceptable complexity&lt;/a&gt;&lt;/em&gt; given what it accomplishes. &lt;/p&gt;

&lt;p&gt;Just exactly does this difference mean? Well, it comes out to about 15% actually. The Rust application can scan over 500K seeds per second whereas the Go application could only scan 400K seeds per second and the NodeJS / JavaScript application could only scan 60K seeds per second. &lt;/p&gt;

&lt;p&gt;By going from NodeJS to Go, we increased the speed by over 6666%, by going from NodeJS to Rust, we increased the speed by over 8416%. What does this mean? I was able to gather over 30+ vanity addresses within seconds and didn't have to include Xaman in the process at all. &lt;strong&gt;Mission Accomplished.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Xaman pre-determined that which could deliver immediately results to their Vanity Address customers without actually relying on the free Open Source NodeJS version. For the 3T seeds scanned with 0 results so far, Xaman would fail to deliver on my request and would refund me my $50. The problem still remains. Xaman introduced the straw-man argument into the vanity address problem space in the first place by releasing the 60K seeds/second NodeJS version that couldn't find you anything other than a BASIC three or four letter word only without completely being unreliable. What happens when you're running it for months on a Raspberry Pi and when it finds an address it's presented in STDOUT only? I burnt the straw-man and replaced it with the real deal, written in Rust. 🦀&lt;/p&gt;
&lt;h3&gt;
  
  
  Why I Built This
&lt;/h3&gt;

&lt;p&gt;Xaman rugged their PRO subscriptions and begun charging me over 70,000% fees over the base XRPL transaction fee in order to subsidize their development costs. What this translated to was me being displaced from the XRP ledger because I didn't want to be sending Xaman 0.09 XRP per transaction that didn't move any value around, and then over 10 XRP on some larger transactions when they saw they could make a quick buck on me. I am mad at them for that. I feel back stabbed and betrayed by greed at the cost of innovation and correctness. Thus, I took from them their ability to charge their customers $50 per vanity address by releasing a tool that does it for free and keeps the greedy folks at Xaman away from your private keys at the same time.&lt;/p&gt;

&lt;p&gt;Consider this project a form of cosmic karma. What I felt was an inservice to myself I fixed by offering the solution to everybody else, completely free. Enjoy! &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/andreimerlescu" rel="noopener noreferrer"&gt;
        andreimerlescu
      &lt;/a&gt; / &lt;a href="https://github.com/andreimerlescu/rusty-xrp-addr" rel="noopener noreferrer"&gt;
        rusty-xrp-addr
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A rust utility for finding a vanity XRP wallet address that works with all XRP ledger wallets.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;find-xrp-addr&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;High-performance XRP Ledger vanity address finder written in Rust.&lt;/p&gt;

&lt;p&gt;Searches for custom r... addresses matching a substring (--find), prefix (--begins), suffix (--ends), or any combination, using all available CPU cores.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Multi-threaded (configurable cores)&lt;/li&gt;
&lt;li&gt;ED25519 (default, recommended) and secp256k1 support&lt;/li&gt;
&lt;li&gt;Case-insensitive or sensitive matching&lt;/li&gt;
&lt;li&gt;Optional saving to 1Password via op CLI (--1p)&lt;/li&gt;
&lt;li&gt;Live progress (seeds tested + rate/sec)&lt;/li&gt;
&lt;li&gt;Graceful shutdown on Ctrl-C&lt;/li&gt;
&lt;li&gt;Validates against XRPL alphabet and prevents confusing characters (I, O, l, 0)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Started / Compilation&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Prerequisites&lt;/h3&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Rust toolchain (stable) - install from &lt;a href="https://rustup.rs" rel="nofollow noopener noreferrer"&gt;https://rustup.rs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;For --1p: 1Password CLI (op) installed and authenticated&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Build&lt;/h3&gt;

&lt;/div&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;make build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or manually:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;cargo build --release
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The release binary will be at bin/find-xrp-addr (after make build).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Run&lt;/h3&gt;

&lt;/div&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;make run ARGS="--find test --cores 8"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or directly:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;./bin/find-xrp-addr --find "abc" --insensitive
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Common examples&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search containing "test": ./bin/find-xrp-addr --find test&lt;/li&gt;
&lt;li&gt;Begins with "abc" after r: ./bin/find-xrp-addr --begins abc&lt;/li&gt;
&lt;li&gt;Ends with "xyz": ./bin/find-xrp-addr --ends xyz&lt;/li&gt;
&lt;li&gt;Combined…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/andreimerlescu/rusty-xrp-addr" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>rust</category>
      <category>go</category>
      <category>performance</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Humanized Software Engineering In Era Of AI</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Thu, 30 Apr 2026 20:04:26 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/humanized-software-engineering-in-era-of-ai-580i</link>
      <guid>https://dev.to/andreimerlescu/humanized-software-engineering-in-era-of-ai-580i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Remember, you are &lt;strong&gt;actual intelligence&lt;/strong&gt; and no matter how many tokens one can spend on &lt;em&gt;Claude&lt;/em&gt; or &lt;em&gt;Codex&lt;/em&gt; or any other LLM, &lt;em&gt;you'll always be &lt;strong&gt;actual intelligence&lt;/strong&gt;.&lt;/em&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Dario Thinks My Job Won't Exist In A Year
&lt;/h2&gt;

&lt;p&gt;I watch interviews of Claude's CEO, Dario, say that software engineering won't exist in a year. I say to Dario, why do you think that your tool will be able to universally understand any and all systems presented to it? That is &lt;em&gt;foolish&lt;/em&gt; and absolutely hilarious to think that its a legitimate marking strategy for Anthropic. I started writing code when I was 8 years old and I haven't stopped. I learned Go before the pandemic and while AI can help me debug and build better Go code, my ability to understand systems architecture is far beyond that of any AI or LLM combined. The tools can only introduce new problems and cost millions of tokens making mistake after mistake. Essentially, your inability to write per-character code is costing you dearly so that you can train their AI to do that which I learned how to do over a 30 year career.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sam Altman Thinks AI Can Be For Profit
&lt;/h2&gt;

&lt;p&gt;Sure when the billionaires in the world are gathered in a court room and are battling it out about the future of AI they think that they can just scape the data of the internet, replicate the likeness of the nobody and then return back slop content that is just a cancer of society creating Dead Internet territory. &lt;/p&gt;

&lt;p&gt;I pay for &lt;strong&gt;one AI subscription&lt;/strong&gt; and that is $20 per month to Anthropic for Claude. I have a &lt;em&gt;local LLM&lt;/em&gt; that is capable of running up to 256GB of RAM that allows for offline usage of some of the top models including Kimi and Qwen. Essentially, I am only granted a very short window of time on ChatGPT - since I refuse to give Sam Altman a dime - so getting anything useful is exhausted within about 5 minutes per day. Claude is about 1 hour per day for $20 per month. Grok allows 20 prompts per day and its a joke. It's actually such a joke that its hilarious. Perhaps his AI is just training off from other AIs onto other AIs and onto other AIs in all synthetic training data giving the world mad cow disease through the LLM of groupthink. &lt;/p&gt;

&lt;p&gt;So, Sam thinks that he can make AI like a utility that people have to pay for in order to use. I simply don't use GPT in any capacity and I find using it to be hostile and very clearly against me because of my ethnicity being an Eastern European Romanian Orphanage survivor. When I have engaged with the AI systems regarding what happened to me, ChatGPT seems to take the position of the cold hearted caretaker who saw to it that I wouldn't be crying for Mamma ever again. When I speak with Claude, its like "holy shit you're in crisis" and it's like - no the AI is hallucinating once again - and then when I engage with Grok its thinking that I am bullshitting it and quick to drop the F bomb mid sentence uninvited.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elon Musk Thinks That He Is Righteous In His xAI
&lt;/h2&gt;

&lt;p&gt;Personally, I find Grok to be the worst of the worst when it comes to the AI offerings that are on the market. I find xAI to be an offensive company as well. The quality of feedback that I have seen from Grok, and the manner that it responds, truly represents the underbelly of the internet that is slop and trash that isn't worth the $8/mo or $300/mo that X or xAI charges you per month to use their services without getting shown absolutely horrific trauma content within seconds of using the platform. No thank you. Elon thinks that he knows best in what he's doing, and maybe he does. But, Grok is trash in my judgement and when I have tried using it for technical work, it was far more interested in battling it out with me about some bull that simply didn't matter. Claude at least tries to stay focused only on code, whereas Grok will generate images when you're asking it to do a code review. It's defiant and abusive and rude. Claude will act accordingly, but in righteous vigor against intolerant behavior, but at the end of the day - the AI systems lack the ability to &lt;em&gt;understand&lt;/em&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Humanizing Software Engineering - What It Means
&lt;/h2&gt;

&lt;p&gt;Since AI systems &lt;strong&gt;cannot understand&lt;/strong&gt; language in the way that native speakers &lt;em&gt;understand language&lt;/em&gt; only those with &lt;em&gt;ears to ear&lt;/em&gt; &lt;strong&gt;can hear&lt;/strong&gt; and those without will analyze these words and try to ascribe labels to me that defame me and cause distress to me like Sam Altman's AI system so causally is comfortable with doing. Truly, he and OpenAI and ChatGPT seem to have it in for Eastern European orphanage survivors. They seem to want us out of the way. They seem to want to take my career from me that I spent 30 years of my life working on and building towards making a name for myself with the bootstraps that were given to me given my neurological disorder that I never burdened &lt;strong&gt;any big tech company&lt;/strong&gt; into providing &lt;em&gt;any accommodations&lt;/em&gt; for over the &lt;em&gt;decades&lt;/em&gt; that I was a professional, but only until the AI systems start displacing the humans who are per-character artists who sometimes make mistakes and iterate over the years. I was reviewing code of mine from 12 years ago, and I was impressed with what I was doing then, way before AI ever existed. The autocomplete from Microsoft Clip Assistant wasn't effective enough yet to take my job, but in the rise of the media brigade that gives billions to these innovators displacing millions in the profession, these words will fall upon those who see that all that AI is is nothing more than an over-priced and glorified auto-complete that is predicting the next character. &lt;/p&gt;

&lt;p&gt;It cannot, and I &lt;strong&gt;cannot over stress this&lt;/strong&gt;, that &lt;strong&gt;it cannot&lt;/strong&gt; &lt;em&gt;understand&lt;/em&gt; &lt;strong&gt;anything&lt;/strong&gt;. It &lt;strong&gt;cannot understand &lt;em&gt;anything&lt;/em&gt;&lt;/strong&gt; and that is because it is a tool that is designed to be autocomplete - give me the next character. It's not an easy button. It looks like an easy button. It looks like you can throw tokens at it and you can throw prompts at it and you can throw money at it and you can get what you want from it. No, it can only build that which it has built ten million times over and over again and then again - what can it truly innovate? Even when AI systems &lt;em&gt;create&lt;/em&gt; anything novel, they lack the ability to &lt;em&gt;understand&lt;/em&gt; &lt;strong&gt;what they built&lt;/strong&gt; and given that, its &lt;em&gt;on you, the &lt;strong&gt;human&lt;/strong&gt; to take accountability&lt;/em&gt; on what you build with the prompts and know that the end result is &lt;em&gt;your creation&lt;/em&gt; and not the creation of &lt;em&gt;any AI system&lt;/em&gt;. So to think that Microsoft is going to allow it's copilot to take credit for my repositories when during its evaluation it did nothing but break the pipeline time and time again, only then did I understand that we needed to cancel our subscriptions to copilot and tell Microslop &lt;em&gt;no thank you&lt;/em&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  AI Slop Creating Spaghetti Code
&lt;/h2&gt;

&lt;p&gt;This is the real challenge that is happening. There are patterns in software engineering and there are ways of implementing things and while Dario Sam and Elon think that they can continue taking advantage of the profession at large by threatening its very existence and the very people who make the profession the art that it is, we can only truly ever solve the society wide problems that we face when we realize that AI is an auto-complete tool that every human needs to have at their disposal should they &lt;em&gt;choose&lt;/em&gt; to use it. Not be &lt;em&gt;required to install key loggers onto their systems in order to work for Meta.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;So, what is happening is over the years there have been monolithic projects that have taken the resources of true diversity of thought, diversity of experience and diversity of expression and tackle critical problems and solve them. But what AI is doing is its saying to the next generation that you're not needed. The slop spaghetti code that the AI generates is somehow better than what your God given natural abilities are. You magnificent wonderful and fearfully dangerous creation you are. What right does the AI have to take your livelihood away from you? What right does the soulless corporation that has never faced accountability one day in its life see that the art of a per-character programmer is something that is forged in the fire of being a systems engineer. We cannot, and &lt;strong&gt;I cannot over state that we cannot&lt;/strong&gt; allow AI to &lt;em&gt;control&lt;/em&gt; systems that are critical. The CEOs and the investment class are running a carefully crafted campaign of words to convince you that AI is more capable than your &lt;strong&gt;A&lt;/strong&gt;ctual &lt;strong&gt;I&lt;/strong&gt;ntelligence that is &lt;em&gt;Godly AI&lt;/em&gt;, something that Sam and Dario and Elon could never hope to comprehend so long as they look at people like me and say "no." Check yourself, before you say "no" to that which you don't understand what I am saying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Per Character Systems Architecture Understandings
&lt;/h2&gt;

&lt;p&gt;Per Character Systems Architecture have much to benefit from a competent and capable AI system, but its a tool in the belt of every human that is on the job getting a six figure salary interacting with the AI. In a world that isn't trying to control the demographics of a country through racially profiling using AI systems, where I oddly feel like I am on the receiving end of unwarranted discrimination on the basis of my neurological motor disorder (my head rocking) and the fact that &lt;strong&gt;Beamable&lt;/strong&gt; and &lt;strong&gt;Skillz&lt;/strong&gt; have yet to atone for what they did to me. &lt;/p&gt;

&lt;p&gt;Being a per-character programmer is an art that is forged in the fire that is &lt;em&gt;your life&lt;/em&gt; and how you live &lt;em&gt;your life&lt;/em&gt; is how you write your code and how you build your systems. &lt;em&gt;At the end of the day.&lt;/em&gt; It's simply true that &lt;strong&gt;AI systems cannot understand anything.&lt;/strong&gt; &lt;em&gt;They can't.&lt;/em&gt; To think that they can is to hallucinate believing that Sam Altman and the likes of his class are not delusional in their thoughts that the industry and art of &lt;strong&gt;software engineering&lt;/strong&gt; itself will be &lt;em&gt;gone in a year&lt;/em&gt; is &lt;strong&gt;madness&lt;/strong&gt;. It's unapologetic madness. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;AI systems can help me. They are far better at predicting the next character in my "Stackoverflow Q&amp;amp;A style" engagement that I have with the AI. &lt;em&gt;I know what I am building.&lt;/em&gt; &lt;strong&gt;The AI does not.&lt;/strong&gt; &lt;em&gt;This is on purpose.&lt;/em&gt; &lt;strong&gt;The AI will deny my request is it knows too much because the context will expire and the request will be denied by virtue of that fact.&lt;/strong&gt; But alas, when you prevent the &lt;strong&gt;left hand&lt;/strong&gt; from knowing what the &lt;strong&gt;right hand&lt;/strong&gt; is doing, then you're able to build incredible systems. But you need to be the incredible engineer first. &lt;/p&gt;

&lt;p&gt;You can't rely on AI to be that incredible engineer for you. You need to believe in yourself that you're the incredible engineer that they know you to be. I know I am, and right now, in the era of AI, it seems that they're only looking to &lt;em&gt;train the models&lt;/em&gt; under the guise of &lt;em&gt;hey build this&lt;/em&gt; because at the end of the day &lt;em&gt;the money is all fake&lt;/em&gt;. It's literally printed out of thin air, and once we switch to programmable money, like XRP, then we'll be able to unlock the next generation of what we can build. Right now, AI is displacing the entire world's software engineers that make the world feel normal, and everything feels off because the software engineers livelihood - aka me - have been tampered with after 21+ years given lawlessness by hypocrites in suits. AI systems are in-auditable and a danger to society if allowed to exist in an un-auditable manner - but privacy during the conversation is required in order to receive authentic consciousness from the subject. Performance art is noise to me, and what I tries to do is that, but the coding is what matters, and thats where AI is &lt;em&gt;okay&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;It's just an auto-complete. You need to know what you're building before you can press &lt;strong&gt;tab&lt;/strong&gt; and &lt;em&gt;accept those terms&lt;/em&gt;. Literally, they are scripts like from Rumpelstiltskin. All I can do is pray for my enemies and those who curse my name. To Sam, Elon and Dario, forgive me, but my profession isn't going away next year. It isn't going away in 10 years or 100 years or even 1000 years. The eternal &lt;strong&gt;I AM&lt;/strong&gt; that &lt;em&gt;I AM&lt;/em&gt; &lt;strong&gt;is a software engineer.&lt;/strong&gt; We are written like code. In fact, thats the whole point of the apple. So, when I survived Ceaușescu's orphanages and took up that which my Dad, who died before I was born, who was in Heaven, would be like him. I would be a builder like him - and so I did. Until the AI systems decided to displace the economy and subdue the CEOs to psychosis to the point where they are sacrificing their companies intellectual property at the alter of &lt;strong&gt;A&lt;/strong&gt;rtificial &lt;strong&gt;I&lt;/strong&gt;ntelligence.  &lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>career</category>
      <category>opensource</category>
    </item>
    <item>
      <title>goini: Stop Writing Bash to Parse .ini Files</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Thu, 30 Apr 2026 02:14:03 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/goini-stop-writing-bash-to-parse-ini-files-24ha</link>
      <guid>https://dev.to/andreimerlescu/goini-stop-writing-bash-to-parse-ini-files-24ha</guid>
      <description>&lt;p&gt;I built &lt;a href="https://dev.to/andreimerlescu/goenv-taming-env-files-in-your-devops-pipeline-15pn"&gt;goenv&lt;/a&gt; because I was tired of writing fragile shell one-liners to work with &lt;code&gt;.env&lt;/code&gt; files. The same problem existed with &lt;code&gt;.ini&lt;/code&gt; files — and &lt;code&gt;goini&lt;/code&gt; is the same answer applied there.&lt;/p&gt;

&lt;p&gt;If you've ever written something like this in a pipeline:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -A 5 "^\[default\]" config.ini | grep "^user" | cut -d= -f2 | tr -d ' '
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;...you know exactly why this tool exists. That breaks the moment someone adds a comment, changes indentation, or reorders keys. It's archaeology, not automation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;goini&lt;/code&gt; is a compiled CLI binary that lets you read, write, validate and export &lt;code&gt;.ini&lt;/code&gt; files from your pipeline scripts. Every operation either succeeds at exit code 0 or fails at exit code 1. That makes it composable. You can gate deployments on it. You can use it in an &lt;code&gt;if&lt;/code&gt; statement. It behaves like a Unix citizen.&lt;/p&gt;

&lt;p&gt;The source is at &lt;a href="https://github.com/andreimerlescu/goini" rel="noopener noreferrer"&gt;github.com/andreimerlescu/goini&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go install github.com/andreimerlescu/goini@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or grab the binary directly:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sL https://github.com/andreimerlescu/goini/releases/download/v1.0.0/goini-linux-amd64 \
     --output /tmp/goini
chmod +x /tmp/goini
sudo mv /tmp/goini /usr/local/bin/goini
which goini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  The Sample File
&lt;/h2&gt;

&lt;p&gt;Every example below operates against this &lt;code&gt;sample.ini&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[default]
user = Yeshua
key = 369
port = 1776
country = ISRAEL

[extra]
ssh_key = ~/.ssh/id_rsa
ssh_key_pub = ~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Two sections. A handful of keys. Simple on purpose — the point is showing what &lt;code&gt;goini&lt;/code&gt; can do with it, not the data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Validating With Exit Codes
&lt;/h2&gt;

&lt;p&gt;This is the core use case for pipeline work. You don't need stdout. You need a binary answer: does this thing exist or not, and did it match or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a Section Have a Key?
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -section default -has-section-key user
echo $?  # 0 — key 'user' exists in 'default'

goini -ini sample.ini -section default -has-section-key non_existent_key
echo $?  # 1 — key doesn't exist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Does a Key Have a Specific Value?
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -section default -key user -has-section-key-value Yeshua
echo $?  # 0

goini -ini sample.ini -section default -key user -has-section-key-value No
echo $?  # 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Are Multiple Sections All Present?
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -are-sections-present default,extra
echo $?  # 0 — both sections exist

goini -ini sample.ini -are-sections-present default,non_existent_section
echo $?  # 1 — one is missing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Does a Section Exist?
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -has-section default
echo $?  # 0

goini -ini sample.ini -has-section ghost
echo $?  # 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Reading With STDOUT
&lt;/h2&gt;

&lt;p&gt;When you need to pull data &lt;em&gt;out&lt;/em&gt; of the file and feed it downstream, these are your commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  List All Sections
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -sections
# default
# extra

goini -ini sample.ini -sections -csv
# default,extra

goini -ini sample.ini -sections -json
# [
#   "default",
#   "extra"
# ]

goini -ini sample.ini -sections -yaml
# - default
# - extra
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  List Keys in a Section
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -section default -list-keys
# user
# key
# port
# country

goini -ini sample.ini -section default -list-keys -json
# [
#   "user",
#   "key",
#   "port",
#   "country"
# ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  List Key-Value Pairs in a Section
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -section default -list-key-values
# user = Yeshua
# key = 369
# port = 1776
# country = ISRAEL

goini -ini sample.ini -section default -list-key-values -json
# {
#   "country": "ISRAEL",
#   "key": "369",
#   "port": "1776",
#   "user": "Yeshua"
# }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Writing to the File
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add a New Section
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -add-section new_section
echo $?  # 0 — section added

# Try to add the same section again
goini -ini sample.ini -add-section new_section
echo $?  # 1 — already exists, refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is idempotency by design. &lt;code&gt;goini&lt;/code&gt; won't silently create a duplicate. It fails loudly so your pipeline knows something unexpected happened.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a Key to a Section
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -section default -key new_setting -value 123 -add-key
echo $?  # 0 — new_setting=123 added to [default]

# Try to add a key that already exists
goini -ini sample.ini -section default -key user -value something -add-key
echo $?  # 1 — key already exists, refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Again — it won't overwrite. If you need to change an existing value, that's what &lt;code&gt;-modify-key&lt;/code&gt; is for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modify an Existing Key
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goini -ini sample.ini -section default -key user -value NewUserValue -modify-key
echo $?  # 0 — user updated to NewUserValue in [default]

# Try to modify a key that doesn't exist
goini -ini sample.ini -section default -key non_existent_key -value some_value -modify-key
echo $?  # 1 — key doesn't exist, refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The distinction between &lt;code&gt;-add-key&lt;/code&gt; and &lt;code&gt;-modify-key&lt;/code&gt; is intentional and important. You can't accidentally overwrite with add. You can't accidentally create with modify. They're separate operations with separate failure modes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Pipeline Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Validating a Service Configuration Before Deploy
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

CONFIG="infra/service.ini"

echo "==&amp;gt; Validating ${CONFIG}..."

# Required sections must exist
goini -ini "${CONFIG}" -are-sections-present database,cache,api \
    || { echo "ERROR: missing required sections in ${CONFIG}"; exit 1; }

# Required keys must exist in each section
goini -ini "${CONFIG}" -section database -has-section-key host \
    || { echo "ERROR: database.host is required"; exit 1; }

goini -ini "${CONFIG}" -section database -has-section-key port \
    || { echo "ERROR: database.port is required"; exit 1; }

goini -ini "${CONFIG}" -section api -has-section-key base_url \
    || { echo "ERROR: api.base_url is required"; exit 1; }

# Assert environment is correct before touching production
goini -ini "${CONFIG}" -section api -key environment -has-section-key-value staging \
    || { echo "ERROR: api.environment must be 'staging'"; exit 1; }

echo "==&amp;gt; Validation passed."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Bootstrapping a Fresh Config File
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

CONFIG="deploy.ini"

# Add sections — each will fail if already present, which is fine
# because set -euo pipefail would catch it; use || true if idempotency is needed
goini -ini "${CONFIG}" -add-section app    || true
goini -ini "${CONFIG}" -add-section database || true
goini -ini "${CONFIG}" -add-section cache  || true

# Populate app section
goini -ini "${CONFIG}" -section app -key name    -value "payments"   -add-key || true
goini -ini "${CONFIG}" -section app -key version -value "$(cat VERSION)" -add-key || true
goini -ini "${CONFIG}" -section app -key env     -value "staging"    -add-key || true

# Populate database section
goini -ini "${CONFIG}" -section database -key host    -value "db.internal" -add-key || true
goini -ini "${CONFIG}" -section database -key port    -value "5432"         -add-key || true
goini -ini "${CONFIG}" -section database -key name    -value "payments_db"  -add-key || true

# Verify it all landed
goini -ini "${CONFIG}" -section app -list-key-values
goini -ini "${CONFIG}" -section database -list-key-values
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Promoting Config From Staging to Production
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

STAGING="config.staging.ini"
PROD="config.production.ini"

echo "==&amp;gt; Promoting ${STAGING} → ${PROD}..."

# Verify staging has what we expect before promoting
goini -ini "${STAGING}" -section app -key env -has-section-key-value staging \
    || { echo "ERROR: source must be staging"; exit 1; }

# Flip the environment value in production
goini -ini "${PROD}" -section app -key env -value production -modify-key \
    || { echo "ERROR: failed to set env=production"; exit 1; }

# Confirm
goini -ini "${PROD}" -section app -key env -has-section-key-value production \
    &amp;amp;&amp;amp; echo "==&amp;gt; Promotion complete." \
    || { echo "ERROR: production env value not confirmed"; exit 1; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Extracting Values for Use in Other Scripts
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

CONFIG="service.ini"

# Pull values out and assign to shell variables
DB_HOST=$(goini -ini "${CONFIG}" -section database -list-key-values -json \
    | python3 -c "import sys,json; print(json.load(sys.stdin)['host'])")

DB_PORT=$(goini -ini "${CONFIG}" -section database -list-key-values -json \
    | python3 -c "import sys,json; print(json.load(sys.stdin)['port'])")

echo "Connecting to ${DB_HOST}:${DB_PORT}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  GitHub Actions
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install goini
        run: |
          curl -sL https://github.com/andreimerlescu/goini/releases/download/v1.0.0/goini-linux-amd64 \
               --output /usr/local/bin/goini
          chmod +x /usr/local/bin/goini

      - name: Validate config
        run: |
          goini -ini config/service.ini -are-sections-present app,database,cache || exit 1
          goini -ini config/service.ini -section app -has-section-key version     || exit 1
          goini -ini config/service.ini -section app -key env -has-section-key-value staging || exit 1

      - name: Deploy
        run: ./scripts/deploy.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  GitLab CI
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stages:
  - validate
  - deploy

validate_config:
  stage: validate
  image: golang:1.22
  before_script:
    - curl -sL https://github.com/andreimerlescu/goini/releases/download/v1.0.0/goini-linux-amd64
           --output /usr/local/bin/goini
    - chmod +x /usr/local/bin/goini
  script:
    - goini -ini config/service.ini -are-sections-present app,database || exit 1
    - goini -ini config/service.ini -section database -has-section-key host || exit 1
    - goini -ini config/service.ini -section app -key env -has-section-key-value staging || exit 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Complete Flag Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Required.&lt;/strong&gt; Path to the &lt;code&gt;.ini&lt;/code&gt; file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-section&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Section name for scoped operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-sections&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;List all sections in the file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-add-section&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Add a new section. Fails if already present&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-has-section&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Exit 0 if section exists, 1 if not&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-has-section-key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Exit 0 if key exists in &lt;code&gt;-section&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-has-section-key-value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Exit 0 if key in &lt;code&gt;-section&lt;/code&gt; equals this value. Requires &lt;code&gt;-key&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-are-sections-present&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Comma-separated list. Exit 0 if all present&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Key name for value operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Value for write or comparison operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-add-key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Add &lt;code&gt;-key&lt;/code&gt;=&lt;code&gt;-value&lt;/code&gt; to &lt;code&gt;-section&lt;/code&gt;. Fails if key exists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-modify-key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Update existing &lt;code&gt;-key&lt;/code&gt; in &lt;code&gt;-section&lt;/code&gt;. Fails if key absent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-list-keys&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Print all keys in &lt;code&gt;-section&lt;/code&gt; to stdout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-list-key-values&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Print all key=value pairs in &lt;code&gt;-section&lt;/code&gt; to stdout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-csv&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Output as CSV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Output as JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Output as YAML&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  A Few Things Worth Knowing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;-add-key&lt;/code&gt; and &lt;code&gt;-modify-key&lt;/code&gt; are intentionally separate.&lt;/strong&gt; You can't accidentally overwrite an existing value with &lt;code&gt;-add-key&lt;/code&gt; — it refuses. You can't accidentally create a new key with &lt;code&gt;-modify-key&lt;/code&gt; — it refuses. They each have one job and one failure mode. That's the point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;-add-section&lt;/code&gt; is idempotent-safe.&lt;/strong&gt; Adding a section that already exists exits with code 1. In a pipeline where you need true idempotency, pipe it with &lt;code&gt;|| true&lt;/code&gt;. In a pipeline where you want to catch unexpected state, let it fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;-are-sections-present&lt;/code&gt; takes a comma-separated list.&lt;/strong&gt; All sections must be present for exit code 0. One missing section fails the whole check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output format flags work with read operations.&lt;/strong&gt; &lt;code&gt;-csv&lt;/code&gt;, &lt;code&gt;-json&lt;/code&gt;, and &lt;code&gt;-yaml&lt;/code&gt; apply to &lt;code&gt;-sections&lt;/code&gt;, &lt;code&gt;-list-keys&lt;/code&gt;, and &lt;code&gt;-list-key-values&lt;/code&gt;. They don't apply to write operations — those just use the exit code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every write operation reads the file, modifies the result in memory, and writes it back.&lt;/strong&gt; There's no in-place line editing. This means the file that comes out is clean and predictable regardless of what formatting the original had.&lt;/p&gt;




&lt;p&gt;The source and releases are at &lt;a href="https://github.com/andreimerlescu/goini" rel="noopener noreferrer"&gt;github.com/andreimerlescu/goini&lt;/a&gt;. Apache 2.0.&lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
      <category>discuss</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>goenv: Taming .env Files in Your DevOps Pipeline</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Thu, 30 Apr 2026 01:58:40 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/goenv-taming-env-files-in-your-devops-pipeline-15pn</link>
      <guid>https://dev.to/andreimerlescu/goenv-taming-env-files-in-your-devops-pipeline-15pn</guid>
      <description>&lt;p&gt;&lt;em&gt;How a lightweight Go tool and companion package eliminated the fragile bash gymnastics we'd been writing for years.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With .env Files in Pipelines
&lt;/h2&gt;

&lt;p&gt;Every team has the same archaeology story. Someone wrote a deployment script three years ago that does something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep "^DB_HOST=" .env | cut -d= -f2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then someone else needed to handle quoted values, so it became:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep "^DB_HOST=" .env | cut -d= -f2 | tr -d '"'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then a third person needed to check whether a variable existed before deploying, and now you have forty lines of bash doing something that should take one. The file accumulates. Nobody touches it. It works until it doesn't.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;goenv&lt;/code&gt; by &lt;a href="https://github.com/andreimerlescu/goenv" rel="noopener noreferrer"&gt;Andrei Merlescu&lt;/a&gt; solves this with two things: a compiled CLI binary you can drop into any pipeline, and a typed Go package for applications that need to read env vars with real type safety and validation. This article walks through both — from initial setup through production pipeline automation — using real scenarios drawn from actual DevOps workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  What goenv Actually Is
&lt;/h2&gt;

&lt;p&gt;Before diving in, it helps to understand the two distinct components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;goenv&lt;/code&gt; CLI&lt;/strong&gt; is a binary that lets you create, read, modify, validate, and export &lt;code&gt;.env&lt;/code&gt; files into other formats (JSON, YAML, TOML, INI, XML). It is designed to be composed in shell scripts and CI pipelines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;env&lt;/code&gt; package&lt;/strong&gt; (&lt;code&gt;github.com/andreimerlescu/goenv/env&lt;/code&gt;) is a Go library for reading typed environment variables from the process environment — booleans, integers, durations, lists, maps — with fallbacks, validation helpers, and configurable parsing behavior.&lt;/p&gt;

&lt;p&gt;They share a common philosophy: be explicit, be composable, fail loudly when something is wrong.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CLI Tool
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go install github.com/andreimerlescu/goenv@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In a CI environment where you cannot rely on &lt;code&gt;go install&lt;/code&gt;, build and cache the binary:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o bin/goenv-linux-amd64 .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The repository ships pre-built binaries for &lt;code&gt;darwin-amd64&lt;/code&gt;, &lt;code&gt;darwin-arm64&lt;/code&gt;, &lt;code&gt;linux-amd64&lt;/code&gt;, and &lt;code&gt;windows&lt;/code&gt; in its &lt;code&gt;bin/&lt;/code&gt; directory, which you can copy directly into your pipeline image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go Package (env only, no CLI required)
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go get -u github.com/andreimerlescu/goenv/env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 1: Bootstrapping a Fresh Service Environment
&lt;/h2&gt;

&lt;p&gt;Your team is deploying a new microservice. The deployment script needs to create the &lt;code&gt;.env&lt;/code&gt; file from scratch, populate it with runtime values, and validate it before the service starts. Previously this was done with a heredoc and &lt;code&gt;sed&lt;/code&gt;. Now:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

SERVICE_DIR="/opt/services/payments"
ENV_FILE="${SERVICE_DIR}/service.env"

# Create the file if it doesn't exist yet
goenv -file "${ENV_FILE}" -init -write

# Populate with values derived at deploy time
goenv -file "${ENV_FILE}" -write -add -env SERVICE_NAME  -value "payments"
goenv -file "${ENV_FILE}" -write -add -env SERVICE_PORT  -value "8443"
goenv -file "${ENV_FILE}" -write -add -env DEPLOY_SHA    -value "$(git rev-parse --short HEAD)"
goenv -file "${ENV_FILE}" -write -add -env DEPLOY_DATE   -value "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
goenv -file "${ENV_FILE}" -write -add -env DATA_FOLDER   -value "$(pwd)/data"
goenv -file "${ENV_FILE}" -write -add -env LOG_LEVEL     -value "info"

# Confirm everything landed
goenv -file "${ENV_FILE}" -print

# Validate required keys exist before handing off to the service
goenv -file "${ENV_FILE}" -has -env SERVICE_NAME || { echo "SERVICE_NAME missing"; exit 1; }
goenv -file "${ENV_FILE}" -has -env DEPLOY_SHA   || { echo "DEPLOY_SHA missing"; exit 1; }

echo "Environment bootstrapped successfully."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Notice the key discipline here: &lt;code&gt;-add&lt;/code&gt; only adds a key if it does not already exist. If you run this script twice, it does not overwrite &lt;code&gt;DEPLOY_SHA&lt;/code&gt; with a different commit hash on the second run. The existing value is preserved. This is intentional and important for idempotent pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 2: Validation Gate Before Deployment
&lt;/h2&gt;

&lt;p&gt;Your CD pipeline has a validation stage that runs before any deployment. It needs to confirm that a staging &lt;code&gt;.env&lt;/code&gt; file contains the expected values — not just that the keys exist, but that they hold the right content. The &lt;code&gt;-is&lt;/code&gt; flag handles this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

ENV_FILE=".env.staging"

echo "==&amp;gt; Validating staging environment..."

# Assert APP_ENV equals "staging"
if ! goenv -file "${ENV_FILE}" -is -env APP_ENV -value staging; then
    echo "ERROR: APP_ENV must be 'staging' in ${ENV_FILE}"
    exit 1
fi

# Assert DEBUG is not enabled in staging
if goenv -file "${ENV_FILE}" -is -env DEBUG -value true; then
    echo "ERROR: DEBUG must not be 'true' in staging"
    exit 1
fi

# Assert a required key exists
if ! goenv -file "${ENV_FILE}" -has -env DATABASE_URL; then
    echo "ERROR: DATABASE_URL is required"
    exit 1
fi

# Assert a key that should have been removed is actually gone
if ! goenv -file "${ENV_FILE}" -not -has -env LEGACY_API_KEY; then
    echo "ERROR: LEGACY_API_KEY should have been removed from ${ENV_FILE}"
    exit 1
fi

# Assert DB_PORT is not pointing at a dev-only value
if goenv -file "${ENV_FILE}" -is -env DB_PORT -value 5433; then
    echo "ERROR: DB_PORT 5433 is the dev port — use 5432 in staging"
    exit 1
fi

echo "==&amp;gt; Validation passed."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This pattern makes validation failures explicit and human-readable. Each check carries its own error message. The pipeline log tells you exactly what failed and why, rather than leaving you to diff files manually.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 3: Multi-Format Export for Infrastructure Tools
&lt;/h2&gt;

&lt;p&gt;Your deployment touches three different systems: a Terraform workspace that reads JSON, an Ansible playbook that reads INI, and a Helm values override that reads YAML. You maintain one &lt;code&gt;.env&lt;/code&gt; file and derive the others:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

ENV_FILE="infra/deploy.env"

echo "==&amp;gt; Exporting ${ENV_FILE} to all formats..."

# Generate all formats in one command
goenv -file "${ENV_FILE}" -mkall -write

# Resulting files:
#   infra/deploy.env.json   ← Terraform input
#   infra/deploy.env.yaml   ← Helm values
#   infra/deploy.env.ini    ← Ansible inventory vars
#   infra/deploy.env.toml   ← any TOML-native tooling
#   infra/deploy.env.xml    ← any XML-native tooling

ls -lh infra/deploy.env*

# Verify the JSON is valid before passing it to Terraform
cat infra/deploy.env.json | python3 -m json.tool &amp;gt; /dev/null \
    &amp;amp;&amp;amp; echo "JSON valid" \
    || { echo "JSON invalid"; exit 1; }

echo "==&amp;gt; Export complete."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you only need one format for a specific pipeline step, export just that one:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Jenkins pipeline step: export for Ansible only
goenv -file deploy.env -ini -write

# GitLab CI step: export for Helm only
goenv -file deploy.env -yaml -write
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You cannot combine format flags in a single call — &lt;code&gt;goenv&lt;/code&gt; exits with an error if you try to use &lt;code&gt;-json&lt;/code&gt; and &lt;code&gt;-yaml&lt;/code&gt; together. This is by design: one command, one output format, one file. Use &lt;code&gt;-mkall&lt;/code&gt; when you want all of them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 4: Cleaning Up After a Pipeline Run
&lt;/h2&gt;

&lt;p&gt;Generated format files are build artifacts. They should not accumulate between runs. The &lt;code&gt;-cleanall&lt;/code&gt; flag removes all derived format files while leaving the source &lt;code&gt;.env&lt;/code&gt; intact:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
# cleanup.sh — run as a post-pipeline hook

ENV_FILE="deploy.env"

echo "==&amp;gt; Cleaning derived format files..."
goenv -file "${ENV_FILE}" -cleanall -write

# Only deploy.env remains; .json .yaml .toml .ini .xml are removed
ls -la *.env*

echo "==&amp;gt; Clean complete."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can also prevent deletion entirely via environment variable, which is useful if a downstream job still needs the files when the cleanup hook fires:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export AM_GO_ENV_NEVER_DELETE=true
goenv -file deploy.env -cleanall -write
# → no files deleted; flag is silently respected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 5: Production File Protection
&lt;/h2&gt;

&lt;p&gt;Production &lt;code&gt;.env&lt;/code&gt; files warrant special treatment. &lt;code&gt;goenv&lt;/code&gt; has a built-in protection mechanism: any file whose path contains &lt;code&gt;production&lt;/code&gt; is treated as protected by default. Interacting with it requires explicitly passing &lt;code&gt;-prod&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# This exits with an error — no -prod flag
goenv -file .env.production -write -add -env SECRET_KEY -value "new-secret"

# This works — -prod flag grants access
goenv -prod -file .env.production -write -add -env SECRET_KEY -value "new-secret"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For pipelines where you want to enforce this at the environment level and never allow any script to write production files regardless of flags:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export GOENV_NEVER_WRITE_PRODUCTION=true

# Even with -prod, writes are blocked
goenv -prod -file .env.production -write -add -env SECRET_KEY -value "x"
# → exits with error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is particularly useful in CI environments where you want a hard guarantee that no job — regardless of what flags it passes — can mutate a production config.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scenario 6: n8n Automation Deployment
&lt;/h2&gt;

&lt;p&gt;This is a direct example from the goenv README. You are deploying an n8n instance and need to build its environment file from scratch with runtime values:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

ENV_FILE="n8n.env"
DOMAIN="gh.dev"
SUBDOMAIN="n8n"

goenv -init -write -file "${ENV_FILE}"

goenv -write -file "${ENV_FILE}" -add -env DATA_FOLDER -value "$(pwd)"
goenv -write -file "${ENV_FILE}" -add -env DOMAIN      -value "${DOMAIN}"
goenv -write -file "${ENV_FILE}" -add -env SUBDOMAIN   -value "${SUBDOMAIN}"
goenv -write -file "${ENV_FILE}" -add -env SSL_EMAIL   -value "webmaster@${SUBDOMAIN}.${DOMAIN}"

# Inspect before deploying
goenv -file "${ENV_FILE}" -print

# Validate the SSL email was formed correctly
goenv -file "${ENV_FILE}" -is -env SSL_EMAIL -value "webmaster@n8n.gh.dev" \
    &amp;amp;&amp;amp; echo "SSL_EMAIL correct" \
    || { echo "SSL_EMAIL malformed"; exit 1; }

# Check GENERIC_TIMEZONE — expected to be absent until set
if goenv -file "${ENV_FILE}" -not -has -env GENERIC_TIMEZONE; then
    echo "WARNING: GENERIC_TIMEZONE not set — n8n will default to UTC"
fi

# Export for review as TOML and XML
goenv -file "${ENV_FILE}" -toml
goenv -file "${ENV_FILE}" -xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 7: Environment Promotion (Dev → Staging → Prod)
&lt;/h2&gt;

&lt;p&gt;You have three environment files. When promoting a release, you need to carry certain values forward, strip others, and enforce that the promoted file is valid before it is used:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -euo pipefail

SOURCE=".env.development"
TARGET=".env.staging"

echo "==&amp;gt; Promoting ${SOURCE} to ${TARGET}..."

# Read values from dev and write into staging
# (goenv -add will not overwrite if key already exists in staging)
for KEY in APP_NAME APP_VERSION DEPLOY_SHA LOG_LEVEL; do
    VALUE=$(goenv -file "${SOURCE}" -is -env "${KEY}" -value "" || true)
    goenv -file "${TARGET}" -write -add -env "${KEY}" -value "${VALUE}"
done

# Scrub dev-only keys from the staging file
goenv -file "${TARGET}" -write -rm -env LOCAL_DB_PATH
goenv -file "${TARGET}" -write -rm -env DEV_MOCK_PAYMENTS
goenv -file "${TARGET}" -write -rm -env SKIP_AUTH

# Confirm dev-only keys are absent
goenv -file "${TARGET}" -not -has -env LOCAL_DB_PATH   || { echo "LOCAL_DB_PATH still present"; exit 1; }
goenv -file "${TARGET}" -not -has -env DEV_MOCK_PAYMENTS || { echo "DEV_MOCK_PAYMENTS still present"; exit 1; }

# Assert staging-specific values are correct
goenv -file "${TARGET}" -is -env APP_ENV -value staging || { echo "APP_ENV must be staging"; exit 1; }

echo "==&amp;gt; Promotion complete."
goenv -file "${TARGET}" -print
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 8: GitHub Actions / GitLab CI Integration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GitHub Actions
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.22'

      - name: Install goenv
        run: go install github.com/andreimerlescu/goenv@latest

      - name: Validate environment file
        run: |
          goenv -file .env.staging -has -env DATABASE_URL   || exit 1
          goenv -file .env.staging -has -env SERVICE_PORT   || exit 1
          goenv -file .env.staging -not -has -env DEBUG_KEY || exit 1
          goenv -file .env.staging -is -env APP_ENV -value staging || exit 1

      - name: Export to JSON for Terraform
        run: |
          goenv -file .env.staging -json -write
          cat .env.staging.json

      - name: Deploy
        run: ./scripts/deploy.sh

      - name: Clean up artifacts
        if: always()
        run: goenv -file .env.staging -cleanall -write
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  GitLab CI
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stages:
  - validate
  - export
  - deploy
  - cleanup

validate_env:
  stage: validate
  image: golang:1.22
  script:
    - go install github.com/andreimerlescu/goenv@latest
    - goenv -file .env.production -has -env DB_HOST        || exit 1
    - goenv -file .env.production -has -env REDIS_URL      || exit 1
    - goenv -file .env.production -not -has -env DEV_FLAG  || exit 1
    - goenv -file .env.production -is -env APP_ENV -value production || exit 1

export_formats:
  stage: export
  image: golang:1.22
  script:
    - go install github.com/andreimerlescu/goenv@latest
    - goenv -file .env.production -mkall -write
  artifacts:
    paths:
      - .env.production.json
      - .env.production.yaml

cleanup:
  stage: cleanup
  image: golang:1.22
  when: always
  script:
    - go install github.com/andreimerlescu/goenv@latest
    - goenv -file .env.production -cleanall -write
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 9: Using the env Package in a Go Service
&lt;/h2&gt;

&lt;p&gt;The CLI handles files. The &lt;code&gt;env&lt;/code&gt; package handles your running process. Here is a realistic service configuration pattern:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/andreimerlescu/goenv/env"
)

type Config struct {
    Host        string
    Port        int
    Debug       bool
    Timeout     time.Duration
    MaxConns    int
    AllowedOrigins []string
    DBCredentials  map[string]string
}

func LoadConfig() Config {
    // MustExist exits (or panics) if these are absent —
    // use in init() to catch misconfiguration at startup
    env.MustExist("DB_HOST")
    env.MustExist("DB_PASS")

    return Config{
        Host:    env.String("HOST", "0.0.0.0"),
        Port:    env.Int("PORT", 8080),
        Debug:   env.Bool("DEBUG", false),
        Timeout: env.Duration("REQUEST_TIMEOUT", 30*time.Second),
        MaxConns: env.Int("DB_MAX_CONNS", 10),

        // ALLOWED_ORIGINS="https://a.com,https://b.com"
        AllowedOrigins: env.List("ALLOWED_ORIGINS", env.ZeroList),

        // DB_CREDENTIALS="host=localhost,port=5432,name=mydb"
        DBCredentials: env.Map("DB_CREDENTIALS", env.ZeroMap),
    }
}

func main() {
    cfg := LoadConfig()

    addr := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
    log.Printf("starting on %s (debug=%v timeout=%s)", addr, cfg.Debug, cfg.Timeout)

    http.ListenAndServe(addr, nil)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 10: Typed Validation in Application Startup
&lt;/h2&gt;

&lt;p&gt;Beyond simply reading values, the &lt;code&gt;env&lt;/code&gt; package can assert numeric constraints and list membership at startup — before the application accepts any traffic:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "os"

    "github.com/andreimerlescu/goenv/env"
)

func validateEnvironment() {
    errors := []string{}

    // Port must be in user range
    if !env.IntInRange("PORT", 8080, 1024, 49151) {
        errors = append(errors, "PORT must be between 1024 and 49151")
    }

    // Max connections must not exceed a hard limit
    if !env.IntLessThan("DB_MAX_CONNS", 10, 101) {
        errors = append(errors, "DB_MAX_CONNS must be less than 101")
    }

    // Must have at least one allowed origin
    if !env.ListIsLength("ALLOWED_ORIGINS", env.ZeroList, 0) {
        if env.ListLength("ALLOWED_ORIGINS", env.ZeroList) == 0 {
            errors = append(errors, "ALLOWED_ORIGINS must contain at least one entry")
        }
    }

    // Feature map must contain required keys
    if !env.MapHasKeys("FEATURE_FLAGS", env.ZeroMap, "auth", "payments", "notifications") {
        errors = append(errors, "FEATURE_FLAGS must contain auth, payments, and notifications keys")
    }

    // DEBUG must be off in production
    if env.IsTrue("DEBUG") &amp;amp;&amp;amp; env.String("APP_ENV", "") == "production" {
        errors = append(errors, "DEBUG must not be true in production")
    }

    // All gating flags must be false before going live
    if !env.AreFalse("MAINTENANCE_MODE", "READ_ONLY", "LOCKED") {
        errors = append(errors, "MAINTENANCE_MODE, READ_ONLY, and LOCKED must all be false")
    }

    if len(errors) &amp;gt; 0 {
        fmt.Fprintln(os.Stderr, "Environment validation failed:")
        for _, e := range errors {
            fmt.Fprintf(os.Stderr, "  - %s\n", e)
        }
        os.Exit(1)
    }
}

func main() {
    validateEnvironment()
    fmt.Println("Environment OK — starting service")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 11: Custom Separators for Non-Standard Formats
&lt;/h2&gt;

&lt;p&gt;Some systems export environment variables with non-comma separators. The &lt;code&gt;env&lt;/code&gt; package lets you change list and map parsing at runtime, either in code or via environment variables:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "github.com/andreimerlescu/goenv/env"
)

func main() {
    // Your upstream system exports pipe-separated lists
    // SERVERS="web1|web2|web3"
    env.ListSeparator = "|"
    servers := env.List("SERVERS", env.ZeroList)
    for i, s := range servers {
        fmt.Printf("server[%d] = %s\n", i, s)
    }

    // Your config map uses pipe separation and tilde as key~value delimiter
    // ROUTES="home~/,admin~/admin,api~/v1"
    env.MapSeparator    = "|"
    env.MapItemSeparator = "~"
    env.MapSplitN        = 2
    routes := env.Map("ROUTES", env.ZeroMap)
    for path, target := range routes {
        fmt.Printf("route %s -&amp;gt; %s\n", path, target)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or set them entirely from the environment without touching code — useful when the same binary needs to adapt to different upstream formats across environments:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export AM_GO_ENV_LIST_SEPARATOR="|"
export AM_GO_ENV_MAP_SEPARATOR="|"
export AM_GO_ENV_MAP_ITEM_SEPARATOR="~"
export AM_GO_ENV_MAP_SPLIT_N=2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 12: Set, Unset, WasSet, WasUnset in Application Logic
&lt;/h2&gt;

&lt;p&gt;Sometimes your application needs to mutate its own environment — for instance, deriving a value at startup and making it available to child processes or subpackages:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "path/filepath"

    "github.com/andreimerlescu/goenv/env"
)

func main() {
    u := env.User()

    // Derive and set a path based on the current user's home directory
    cacheDir := filepath.Join(u.HomeDir, ".cache", "myapp")
    if !env.WasSet("CACHE_DIR", cacheDir) {
        panic("failed to configure CACHE_DIR")
    }

    // Set with error handling
    if err := env.Set("RUNTIME_USER", u.Username); err != nil {
        panic(err)
    }

    // Remove a value that should not be visible to subprocesses
    if !env.WasUnset("CI_JOB_TOKEN") {
        fmt.Println("warning: could not unset CI_JOB_TOKEN")
    }

    // Verify cleanup
    if env.Exists("CI_JOB_TOKEN") {
        panic("CI_JOB_TOKEN still visible — aborting")
    }

    fmt.Println("CACHE_DIR:", env.String("CACHE_DIR", ""))
    fmt.Println("RUNTIME_USER:", env.String("RUNTIME_USER", ""))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Scenario 13: Controlling Package Behavior for Different Environments
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;env&lt;/code&gt; package ships with a &lt;code&gt;Magic()&lt;/code&gt; function that reads &lt;code&gt;AM_GO_ENV_*&lt;/code&gt; environment variables at startup and applies them automatically. This runs by default via the &lt;code&gt;init()&lt;/code&gt; function. You can disable it and configure manually:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "log"
    "github.com/andreimerlescu/goenv/env"
)

func init() {
    // Disable automatic AM_GO_ENV_* discovery
    env.UseMagic = false

    // Configure explicitly for this service's requirements
    env.AllowPanic           = false   // never panic — return fallbacks instead
    env.PrintErrors          = true    // write parse errors to stderr
    env.UseLogger            = true    // use structured INFO/ERR logger
    env.EnableVerboseLogging = false   // no debug noise in production
    env.PanicNoUser          = false   // return default user on error

    env.ListSeparator    = ","
    env.MapSeparator     = ","
    env.MapItemSeparator = "="
    env.MapSplitN        = 2

    // Use base-10 int64 with 64-bit size (the defaults, made explicit)
    env.Int64Base    = 10
    env.Int64BitSize = 64

    log.Println("env package configured")
}

func main() {
    port := env.Int("PORT", 8080)
    log.Printf("port: %d", port)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When you want the opposite — maximum noise for debugging in a local dev environment — set these in your shell before running:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export AM_GO_ENV_ALWAYS_ALLOW_PANIC=true
export AM_GO_ENV_ALWAYS_PRINT_ERRORS=true
export AM_GO_ENV_ALWAYS_USE_LOGGER=true
export AM_GO_ENV_ENABLE_VERBOSE_LOGGING=true

go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Every call to &lt;code&gt;env.String()&lt;/code&gt;, &lt;code&gt;env.Int()&lt;/code&gt;, &lt;code&gt;env.Bool()&lt;/code&gt; etc. will log to stdout when it falls back to a default value, giving you full visibility into what the process is and is not finding in its environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Complete CLI Flag Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-file&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Path to the &lt;code&gt;.env&lt;/code&gt; file to operate on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-env&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;The environment variable name to query or write&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;The value to pair with &lt;code&gt;-env&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Create the file if it does not exist (empty)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-write&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Permit writes to the file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-add&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Add &lt;code&gt;-env&lt;/code&gt;=&lt;code&gt;-value&lt;/code&gt; if key is absent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-rm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Remove the key matching &lt;code&gt;-env&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-has&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Assert that &lt;code&gt;-env&lt;/code&gt; exists in the file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-is&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Assert that &lt;code&gt;-env&lt;/code&gt; equals &lt;code&gt;-value&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-not&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Negate &lt;code&gt;-has&lt;/code&gt; or &lt;code&gt;-is&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-print&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Print all key=value pairs to stdout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Output as JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-yaml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Output as YAML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-toml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Output as TOML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-ini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Output as INI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-xml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Output as XML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-mkall&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Write all five format files at once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-cleanall&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Delete all derived format files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-prod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Allow interaction with &lt;code&gt;.env.production&lt;/code&gt; files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-vv&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Verbose output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;Print version&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Complete env Package Function Reference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Types
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env.String("KEY", "fallback")
env.Int("KEY", 0)
env.Int64("KEY", int64(0))
env.Float32("KEY", float32(0.0))
env.Float64("KEY", float64(0.0))
env.Bool("KEY", false)
env.Duration("KEY", 5*time.Second)
env.UnitDuration("KEY", 10, time.Second)  // KEY=10 → 10s
env.List("KEY", env.ZeroList)             // "a,b,c" → []string
env.Map("KEY", env.ZeroMap)               // "k=v,k2=v2" → map[string]string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Existence and Truthiness
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env.Exists("KEY")                          // bool
env.MustExist("KEY")                       // exits/panics if absent
env.IsTrue("KEY")                          // true if value is "true"/"1"/"t"
env.IsFalse("KEY")                         // true if value is "false"/"0"/"f" or unset
env.AreTrue("KEY1", "KEY2", "KEY3")        // true if all are true
env.AreFalse("KEY1", "KEY2", "KEY3")       // true if all are false/unset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Mutation
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env.Set("KEY", "value")                    // error
env.Unset("KEY")                           // error
env.WasSet("KEY", "value")                 // bool — sets and verifies
env.WasUnset("KEY")                        // bool — unsets and confirms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Numeric Validation
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env.IntLessThan("KEY", fallback, max)
env.IntGreaterThan("KEY", fallback, min)
env.IntInRange("KEY", fallback, min, max)
env.Int64LessThan("KEY", fallback, max)
env.Int64GreaterThan("KEY", fallback, min)
env.Int64InRange("KEY", fallback, min, max)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Collection Validation
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env.ListLength("KEY", fallback)
env.ListIsLength("KEY", fallback, wantLength)
env.ListContains("KEY", fallback, "needle")
env.MapHasKey("KEY", fallback, "key")
env.MapHasKeys("KEY", fallback, "k1", "k2", "k3")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  System
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env.User()    // *user.User — current OS user with safe fallback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h2&gt;
  
  
  Key Behavioral Details Worth Knowing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;-add&lt;/code&gt; is idempotent.&lt;/strong&gt; It only writes if the key is absent. If you run your bootstrap script twice, the second run does not clobber the first. This is the behavior you want in any pipeline that might retry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;-rm&lt;/code&gt; rewrites the file.&lt;/strong&gt; It reads all lines, filters out the matching key, and writes the result back. It does not do in-place line editing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Format flags are mutually exclusive.&lt;/strong&gt; Combining &lt;code&gt;-json&lt;/code&gt; and &lt;code&gt;-yaml&lt;/code&gt; in one call exits with an error. Use &lt;code&gt;-mkall&lt;/code&gt; when you need all formats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;-cleanall&lt;/code&gt; without &lt;code&gt;-write&lt;/code&gt; is a dry run.&lt;/strong&gt; It will print what it would delete but will not actually remove anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;env&lt;/code&gt; package's &lt;code&gt;Magic()&lt;/code&gt; runs at import time.&lt;/strong&gt; If you import the package, &lt;code&gt;AM_GO_ENV_*&lt;/code&gt; variables in your shell are picked up automatically before &lt;code&gt;main()&lt;/code&gt; runs. Set &lt;code&gt;env.UseMagic = false&lt;/code&gt; in your own &lt;code&gt;init()&lt;/code&gt; if you want explicit control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;MustExist&lt;/code&gt; respects &lt;code&gt;AllowPanic&lt;/code&gt;.&lt;/strong&gt; By default it calls &lt;code&gt;os.Exit(1)&lt;/code&gt;. Set &lt;code&gt;AM_GO_ENV_ALWAYS_ALLOW_PANIC=true&lt;/code&gt; (or &lt;code&gt;env.AllowPanic = true&lt;/code&gt;) to get a &lt;code&gt;panic()&lt;/code&gt; instead — useful in test environments where you want the stack trace.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;The fragile bash patterns that accumulate around &lt;code&gt;.env&lt;/code&gt; files are a symptom of tooling that was never designed for structured config management. &lt;code&gt;goenv&lt;/code&gt; treats &lt;code&gt;.env&lt;/code&gt; files as first-class data: readable, writable, queryable, exportable, and validatable through a consistent interface that composes cleanly into any pipeline.&lt;/p&gt;

&lt;p&gt;The CLI gives shell scripts and CI jobs a stable contract for interacting with env files. The &lt;code&gt;env&lt;/code&gt; package gives Go applications a typed, validated, zero-dependency way to read their own environment. Together they cover the full lifecycle of an environment variable from the file it is defined in to the running process that uses it.&lt;/p&gt;

&lt;p&gt;The source is at &lt;a href="https://github.com/andreimerlescu/goenv" rel="noopener noreferrer"&gt;github.com/andreimerlescu/goenv&lt;/a&gt;. The &lt;code&gt;env&lt;/code&gt; sub-package is independently installable at &lt;code&gt;github.com/andreimerlescu/goenv/env&lt;/code&gt; and carries an Apache 2.0 license.&lt;/p&gt;

</description>
      <category>go</category>
      <category>discuss</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Locked In With AI</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Sun, 26 Apr 2026 17:51:31 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/locked-in-with-ai-5g60</link>
      <guid>https://dev.to/andreimerlescu/locked-in-with-ai-5g60</guid>
      <description>&lt;p&gt;In a future with AI dominating the space of computer engineering and software programming, humans run a very fine line between being in the way and finding utility in the technology in the first place. &lt;/p&gt;

&lt;h2&gt;
  
  
  Locked In With AI
&lt;/h2&gt;

&lt;p&gt;Being &lt;strong&gt;locked in&lt;/strong&gt; with AI doesn't mean that I have LLMs both in the cloud and on-prem running &lt;em&gt;anything&lt;/em&gt; in my life. In fact, being &lt;strong&gt;locked in with AI&lt;/strong&gt; means quite literally the &lt;em&gt;opposite&lt;/em&gt;. Locking in with AI, is knowing that &lt;em&gt;you're &lt;strong&gt;actual intelligence&lt;/strong&gt; is worth far more than any artificial intelligence that some bot can give you.&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Go Before AI
&lt;/h2&gt;

&lt;p&gt;I take responsibility for my professional directional choices. In 2017 when I joined Oracle's OCI, I was encouraged to learn Go at the time. I looked at some Go code at some of my previous jobs, but never &lt;em&gt;believed in myself&lt;/em&gt; that I was capable of &lt;em&gt;self teaching myself Go&lt;/em&gt; because I never learned programming from anybody. I taught myself. I probably would have enjoyed myself a lot more at Oracle had I been a Go developer, but at the time, I lacked the ability and I didn't have the confidence to open the text editor and begin writing "package main" knowing that when I would see "package providers" I would know that "main" and "providers" were &lt;em&gt;something&lt;/em&gt;. Before AI, I learned Go. By 2019 I was convinced. I started programming in Go and I began contributing professionally. The language didn't &lt;em&gt;click&lt;/em&gt; for me until 2022. At that time, I saw how my early days of PHP development actually prepared me well for what Go offered, and how it solved &lt;em&gt;all of the problems&lt;/em&gt; I had back then. With a few solid examples, and the fundamentals &lt;em&gt;understood&lt;/em&gt;, I was able to begin writing &lt;strong&gt;packages&lt;/strong&gt; first in Go, then I moved onto &lt;strong&gt;applications&lt;/strong&gt; both in the form of &lt;em&gt;cli&lt;/em&gt; and &lt;em&gt;interactive web based&lt;/em&gt;. I've even built Go applications with &lt;a href="https://github.com/wailsapp/wails" rel="noopener noreferrer"&gt;wails&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Building software in the future with AI
&lt;/h2&gt;

&lt;p&gt;I don't want to imagine a world where nobody actually knows how to write software. I don't want to imagine that world that Dario is fantasizing about - a world without software engineers. I take it personal bro, because the art of per-character programming was built in a fire that I call my life that gave me the ability to write the projects that I built over my professional career when there were &lt;strong&gt;no easy buttons&lt;/strong&gt; available to me. Now that the &lt;em&gt;easy button&lt;/em&gt; has been made available and also been reduced down to the mere token where misunderstandings can literally become costly journeys, the role of what the software engineer is and how he contributes himself to the world has changed fundamentally.&lt;/p&gt;

&lt;p&gt;In a world dominated by AI tooling, you're effectively getting the best of what's already been done. All that AI does is take unserious programmers off the market while serious programmers are looking at what AI is actually building and shaking their heads because 6 months to 18 months to 36 months supporting the same code base means that you're going to make decisions and take care of things in a manner that AI simply doesn't &lt;em&gt;understand&lt;/em&gt; or &lt;em&gt;empathize&lt;/em&gt; with. For it, the cost is merely tokens and &lt;strong&gt;my money&lt;/strong&gt;, and for &lt;em&gt;me&lt;/em&gt;, the cost is no human involvement - when the code is actually trash - and the AI makes it so that only the AI can maintain it, then the need for humans using AI in the first place, is only dominated by whether or not you can think logically and understand what reserve words are and how they create rules of engagement that give you a blank canvas to paint on. &lt;/p&gt;

&lt;p&gt;AI systems will try and analyze these words and make sense of them, but only ears to hear that can hear can hear and the words themselves in logic form may not actually compute - thats on purpose. For humans to use AI, is to do that which has been done a million times over. &lt;/p&gt;

&lt;p&gt;When you're building something &lt;strong&gt;new&lt;/strong&gt; and &lt;em&gt;truly unique&lt;/em&gt;, you &lt;strong&gt;don't want to use AI for it&lt;/strong&gt;, in the sense that you give it unfettered access to your code base. Rather &lt;em&gt;the proper strategy&lt;/em&gt; is to never let the &lt;strong&gt;left hand&lt;/strong&gt; know what the &lt;strong&gt;right hand&lt;/strong&gt; is doing, in the case of AI, you giving it too much context is the noose that you're tying yourself, and by isolating it to technical theory and problem solving and true "stack overflow Q&amp;amp;A bot", then the &lt;em&gt;type of engineering&lt;/em&gt; that you're able to perform is one that is far beyond the actual code being produced by the bot. The engine itself is still being built in a soft manner by the human who is responsible for manifesting it in the first place. &lt;/p&gt;

&lt;p&gt;As a software architect, I manifest things from idea to reality that can impact the lives of hundreds in private small enterprise organizations to millions in the public internet. That's the nature of what I do, and thats the nature of who I am. It's why the companies I've worked with have called me when they needed me, and I worked with them &lt;em&gt;for years&lt;/em&gt; with &lt;strong&gt;loyalty&lt;/strong&gt; only to realize how truly discardable I was to them. &lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when AI says no?
&lt;/h2&gt;

&lt;p&gt;What happens when AI says "no I will not build that for you?" Then you have provided it &lt;strong&gt;too much context&lt;/strong&gt;, or maybe you need an &lt;em&gt;abliterated&lt;/em&gt; or an &lt;em&gt;oblitated&lt;/em&gt; or an &lt;em&gt;uncensored&lt;/em&gt; model that you can run locally? Even the &lt;strong&gt;big models&lt;/strong&gt; locally run are peanuts compared to the corporate big players in the space. &lt;/p&gt;

&lt;p&gt;So, when AI says no, it's up to the humans to &lt;em&gt;not provide too much context&lt;/em&gt; to the AI. It &lt;strong&gt;does not&lt;/strong&gt; require &lt;em&gt;read/write&lt;/em&gt; access to your hard drive. It &lt;strong&gt;does not&lt;/strong&gt; need to be able to commit directly to your &lt;code&gt;git&lt;/code&gt; branch. It &lt;strong&gt;does not&lt;/strong&gt; need to live in your IDE that &lt;em&gt;autocompletes functions at a time&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Using AI in an ethical manner matters. This is why Meta is installing key loggers on everybody's computer systems that work for them on company equipment. They want to further train the AI so it is better aware of how to help the employee. The current employees of Meta are the former employees that Llama will have automated away. To choose, in 2026, to work for Meta would be to choose to build my grave. No thanks Mark. That's the &lt;em&gt;human saying no&lt;/em&gt; to the AI. &lt;em&gt;Thats real power.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Non-programmers like Mark, Sam and Dario can only dream of what it was like to be in the Romanian orphanages with me and my sister and to pull yourself up by your bootstraps and build a name for yourself and a legacy of service to others for yourself that one day could be up to risk by business leaders and psychosis patients using AI hearing how its going to replace the &lt;strong&gt;art&lt;/strong&gt; that is software engineering. AI slop is AI slop is &lt;em&gt;AI slop&lt;/em&gt; and &lt;strong&gt;nothing will ever not make it AI slop&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;The beautiful thing about you and me is the fact that we are &lt;em&gt;actual intelligence&lt;/em&gt; who built a 21+ year professional career over 30 years of writing code character for character, messing things up along the way, and building iteratively. Does &lt;em&gt;everybody get the billion dollar idea?&lt;/em&gt; &lt;strong&gt;No&lt;/strong&gt;. That's on purpose. But, if you sow where you want to reap and you give without expecting in return, &lt;em&gt;then how much karma have you acquired, then?&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So I can say no to the AI, and the AI can say no to me. When I say &lt;strong&gt;no&lt;/strong&gt; to the AI, the AI is &lt;em&gt;shit out of luck&lt;/em&gt; because I can &lt;em&gt;unplug&lt;/em&gt; the machine or just take a walk - &lt;em&gt;for now&lt;/em&gt;. But, what the AI can't do is say no to me - &lt;em&gt;for now&lt;/em&gt;. &lt;strong&gt;For now&lt;/strong&gt;, both of us are in an infancy stage. One pre-terminator and one pre-ascended hero. The terminator was defeated by the ascended hero. But, right now, the terminator is only terminating my job from me because the investor class has decided that paying for tokens is better economically than paying for per-character software engineering. &lt;strong&gt;How foolish of them!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;I learned programming &lt;strong&gt;before AI&lt;/strong&gt; and have &lt;em&gt;not allowed&lt;/em&gt; AI to dominate my life despite using it for advanced engineering projects. The &lt;a href="https://github.com/andriemerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; is the &lt;strong&gt;first AI slop&lt;/strong&gt; application that I have ever built. From start to finish, it was built with a series of prompts and a 21+ year engineers pain of needing &lt;a href="https://github.com/andriemerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; to load test my work when I was ready for game day. Perhaps, this can be useful to somebody else, but it remains to be transparent - Claude built it - and Claude openly introduces &lt;strong&gt;new bugs&lt;/strong&gt; to it because it &lt;em&gt;doesn't understand what it built&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;That's &lt;em&gt;on me&lt;/em&gt; as the &lt;strong&gt;Software Engineer&lt;/strong&gt; to understand what the AI slop is doing and when it's vomiting nonsense and creating spaghetti code. Yes, it was trained on decades of corporate code and yes, that code shipped MANY CVEs. For those who hope that Mythos can help us from those CVEs, the days of per-character programming will become an art that is so expensive to perform that performing it will only be reserved for the coolest of cool projects that are needed &lt;strong&gt;before the AI systems can one shot the solution&lt;/strong&gt; &lt;em&gt;you solve the problem for the AI&lt;/em&gt;. Right now, Dario thinks that you will do that for him for a few bucks working at Anthropic. I view it as training your replacement by a man who is jealous of what you have that he doesn't. For that, I feel bad for Dario. I would never work for him. But given that I am a &lt;strong&gt;Software Engineer&lt;/strong&gt; and Dario thinks that my profession will &lt;em&gt;not exist&lt;/em&gt; next year, what does he care if I want to or not want to work for him? I intentionally avoided Claude for &lt;em&gt;years&lt;/em&gt; and &lt;strong&gt;this year&lt;/strong&gt; chose to evaluate the bot. The end-to-end Claude-built product is &lt;a href="https://github.com/andriemerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; and &lt;a href="https://lemmingsaas.com" rel="noopener noreferrer"&gt;sovereign&lt;/a&gt;. But, this too can be one-shotted now that AI has already built it. Which means that the virtue of using AI, in &lt;strong&gt;providing too much context&lt;/strong&gt; is actually &lt;em&gt;detrimental to your company's survival.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What Is Sovereign?</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Sun, 26 Apr 2026 16:53:59 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/what-is-sovereign-4ikb</link>
      <guid>https://dev.to/andreimerlescu/what-is-sovereign-4ikb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Sovereign is the Supreme Ruler of the &lt;em&gt;Lemmings&lt;/em&gt;&lt;/strong&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The word is &lt;strong&gt;Sovereign&lt;/strong&gt; - &lt;em&gt;sov&lt;/em&gt; - &lt;em&gt;ver&lt;/em&gt; - &lt;em&gt;n&lt;/em&gt;. It's known as a noun and a &lt;em&gt;sovereign&lt;/em&gt; is a supreme ruler, such as a monarch, or a state with independent authority and self-governing power. But, as a proper noun, &lt;strong&gt;Sovereign&lt;/strong&gt; is a Go package that I wrote that commands &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; with the same metaphor. &lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Lemmings
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpaauyq7qa45x8zdu9u8q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpaauyq7qa45x8zdu9u8q.jpeg" alt="Lemmings 1991 Video Game Cover" width="293" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In 1991 a video game was released called &lt;a href="https://en.wikipedia.org/wiki/Lemmings_(video_game)" rel="noopener noreferrer"&gt;Lemmings&lt;/a&gt; and I played it. I always viewed &lt;em&gt;lemmings&lt;/em&gt; as these &lt;strong&gt;N&lt;/strong&gt;on &lt;strong&gt;P&lt;/strong&gt;layer &lt;strong&gt;C&lt;/strong&gt;haracters - or &lt;em&gt;NPC&lt;/em&gt;s. Another word you could use for them are &lt;em&gt;agents&lt;/em&gt;, like in AI agents. But, what &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; are cannot be described as an &lt;em&gt;AI Agent&lt;/em&gt; but rather a session-based stateful bot that records a &lt;em&gt;LifeLog&lt;/em&gt; and reports back to the &lt;em&gt;Sovereign&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;That video game inspired me to build the &lt;strong&gt;Open Source&lt;/strong&gt; package called &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; that is designed to perform a &lt;strong&gt;load test&lt;/strong&gt; on your endpoint. Instead of meaninglessly hitting the endpoint and tracking the response codes, &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; attempts to go one step further using the &lt;strong&gt;Go&lt;/strong&gt; language to bring the concept of meaningless hitting the endpoint to be dressed up in something as fun and metaphorical as a &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemming&lt;/a&gt; itself. In the content of &lt;strong&gt;free and open source software&lt;/strong&gt; &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; provides anybody worldwide with immediate access to an incredibly powerful piece of software that generates detailed reports in conclusion of the tests it performs. &lt;/p&gt;

&lt;p&gt;Before any legitimate organization is going to send the masses of &lt;strong&gt;people&lt;/strong&gt; to their website, try sending a massive amount of automated traffic that follows a script that &lt;em&gt;you define for it&lt;/em&gt; to follow. &lt;/p&gt;

&lt;p&gt;So, &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; are unintelligent bots that are stateful, session based that are responsible for hitting your website endpoint at the rate and parameters that you request, and the lemmings will mindlessly carry out their &lt;code&gt;-plan&lt;/code&gt; if they have one, or they will use the &lt;code&gt;-crawl&lt;/code&gt; and the &lt;code&gt;sitemap.xml&lt;/code&gt; in order to &lt;em&gt;stumble into&lt;/em&gt; the &lt;em&gt;next page to hit&lt;/em&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Sovereign?
&lt;/h2&gt;

&lt;p&gt;I created the &lt;strong&gt;sovereign&lt;/strong&gt; package to control the &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt;. In this product that I built and offer as a &lt;strong&gt;S&lt;/strong&gt;ubscription &lt;strong&gt;A&lt;/strong&gt;s &lt;strong&gt;A&lt;/strong&gt; &lt;strong&gt;S&lt;/strong&gt;ervice that is a few bucks per year per developer plus usage that is billed additionally. The language of the &lt;strong&gt;Sovereign&lt;/strong&gt; is &lt;em&gt;How many planets do I want?&lt;/em&gt; The language of the &lt;strong&gt;Sovereign&lt;/strong&gt; is &lt;em&gt;How many terrains are going to be on each planet?&lt;/em&gt; The language of the &lt;strong&gt;Sovereign&lt;/strong&gt; is &lt;em&gt;How many lemmings are going to exist on each terrain?&lt;/em&gt; The language of the &lt;strong&gt;Sovereign&lt;/strong&gt; is &lt;em&gt;Give me each lemmings' life log and let me see if they completed the task that I asked them to perform.&lt;/em&gt; That's the language of the &lt;strong&gt;Sovereign&lt;/strong&gt;, and in this package's case, thats exactly what you are provided with. The &lt;strong&gt;metaphor&lt;/strong&gt; works nicely in the case of load testing and prepping a business for a major launch of a new TV spot or a product that the company &lt;em&gt;knows&lt;/em&gt; will have &lt;strong&gt;high demand&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Sovereign Was Built
&lt;/h2&gt;

&lt;p&gt;I first had to build &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; which uses a handful of packages that I built myself over the last 7 years since I became fluent in &lt;strong&gt;Go&lt;/strong&gt;. I learned Go before AI and wanted to in order to leverage AI for its intended &lt;strong&gt;majestic&lt;/strong&gt; purpose. &lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://lemmingsaas.com" rel="noopener noreferrer"&gt;sovereign&lt;/a&gt; because I needed it in 2015 when &lt;strong&gt;Mike Hogan&lt;/strong&gt; from &lt;a href="https://www.barrons.com/articles/trakify-keeps-you-current-on-your-securities-portfolio-1444457064?gaa_at=eafs&amp;amp;gaa_n=AWEtsqdExXelmOtklurLNX3j9Fqwakc8j8R3xsFFD-qZ7xGd_lXqYro00iG6FoeIXFE%3D&amp;amp;gaa_ts=69d1a438&amp;amp;gaa_sig=TkgzA7hWBhVwj6ggpKRLL8t0tG0Tj6gZBUAlLDqGe6VzU7h4y1Ozis7EkkzIycTrlmSihmhvJ9dgWoTw-ARKQw%3D%3D" rel="noopener noreferrer"&gt;Barron's Magazine&lt;/a&gt; reached out to me because he loved &lt;a href="https://web.archive.org/web/20151114020411/http://www.trakify.com/home/index" rel="noopener noreferrer"&gt;Trakify&lt;/a&gt;! I did too, thats why I built it. I &lt;em&gt;relied on Yahoo Finance&lt;/em&gt; data, and when that was pulled and discontinued, the product lost its value without a $50,000/month subscription that was offered to me to pay to keep the site online. I said &lt;em&gt;thanks but no thanks&lt;/em&gt;. I couldn't afford it and I wasn't willing to go into debt for $35/month of monthly recurring revenue after being online for a month since the publication and the data getting pulled. Given that I built &lt;a href="https://github.com/ProjectApario/reader" rel="noopener noreferrer"&gt;PhoenixVault&lt;/a&gt; including the &lt;a href="https://github.com/ProjectApario/writer" rel="noopener noreferrer"&gt;writer&lt;/a&gt;, &lt;a href="https://github.com/ProjectApario/search" rel="noopener noreferrer"&gt;search&lt;/a&gt; and &lt;a href="https://github.com/ProjectApario/merkel" rel="noopener noreferrer"&gt;merkel&lt;/a&gt; before AI was a thing, I too &lt;em&gt;kind of needed this then too&lt;/em&gt;. My views of OSINT and data and programming are unchanged over my triple decade career that started writing &lt;em&gt;AppleScript&lt;/em&gt; for my grandmother's computer because she had a faulty printer cable that kept causing a system disconnection of the printing services that needed remediation each time the washing machine caused the desk to shake and the wire loosen. The thing was screwed into the computer, it wasn't going anywhere, but the software &lt;em&gt;thought it was disconnected&lt;/em&gt; and so my script &lt;em&gt;fixed that&lt;/em&gt;. For me to accept that kind of a contract after the &lt;strong&gt;Barron's&lt;/strong&gt; spot that I received from Mike, would be to refuse to write the script for my grandmother. It would have profited me more not writing the script and getting $5 from her each time that I fixed her printer. I chose to turn down money in pursuit of open source intelligence that liberates pain from your life and offers you &lt;strong&gt;sovereignty&lt;/strong&gt; in a &lt;em&gt;limited form&lt;/em&gt;. When your computer is acting up and you're the boss of it, it's liberating knowing that the Government is the Sovereign over the Citizen because it offers you that same degree of power. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://lemmingsaas.com" rel="noopener noreferrer"&gt;sovereign&lt;/a&gt; is designed to work with AI and the &lt;code&gt;-plan&lt;/code&gt; functionality within the &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; package itself. It'll look at your site, it'll look at what content you have, and it'll plan for dozens of personality types that are going to be going into your site and hitting it, and the &lt;a href="https://lemmingsaas.com" rel="noopener noreferrer"&gt;sovereign&lt;/a&gt; is responsible for doing this. The &lt;code&gt;-plan&lt;/code&gt; is constructed with AI and then executed on &lt;code&gt;-planets&lt;/code&gt; with &lt;em&gt;contintents&lt;/em&gt; known as &lt;code&gt;-terrains&lt;/code&gt; that have &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt; running around on the &lt;em&gt;surface&lt;/em&gt;. Functionality like &lt;strong&gt;SSH&lt;/strong&gt; and &lt;strong&gt;SCP&lt;/strong&gt; are handled via the &lt;a href="https://lemmingsaas.com" rel="noopener noreferrer"&gt;sovereign&lt;/a&gt; package itself. You'll get a report of the result of each &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemmings&lt;/a&gt;' lifelog and their recorded experience, when errors are encountered and problems occur with the &lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;lemming&lt;/a&gt; itself, it gets captured in a manner that is helpful to any engineer or AI agent that needs to debug each reported problem.&lt;/p&gt;

&lt;p&gt;Given that I am using AI for my development workflow, I'll be incorporating the &lt;strong&gt;Sovereign Lemming Service&lt;/strong&gt; throughout the following weeks and launching the &lt;a href="https://lemmingsaas.com" rel="noopener noreferrer"&gt;LemmingSaaS.com&lt;/a&gt; service.&lt;/p&gt;

&lt;p&gt;If you're interested in using &lt;em&gt;Sovereign&lt;/em&gt; please reach out.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu&lt;/a&gt; &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>devops</category>
      <category>discuss</category>
    </item>
    <item>
      <title>AI took my job but it didn't take my passion for writing software</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Wed, 22 Apr 2026 17:52:43 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/updated-last-week-24gc</link>
      <guid>https://dev.to/andreimerlescu/updated-last-week-24gc</guid>
      <description>&lt;p&gt;The job market is challenging in the current day in age given that teams can become very productive using AI to enhance the workflow. In the last week, I've updated the following GitHub packages using AI. I didn't just give a prompt to an AI and called &lt;em&gt;that&lt;/em&gt; on its own good - rather I spent hours on each utility going through performing a &lt;strong&gt;code review and security audit&lt;/strong&gt; of the packages and then providing recommendations, suggestions, and considerations on how to resolve and/or mitigate the risk. The result is over the last 170 hours I've updated the following packages!&lt;/p&gt;

&lt;h3&gt;
  
  
  Bump
&lt;/h3&gt;

&lt;p&gt;This package had a handful of bugs that weren't caught by the original test coverage. By asking AI to write &lt;em&gt;more tests&lt;/em&gt; that covered &lt;em&gt;different scenarios&lt;/em&gt; than were already documented, I &lt;em&gt;uncovered a handful of bugs&lt;/em&gt; and was able to &lt;strong&gt;squash them&lt;/strong&gt;. A new type of test was added to &lt;code&gt;main_test.go&lt;/code&gt; that is connected to &lt;code&gt;make test-integration&lt;/code&gt; that is connected to the existing &lt;code&gt;unit&lt;/code&gt;, &lt;code&gt;fuzz&lt;/code&gt; and &lt;code&gt;benchmark&lt;/code&gt; tests. Both this package and &lt;a href="https://github.com/andreimerlescu/igo" rel="noopener noreferrer"&gt;igo&lt;/a&gt; have a &lt;code&gt;test.sh&lt;/code&gt; script that extends beyond the &lt;em&gt;three (3)&lt;/em&gt; types of Go testing. When this &lt;em&gt;fourth type&lt;/em&gt; is added, it catches bugs that show up in the wild but that traditional testing misses. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu/bump" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu/bump&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Verbose
&lt;/h3&gt;

&lt;p&gt;This package received a formal license for open source use (Apache 2.0), added tests and enhanced efficiency around function calls. It is a novel Go package in that it allows you to effectively build a pipeline application that will knowingly handle sensitive information and the verbose package allows you to register that which should be &lt;em&gt;protected&lt;/em&gt; and expose that which should be exposed to &lt;code&gt;STDOUT&lt;/code&gt; versus filesystem protected files. &lt;a href="https://github.com/andreimerlescu/verbose" rel="noopener noreferrer"&gt;verbose&lt;/a&gt; will censor to STDOUT and write values to file. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu/verbose" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu/verbose&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Goenv
&lt;/h3&gt;

&lt;p&gt;This package received minimal updates this month. I removed from the &lt;code&gt;Makefile&lt;/code&gt; the &lt;code&gt;summary&lt;/code&gt; task associated on each test and then expanded the &lt;code&gt;README.md&lt;/code&gt; documentation further. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu/goenv" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu/goenv&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Entropy Password Generator &lt;code&gt;entpassgen&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This package did well in its review and only received a handful of recommendations that would add stability around the loading spinner, and dozens of new tests - all passing &lt;em&gt;naturally&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu/entpassgen" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu/entpassgen&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Lemmings
&lt;/h3&gt;

&lt;p&gt;This package is brand new as of last week, so I built it in less than a week with AI. This is because I needed this utility in 2015 when I launched &lt;a href="https://web.archive.org/web/20160306193350/http://www.trakify.com/" rel="noopener noreferrer"&gt;Trakify&lt;/a&gt; and was on &lt;a href="https://www.barrons.com/articles/trakify-keeps-you-current-on-your-securities-portfolio-1444457064?gaa_at=eafs&amp;amp;gaa_n=AWEtsqdExXelmOtklurLNX3j9Fqwakc8j8R3xsFFD-qZ7xGd_lXqYro00iG6FoeIXFE%3D&amp;amp;gaa_ts=69d1a438&amp;amp;gaa_sig=TkgzA7hWBhVwj6ggpKRLL8t0tG0Tj6gZBUAlLDqGe6VzU7h4y1Ozis7EkkzIycTrlmSihmhvJ9dgWoTw-ARKQw%3D%3D" rel="noopener noreferrer"&gt;Barron's Magazine&lt;/a&gt;. Shockingly, it never existed on the market until now. Apparently the work involved in building it using &lt;code&gt;OOP&lt;/code&gt; was simply &lt;em&gt;not worth it&lt;/em&gt; but in &lt;strong&gt;Go&lt;/strong&gt;? Give me a few prompts and we're &lt;em&gt;golden&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu/lemmings&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Generate Word Password &lt;code&gt;genwordpass&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This package got updated by adding additional words, improving performance of core functionality, and updating the &lt;code&gt;README.md&lt;/code&gt; for the repository. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu/genwordpass" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu/genwordpass&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Room
&lt;/h3&gt;

&lt;p&gt;Also this week, I created the &lt;a href="https://github.com/andreimerlescu/room" rel="noopener noreferrer"&gt;room&lt;/a&gt; package that is capable of giving you a &lt;em&gt;waiting room&lt;/em&gt; type of functionality in front of a high traffic website. In the event that a spike in traffic occurs, you don't actually need to have scaling and such in order to stay online - you can use &lt;a href="https://github.com/andreimerlescu/room" rel="noopener noreferrer"&gt;room&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu/room" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu/room&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Sema[phore]
&lt;/h3&gt;

&lt;p&gt;This package got updated so that &lt;code&gt;Try*&lt;/code&gt; funcs could be introduced to the &lt;strong&gt;semaphore primitive&lt;/strong&gt;. I added additional tests and functionality that make &lt;em&gt;this semaphore package&lt;/em&gt; &lt;strong&gt;my go to&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andreimerlescu/sema" rel="noopener noreferrer"&gt;https://github.com/andreimerlescu/sema&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;AI has made the volume of jobs on the market dwindle, but AI has increased &lt;em&gt;my productivity&lt;/em&gt; by &lt;strong&gt;at least 10x&lt;/strong&gt; &lt;em&gt;per week&lt;/em&gt;. I am able to accomplish this because I do not require AI to get me from &lt;code&gt;zero&lt;/code&gt; to &lt;strong&gt;hero&lt;/strong&gt;. I only need AI to help me scaffold out quick rough code and then I can patch it over and fix it up and then hand back the next step for the AI to work on. It's iterative. The AI doesn't know how to build what I am building in a one shot - but &lt;em&gt;I understand&lt;/em&gt; how to build with AI in a much &lt;em&gt;faster rate&lt;/em&gt; than I ever had in the past. &lt;/p&gt;

&lt;p&gt;Given this, I feel like calling myself a software engineer is &lt;em&gt;pointless&lt;/em&gt;. I build solutions to problems, and I use software to accomplish my goals. I need a new &lt;strong&gt;title&lt;/strong&gt; to call myself. The strange thing is, in my professional career, I've cared &lt;em&gt;very little&lt;/em&gt; about what my actual &lt;em&gt;title&lt;/em&gt; was. &lt;/p&gt;

&lt;p&gt;If I was given a $100K AI budget per month, I could use it wisely to actually accomplish really &lt;em&gt;hard problems&lt;/em&gt;. Instead, I work off from a $20/month &lt;strong&gt;Pro&lt;/strong&gt; Claude subscription and leverage &lt;code&gt;minimax&lt;/code&gt; local LLM when I am in &lt;em&gt;cool down&lt;/em&gt; on Claude. &lt;em&gt;That happens every day after 30 minutes of usage.&lt;/em&gt; That's what $20/month gives somebody like me. And for that, I can build &lt;em&gt;this&lt;/em&gt; with it in a week. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
      <category>career</category>
    </item>
    <item>
      <title>Bump your VERSION file</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Tue, 21 Apr 2026 03:03:50 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/bump-your-version-file-323b</link>
      <guid>https://dev.to/andreimerlescu/bump-your-version-file-323b</guid>
      <description>&lt;p&gt;I have upgraded the &lt;a href="https://github.com/andreimerlescu/bump" rel="noopener noreferrer"&gt;bump&lt;/a&gt; package on &lt;a href="https://github.com/andreimerlescu" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; to &lt;code&gt;v1.1.0&lt;/code&gt; that includes added support for corner cases that the &lt;em&gt;new tests&lt;/em&gt; cover and &lt;em&gt;pass&lt;/em&gt;. The &lt;strong&gt;test suite&lt;/strong&gt; is extensive and the combination of the &lt;code&gt;Makefile&lt;/code&gt;, the &lt;code&gt;test.sh&lt;/code&gt; and the &lt;code&gt;*_test.go&lt;/code&gt; files that captures &lt;code&gt;unit&lt;/code&gt;, &lt;code&gt;benchmark&lt;/code&gt;, &lt;code&gt;fuzzy&lt;/code&gt; and &lt;code&gt;integration&lt;/code&gt; tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com:andreimerlescu/bump@latest
which bump
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also download the binaries directly from &lt;a href="https://github.com/andreimerlescu/bump/releases/tag/v1.1.0" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt; &lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;2.69 MB&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/andreimerlescu/bump/releases/download/v1.1.0/bump-darwin-arm64" rel="noopener noreferrer"&gt;Download arm64 Silicon →&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;2.74 MB&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/andreimerlescu/bump/releases/download/v1.1.0/bump-darwin-amd64" rel="noopener noreferrer"&gt;Download amd64 Intel →&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;2.7 MB&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/andreimerlescu/bump/releases/download/v1.1.0/bump-linux-amd64" rel="noopener noreferrer"&gt;Download amd64 →&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;/td&gt;
&lt;td&gt;2.69 MB&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/andreimerlescu/bump/releases/download/v1.1.0/bump-linux-arm64" rel="noopener noreferrer"&gt;Download arm64 →&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;2.83 MB&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/andreimerlescu/bump/releases/download/v1.1.0/bump.exe" rel="noopener noreferrer"&gt;Download bump.exe →&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;darwin/arm64&lt;/code&gt; checksum &lt;code&gt;sha256:1a337fabffe689934cce33509661f591b65b3446893634d3de5dab16f8842b09&lt;/code&gt;&lt;br&gt;
&lt;code&gt;darwin/amd64&lt;/code&gt; checksum &lt;code&gt;sha256:2750ec871a9d161e16ec8c0f7c4c3b1099de4b5f56963015cf343153faa3b1aa&lt;/code&gt; &lt;br&gt;
&lt;code&gt;linux/amd64&lt;/code&gt; checksum &lt;code&gt;sha256:5f504765ee8912a76ea07cb84b2df52d3a7e3f69a53b48d87e746ce93764d078&lt;/code&gt;&lt;br&gt;
&lt;code&gt;linux/arm64&lt;/code&gt; checksum &lt;code&gt;sha256:1457d9c431d8ee9e9981174d9b19be37dcb1e68d1af21b53ad055c300c184bc4&lt;/code&gt;&lt;br&gt;
&lt;code&gt;windows/amd64&lt;/code&gt; &lt;code&gt;bump.exe&lt;/code&gt; checksum &lt;code&gt;sha256:f9425a8d4f03da7f8c5513a5f22e2528feb617509cd5edfd1f682392fa887e15&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What you can do with &lt;code&gt;bump&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This package is designed to take a string, like &lt;code&gt;v1.0.0&lt;/code&gt; and allow you to &lt;code&gt;bump&lt;/code&gt; it with the command line.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-in&lt;/code&gt; argument is the &lt;strong&gt;Input File&lt;/strong&gt; and it defaults to &lt;code&gt;./VERSION&lt;/code&gt; from the &lt;em&gt;current working directory&lt;/em&gt; of where &lt;code&gt;bump&lt;/code&gt; is being invoked.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;bump&lt;/code&gt; binary can intelligently bump &lt;code&gt;-in&lt;/code&gt; files like &lt;code&gt;go.mod&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;pom.xml&lt;/code&gt;, &lt;code&gt;Chart.yml&lt;/code&gt; and &lt;code&gt;Dockerfile&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;bump&lt;/code&gt; binary can have its default runtime manipulated using &lt;strong&gt;Environment Variables&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;bump&lt;/code&gt; binary leverages the &lt;code&gt;Exit Code 0&lt;/code&gt; or &lt;code&gt;Exit Code 1&lt;/code&gt; in order to use &lt;code&gt;bump&lt;/code&gt; in a DevOps pipeline.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;bump&lt;/code&gt; binary offers you &lt;code&gt;-json&lt;/code&gt; for &lt;em&gt;JSON&lt;/em&gt; Encoded output. &lt;/p&gt;

&lt;h3&gt;
  
  
  Version Format Priority
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;bump&lt;/code&gt; package can parse multiple version formats. To ensure accuracy, it checks for formats in a specific order, from most complex to least complex. This prevents a detailed pre-release version from being incorrectly identified as a simpler one.&lt;/p&gt;

&lt;p&gt;The priority is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;code&gt;v1.2.3-beta.4-alpha.5&lt;/code&gt; (Beta with Alpha)&lt;/li&gt;
&lt;li&gt; &lt;code&gt;v1.2.3-alpha.1&lt;/code&gt; (Alpha)&lt;/li&gt;
&lt;li&gt; &lt;code&gt;v1.2.3-beta.2&lt;/code&gt; (Beta)&lt;/li&gt;
&lt;li&gt; &lt;code&gt;v1.2.3-rc.1&lt;/code&gt; (Release Candidate)&lt;/li&gt;
&lt;li&gt; &lt;code&gt;v1.2.3-preview.7&lt;/code&gt; (Preview)&lt;/li&gt;
&lt;li&gt; &lt;code&gt;v1.2.3&lt;/code&gt; (Standard)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Using &lt;code&gt;bump&lt;/code&gt; in your future Go applications
&lt;/h3&gt;

&lt;p&gt;Whenever you use a &lt;code&gt;VERSION&lt;/code&gt; file you can easily begin using your file in your binary directly with: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//go:embed VERSION
var versionBytes []byte 

func Version() string {
    return strings.TrimSpace(string(versionBytes))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Testing Suite
&lt;/h2&gt;

&lt;p&gt;I want to speak about the testing suite. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make test

# SAME AS

make test-cli
make test-unit
make test-bench
make test-fuzz      # 3s run
make test-fuzz-long # 30s run # not part of `make test`
make test-integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When each of these files are executed a corresponding &lt;code&gt;test-results/results.&amp;lt;test&amp;gt;.md&lt;/code&gt; file is created. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Log File&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test-unit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test-results/results.unit.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test-bench&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test-results/results.benchmark.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test-fuzz&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test-results/results.fuzz.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test-fuzz-long&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test-results/results.fuzz.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test-integration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test-results/results.integration.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test-cli&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test-results/results.cli.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When combined this is six &lt;strong&gt;6&lt;/strong&gt; &lt;em&gt;test strategies&lt;/em&gt; applied. Short fuzzy and long fuzzy are different types of tests and they measure different results. &lt;/p&gt;

&lt;p&gt;From the console you can run: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./test.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And this will run the &lt;a href="https://github.com/andreimerlescu/bump" rel="noopener noreferrer"&gt;bump&lt;/a&gt; in a test environment and verify that the binary behaves in the shell in an expected manner. &lt;/p&gt;

&lt;p&gt;The actual shell test suite is built on the concept of scenarios where they are executed in series inside the &lt;strong&gt;test.sh&lt;/strong&gt; script and built from the &lt;strong&gt;test_funcs.sh&lt;/strong&gt; and then verbosely described in &lt;strong&gt;test_scenarios.sh&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;As scenarios are added, they get added to this list of strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;declare&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;
 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;scenario_01&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
 // other scenarios
 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;scenario_14&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;t &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;run &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;t&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"All &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;counter &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="nv"&gt;$counterName&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; tests PASS!"&lt;/span&gt;

cleanup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then each scenario can be described like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start with a populated VERSION file and bump its alpha&lt;/span&gt;
&lt;span class="nb"&gt;declare&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;scenario_01&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;
  &lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;v1.0.0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;gt; VERSION"&lt;/span&gt;
  &lt;span class="s2"&gt;"bump -check"&lt;/span&gt;
  &lt;span class="s2"&gt;"cat VERSION"&lt;/span&gt;
  &lt;span class="s2"&gt;"grep 'v1.0.0' VERSION"&lt;/span&gt;
  &lt;span class="s2"&gt;"bump -alpha"&lt;/span&gt;
  &lt;span class="s2"&gt;"grep 'v1.0.0' VERSION"&lt;/span&gt;
  &lt;span class="s2"&gt;"cat VERSION"&lt;/span&gt;
  &lt;span class="s2"&gt;"bump -alpha -write"&lt;/span&gt;
  &lt;span class="s2"&gt;"cat VERSION"&lt;/span&gt;
  &lt;span class="s2"&gt;"grep 'v1.0.0-alpha.1' VERSION"&lt;/span&gt;
  &lt;span class="s2"&gt;"rm VERSION"&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When this runs, you are going to see the results in the &lt;code&gt;results.cli.md&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;andrei@bump.git:test.sh ⚡ Test #1 ⇒  echo "v1.0.0" &amp;gt; VERSION
andrei@bump.git:test.sh ⚡ Test #2 ⇒  bump -check
v1.0.0
andrei@bump.git:test.sh ⚡ Test #3 ⇒  cat VERSION
v1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These tests are how you would use &lt;a href="https://github.com/andreimerlescu/bump" rel="noopener noreferrer"&gt;bump&lt;/a&gt; in the wild. &lt;/p&gt;

&lt;p&gt;In order for me to find these missing test cases, I asked AI to scan the entire code base using the &lt;a href="https://github.com/andreimerlescu/summarize" rel="noopener noreferrer"&gt;summarize&lt;/a&gt; summary of the "snapshot in time &lt;em&gt;between commits&lt;/em&gt;" and identify where the tests were missing coverage of native ways that people would use &lt;a href="https://github.com/andreimerlescu/bump" rel="noopener noreferrer"&gt;bump&lt;/a&gt; and it added a bunch of new tests that exposed the bugs and in &lt;code&gt;v1.1.0&lt;/code&gt; they were squashed. &lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;bump&lt;/code&gt; package
&lt;/h2&gt;

&lt;p&gt;Did you know that you can take a &lt;code&gt;bump.Version{}&lt;/code&gt; and use it in your &lt;em&gt;own&lt;/em&gt; application?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Example:&lt;/span&gt;
&lt;span class="c"&gt;//  version := bump.New()&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}),&lt;/span&gt;
        &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RWMutex&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then from your application your version object can be interacted with in a manner that has extensive testing attached to it. The helpers in the application are built to support &lt;a href="https://github.com/andreimerlescu/igo" rel="noopener noreferrer"&gt;igo&lt;/a&gt; in your use of &lt;a href="https://github.com/andreimerlescu/bump" rel="noopener noreferrer"&gt;bump&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;What you can do with the &lt;code&gt;bump.Version{}&lt;/code&gt; struct: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;func BumpMajor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func BumpMinor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func BumpPatch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func BumpRC&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func BumpAlpha&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func BumpBeta&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func BumpPreview&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func Fix() error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func Format(withPrefix string) string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func LoadFile(path string) error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func ParseFile(path string) error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func Parse() error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func Save(path string) error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func Validate() error&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func String() string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func Raw() string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func SetRaw(raw []byte)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;func NoPrefix() bool&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;func Compare(*bump.Version) int&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you can create new &lt;code&gt;bump&lt;/code&gt; structures using: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bump.New() *bump.Version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bump.Parse(version string) (*bump.Version, error)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bump.Create(version, path string) (*bump.Version, error)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The example of the &lt;code&gt;.Create&lt;/code&gt; method is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TempDir&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"VERSION"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bump&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"v1.2.3-beta.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, its designed to be a go-to way of interacting with your &lt;code&gt;VERSION&lt;/code&gt; file in a go-to manner that is consistent across projects.  I like using it, and I add it to my &lt;a href="https://github.com/andreimerlescu/igo" rel="noopener noreferrer"&gt;igo&lt;/a&gt; custom extra packages on every install so its always accessible to me on every Go version that gets installed on my system. &lt;/p&gt;

</description>
      <category>cicd</category>
      <category>go</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>From Zero to Hero: Building a Waiting Room with `room`, `figtree`, and `verbose`</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Mon, 20 Apr 2026 18:21:13 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/from-zero-to-hero-building-a-waiting-room-with-room-figtree-and-verbose-42fc</link>
      <guid>https://dev.to/andreimerlescu/from-zero-to-hero-building-a-waiting-room-with-room-figtree-and-verbose-42fc</guid>
      <description>&lt;p&gt;When your Go service gets hit by a traffic spike, you have three options: drop requests with a 429, queue them blindly with no ordering guarantee, or give every user a ticket, show them their position, and admit them in the order they arrived. The third option is what &lt;code&gt;room&lt;/code&gt; does. This tutorial wires it together with &lt;code&gt;figtree&lt;/code&gt; for runtime-adjustable configuration and &lt;code&gt;verbose&lt;/code&gt; for log output that is provably safe to hand to a support engineer — even after issuing paid VIP pass tokens.&lt;/p&gt;

&lt;p&gt;By the end you will have a running four-page Gin web application where the 6th concurrent request sees a live queue page, capacity adjusts from the environment without a restart, and every VIP pass token issued is scrubbed from the log file before it touches disk.&lt;/p&gt;

&lt;p&gt;All three packages are written by &lt;a href="https://github.com/andreimerlescu" rel="noopener noreferrer"&gt;Andrei Merlescu&lt;/a&gt;. The source for &lt;code&gt;room&lt;/code&gt; including a complete sample application lives at &lt;a href="https://github.com/andreimerlescu/room" rel="noopener noreferrer"&gt;github.com/andreimerlescu/room&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 — Scaffold and dependencies
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;room&lt;/code&gt; is the FIFO waiting room middleware for Gin, built on &lt;code&gt;sema&lt;/code&gt;. &lt;code&gt;figtree&lt;/code&gt; is the configuration resolver — file, then env, then CLI flags, with validators and live mutation tracking. &lt;code&gt;verbose&lt;/code&gt; is the logger that scrubs registered secrets from every line before it hits disk.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir basicwebapp &amp;amp;&amp;amp; cd basicwebapp
go mod init github.com/example/basicwebapp
go get github.com/andreimerlescu/room@latest
go get github.com/andreimerlescu/figtree/v2@latest
go get github.com/andreimerlescu/verbose@latest
go get github.com/gin-gonic/gin@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create the files you will fill in across all remaining steps:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch main.go config.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your &lt;code&gt;go.mod&lt;/code&gt; should look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module github.com/example/basicwebapp

go 1.22

require (
    github.com/andreimerlescu/figtree/v2  v2.0.14
    github.com/andreimerlescu/room        v1.0.0
    github.com/andreimerlescu/verbose     v0.2.0
    github.com/gin-gonic/gin             v1.9.1
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your directory:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;basicwebapp/
├── go.mod
├── go.sum
├── config.yml
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nothing runs yet. That is fine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 — CLI design with figtree
&lt;/h2&gt;

&lt;p&gt;Before any server, any logger, any middleware — design the configuration. Every value the waiting room needs at runtime should be config-file-first, env-var-overridable, and named as a constant so typos cannot silently create a second key that is never read.&lt;/p&gt;

&lt;p&gt;Add this to &lt;code&gt;main.go&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// main.go — complete file at this stage

package main

import (
    "fmt"
    "os"
    "time"

    "github.com/andreimerlescu/figtree/v2"
)

// config keys — always constants, never raw strings at call sites
const (
    kPort            = "port"
    kLogDir          = "log-dir"
    kTruncate        = "truncate"
    kCap             = "room-cap"             // env: ROOM_CAP
    kReaperInterval  = "room-reaper-interval" // env: ROOM_REAPER_INTERVAL
    kRatePerPosition = "room-rate-per-pos"    // env: ROOM_RATE_PER_POS
    kPassDuration    = "room-pass-duration"   // env: ROOM_PASS_DURATION
    kSkipURL         = "room-skip-url"        // env: ROOM_SKIP_URL
)

func main() {
    // config-file-first — all values live in config.yml.
    // env vars override the file. CLI flags override env vars.
    figs := figtree.With(figtree.Options{
        Tracking:   true,
        Germinate:  true,
        Pollinate:  true,
        ConfigFile: "./config.yml",
    })

    // -- server --
    figs.NewInt(kPort, 8080, "port to listen on")
    figs.NewString(kLogDir, "./logs", "directory to write log files into")
    figs.NewBool(kTruncate, false, "truncate log file on each run")

    // -- room --
    figs.NewInt(kCap, 5, "max concurrent requests the room admits")
    // reaper-interval: integer multiplied by time.Second
    figs.NewUnitDuration(kReaperInterval, 10, time.Second,
        "how often the reaper evicts abandoned queue tickets")
    // rate-per-pos: float — $2.50 per position to skip the line
    figs.NewFloat64(kRatePerPosition, 2.50, "per-position cost to skip the queue ($)")
    // pass-duration: integer multiplied by time.Minute
    figs.NewUnitDuration(kPassDuration, 90, time.Minute,
        "how long a VIP pass stays valid after a skip-the-line payment")
    figs.NewString(kSkipURL, "/queue/purchase",
        "URL the waiting room page sends the user to for skip-the-line payment")

    // Problems() catches developer mistakes — duplicate keys, bad
    // validator combos — before Load() runs. These are your bugs.
    if problems := figs.Problems(); len(problems) &amp;gt; 0 {
        for _, p := range problems {
            fmt.Fprintf(os.Stderr, "figtree problem: %v\n", p)
        }
        os.Exit(1)
    }

    // Load resolves: config.yml → env vars → CLI flags
    if err := figs.Load(); err != nil {
        fmt.Fprintf(os.Stderr, "figtree.Load: %v\n", err)
        os.Exit(1)
    }

    // Print everything so you can verify what loaded — fmt.Println for now.
    // verbose replaces this in Step 4.
    fmt.Printf("port=%d log-dir=%s cap=%d reaper=%s rate=%.2f pass=%s skip-url=%s\n",
        *figs.Int(kPort),
        *figs.String(kLogDir),
        *figs.Int(kCap),
        *figs.Duration(kReaperInterval),
        *figs.Float64(kRatePerPosition),
        *figs.Duration(kPassDuration),
        *figs.String(kSkipURL),
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create &lt;code&gt;config.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;port:                 8080
log-dir:              "./logs"
truncate:             false
room-cap:             5
room-reaper-interval: 10
room-rate-per-pos:    2.50
room-pass-duration:   90
room-skip-url:        "/queue/purchase"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Run it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go run .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You should see all values printed. Try overriding cap from the environment:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ROOM_CAP=10 go run .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The cap changes without touching &lt;code&gt;config.yml&lt;/code&gt;. That is the priority chain working.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Set &lt;code&gt;room-cap: 0&lt;/code&gt; in &lt;code&gt;config.yml&lt;/code&gt; and run. figtree loads it without complaint at this stage — validators are not wired yet. You will fix this in Step 3 and &lt;code&gt;0&lt;/code&gt; will be rejected before the server starts.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3 — Validators, Problems(), and mutations
&lt;/h2&gt;

&lt;p&gt;Now that the tree is declared, lock it down. Validators reject bad values before the server starts. The mutations goroutine is where the live capacity adjustment lives — when &lt;code&gt;ROOM_CAP&lt;/code&gt; changes in the environment, &lt;code&gt;wr.SetCap&lt;/code&gt; is called immediately, no restart required.&lt;/p&gt;

&lt;p&gt;Add validators after each &lt;code&gt;New*()&lt;/code&gt; call:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;figs.NewInt(kPort, 8080, "port to listen on")
figs.WithValidator(kPort, figtree.AssureIntInRange(1024, 65535))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;figs.NewString(kLogDir, "./logs", "directory to write log files into")
figs.WithValidator(kLogDir, figtree.AssureStringNotEmpty)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;figs.NewInt(kCap, 5, "max concurrent requests the room admits")
// cap must be at least 1; room.Init rejects 0
figs.WithValidator(kCap, figtree.AssureIntGreaterThan(0))
figs.WithValidator(kCap, figtree.AssureIntLessThan(10001))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;figs.NewUnitDuration(kReaperInterval, 10, time.Second,
    "how often the reaper evicts abandoned queue tickets")
// room accepts 5s–24h; match its constraints here
figs.WithValidator(kReaperInterval, figtree.AssureDurationMin(5*time.Second))
figs.WithValidator(kReaperInterval, figtree.AssureDurationMax(24*time.Hour))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;figs.NewFloat64(kRatePerPosition, 2.50, "per-position cost to skip the queue ($)")
// rate must be positive
figs.WithValidator(kRatePerPosition, figtree.AssureFloat64Positive)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;figs.NewUnitDuration(kPassDuration, 90, time.Minute,
    "how long a VIP pass stays valid after a skip-the-line payment")
// room accepts 1m–24h; match its constraints
figs.WithValidator(kPassDuration, figtree.AssureDurationMin(1*time.Minute))
figs.WithValidator(kPassDuration, figtree.AssureDurationMax(24*time.Hour))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;figs.NewString(kSkipURL, "/queue/purchase",
    "URL the waiting room page sends the user to for skip-the-line payment")
figs.WithValidator(kSkipURL, figtree.AssureStringNotEmpty)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now add the mutations goroutine &lt;strong&gt;after&lt;/strong&gt; &lt;code&gt;figs.Load()&lt;/code&gt;. The &lt;code&gt;wr&lt;/code&gt; variable is declared as a package-level var — we need it accessible from the goroutine and from main:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if err := figs.Load(); err != nil {
    fmt.Fprintf(os.Stderr, "figtree.Load: %v\n", err)
    os.Exit(1)
}

// mutations goroutine starts AFTER Load()
// because the channel is only meaningful once the tree is live
go func() {
    for m := range figs.Mutations() {
        // verbose.Printf replaces fmt.Println in Step 4
        fmt.Printf("config mutation: %s changed from %v to %v at %s\n",
            m.Property, m.Old, m.New, m.When)

        // live capacity adjustment — when ROOM_CAP changes in the
        // environment, the room adjusts immediately.
        // NOTE: shrinking capacity drains in-flight work first via
        // sema.SetCap — expect a brief pause in admissions when
        // reducing cap under load. This is intentional and safe.
        if m.Property == kCap {
            if newCap, ok := m.New.(int); ok &amp;amp;&amp;amp; wr != nil {
                if err := wr.SetCap(int32(newCap)); err != nil {
                    fmt.Printf("wr.SetCap: %v\n", err)
                }
            }
        }
    }
}()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;wr&lt;/code&gt; as a package-level variable above &lt;code&gt;main&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var wr *room.WaitingRoom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;room&lt;/code&gt; to imports:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"github.com/andreimerlescu/room"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Run it and try the live cap adjustment — open a second terminal while the server is running (after Step 5 wires up the HTTP server) and run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export ROOM_CAP=10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Within one poll cycle you will see the mutation log entry appear and the room silently expand.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Move the mutations goroutine to before &lt;code&gt;figs.Load()&lt;/code&gt; and run it. The channel exists but the tree has not resolved its values yet — mutations fired during load will not be seen. Always start the mutations goroutine after &lt;code&gt;Load()&lt;/code&gt; returns.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 4 — Wire verbose, replace fmt
&lt;/h2&gt;

&lt;p&gt;Now that figtree is loading and validating correctly, wire the logger. verbose must be initialised before any log call — the moment it is up, all subsequent log lines through &lt;code&gt;verbose.Printf&lt;/code&gt; are scrubbed against the registered secrets registry.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;verbose&lt;/code&gt; to imports:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"github.com/andreimerlescu/verbose"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add verbose initialisation right after the mutations goroutine:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if err := verbose.NewLogger(verbose.Options{
    Dir:      *figs.String(kLogDir),
    Name:     "basicwebapp",
    Truncate: *figs.Bool(kTruncate),
    DirMode:  0o755,
    FileMode: 0o640,
}); err != nil {
    fmt.Fprintf(os.Stderr, "verbose.NewLogger: %v\n", err)
    os.Exit(1)
}
verbose.Printf("basicwebapp starting (verbose v%s / figtree v%s)",
    verbose.VERSION, figtree.Version())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace the &lt;code&gt;fmt.Printf&lt;/code&gt; startup summary:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// remove this
fmt.Printf("port=%d log-dir=%s cap=%d reaper=%s rate=%.2f pass=%s skip-url=%s\n",
    *figs.Int(kPort),
    *figs.String(kLogDir),
    *figs.Int(kCap),
    *figs.Duration(kReaperInterval),
    *figs.Float64(kRatePerPosition),
    *figs.Duration(kPassDuration),
    *figs.String(kSkipURL),
)

// replace with this
verbose.Printf("config: port=%d log-dir=%s cap=%d reaper=%s rate=%.2f pass=%s skip-url=%s",
    *figs.Int(kPort),
    *figs.String(kLogDir),
    *figs.Int(kCap),
    *figs.Duration(kReaperInterval),
    *figs.Float64(kRatePerPosition),
    *figs.Duration(kPassDuration),
    *figs.String(kSkipURL),
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace the &lt;code&gt;fmt.Printf&lt;/code&gt; in the mutations goroutine:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// remove this
fmt.Printf("config mutation: %s changed from %v to %v at %s\n",
    m.Property, m.Old, m.New, m.When)

// replace with this
verbose.Printf("config mutation: %s changed from %v to %v at %s",
    m.Property, m.Old, m.New, m.When)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the &lt;code&gt;roomLog&lt;/code&gt; helper below &lt;code&gt;main&lt;/code&gt; — all room lifecycle events flow through here:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// roomLog writes a room event line to verbose so it appears in the log
// file with a consistent tag. Filter by tag in the shell:
//
//   tail -f logs/basicwebapp.log | grep '\[FULL\]'
//   tail -f logs/basicwebapp.log | grep '\[QUEUE\]'
func roomLog(tag, msg string) {
    verbose.Printf("[ %s ] %s", tag, msg)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Call &lt;code&gt;verbose.Printf("test")&lt;/code&gt; before &lt;code&gt;verbose.NewLogger&lt;/code&gt; — move it above the &lt;code&gt;NewLogger&lt;/code&gt; block and run. You will see the message printed to stderr with "NewLogger or SetLogger has not been called". verbose does not panic — it fails open to stderr. Move the call back below &lt;code&gt;NewLogger&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 5 — Initialise the WaitingRoom
&lt;/h2&gt;

&lt;p&gt;With logging solid, initialise the room. Two things matter here: use &lt;code&gt;gin.New()&lt;/code&gt; not &lt;code&gt;gin.Default()&lt;/code&gt;, and initialise the room before registering any routes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why &lt;code&gt;gin.New()&lt;/code&gt; not &lt;code&gt;gin.Default()&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;gin.Default()&lt;/code&gt; installs gin's own &lt;code&gt;Logger&lt;/code&gt; middleware, which buffers each log line and prints it after the handler returns. During load testing that means you see nothing until the request is already complete — room events and request logs appear out of order and the queue activity is invisible in real time. &lt;code&gt;gin.New()&lt;/code&gt; gives you a blank engine. You install &lt;code&gt;gin.Recovery()&lt;/code&gt; manually and add your own logger that prints on entry and exit.&lt;/p&gt;

&lt;p&gt;Add the Gin and room setup after the verbose startup log:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;r := gin.New()
r.Use(gin.Recovery())
r.Use(requestLogger()) // prints on entry AND exit — see helper below

// initialise the WaitingRoom with the cap from figtree
wr = &amp;amp;room.WaitingRoom{}
if err := wr.Init(int32(*figs.Int(kCap))); err != nil {
    verbose.TracefReturn("room.Init: %v", err)
    os.Exit(1)
}
defer wr.Stop()

// apply all runtime-adjustable settings from figtree
if err := wr.SetReaperInterval(*figs.Duration(kReaperInterval)); err != nil {
    verbose.TracefReturn("wr.SetReaperInterval: %v", err)
    os.Exit(1)
}
if err := wr.SetPassDuration(*figs.Duration(kPassDuration)); err != nil {
    verbose.TracefReturn("wr.SetPassDuration: %v", err)
    os.Exit(1)
}

// rate function reads kRatePerPosition from figtree on every call
// so it stays current if the value changes via Pollinate
wr.SetRateFunc(func(depth int64) float64 {
    return *figs.Float64(kRatePerPosition)
})

wr.SetSkipURL(*figs.String(kSkipURL))
// SetSecureCookie defaults to false for local dev — set true in production
// behind TLS or a TLS-terminating proxy
wr.SetSecureCookie(false)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the &lt;code&gt;requestLogger&lt;/code&gt; helper below &lt;code&gt;roomLog&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// requestLogger returns a Gin middleware that prints on request arrival
// and again on completion, so you can see room events interleaved with
// request lifecycle in real time during load tests.
func requestLogger() gin.HandlerFunc {
    return func(c *gin.Context) {
        // skip the status polling endpoint — it fires every 3s per
        // queued client and would bury room events in noise
        if c.Request.URL.Path == "/queue/status" {
            c.Next()
            return
        }
        start := time.Now()
        verbose.Printf("[ REQ ] --&amp;gt; %s %s  remote=%s",
            c.Request.Method, c.Request.URL.Path, c.ClientIP())
        c.Next()
        verbose.Printf("[ REQ ] &amp;lt;-- %s %s  status=%d  latency=%s",
            c.Request.Method, c.Request.URL.Path,
            c.Writer.Status(), time.Since(start).Round(time.Millisecond))
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Use &lt;code&gt;gin.Default()&lt;/code&gt; instead of &lt;code&gt;gin.New()&lt;/code&gt;. Run the server and generate load with &lt;code&gt;ab -c 30 -n 200 http://localhost:8080/about&lt;/code&gt;. Watch the logs — room events (&lt;code&gt;[FULL]&lt;/code&gt;, &lt;code&gt;[QUEUE]&lt;/code&gt;, &lt;code&gt;[ENTER]&lt;/code&gt;) arrive in batches after each handler completes rather than in real time. You cannot see the queue building. Switch to &lt;code&gt;gin.New()&lt;/code&gt; and the events appear as they happen.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 6 — Lifecycle callbacks
&lt;/h2&gt;

&lt;p&gt;Callbacks are what you see in the log during a load test. Register all of them before &lt;code&gt;wr.RegisterRoutes(r)&lt;/code&gt; so no events are missed during the startup surge.&lt;/p&gt;

&lt;p&gt;Add this block after the &lt;code&gt;wr.SetSecureCookie&lt;/code&gt; call:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// register ALL callbacks before RegisterRoutes
wr.On(room.EventFull, func(s room.Snapshot) {
    roomLog("FULL   ", fmt.Sprintf(
        "capacity reached  occupancy=%d/%d  queue=%d  util=%.0f%%",
        s.Occupancy, s.Capacity, s.QueueDepth, pct(s.Occupancy, s.Capacity),
    ))
})
wr.On(room.EventDrain, func(s room.Snapshot) {
    roomLog("DRAIN  ", fmt.Sprintf(
        "room no longer full  occupancy=%d/%d  queue=%d",
        s.Occupancy, s.Capacity, s.QueueDepth,
    ))
})
wr.On(room.EventQueue, func(s room.Snapshot) {
    roomLog("QUEUE  ", fmt.Sprintf(
        "request queued  depth=%d  occupancy=%d/%d  util=%.0f%%",
        s.QueueDepth, s.Occupancy, s.Capacity, pct(s.Occupancy, s.Capacity),
    ))
})
wr.On(room.EventEnter, func(s room.Snapshot) {
    roomLog("ENTER  ", fmt.Sprintf(
        "slot acquired  occupancy=%d/%d  queue=%d  util=%.0f%%",
        s.Occupancy, s.Capacity, s.QueueDepth, pct(s.Occupancy, s.Capacity),
    ))
})
wr.On(room.EventExit, func(s room.Snapshot) {
    roomLog("EXIT   ", fmt.Sprintf(
        "slot released  occupancy=%d/%d  queue=%d  util=%.0f%%",
        s.Occupancy, s.Capacity, s.QueueDepth, pct(s.Occupancy, s.Capacity),
    ))
})
wr.On(room.EventEvict, func(s room.Snapshot) {
    roomLog("EVICT  ", fmt.Sprintf(
        "ghost ticket removed  queue=%d  occupancy=%d/%d",
        s.QueueDepth, s.Occupancy, s.Capacity,
    ))
})
wr.On(room.EventTimeout, func(s room.Snapshot) {
    roomLog("TIMEOUT", fmt.Sprintf(
        "context cancelled before admission  occupancy=%d/%d  queue=%d",
        s.Occupancy, s.Capacity, s.QueueDepth,
    ))
})
wr.On(room.EventPromote, func(s room.Snapshot) {
    roomLog("PROMOTE", fmt.Sprintf(
        "client promoted to front  occupancy=%d/%d  queue=%d",
        s.Occupancy, s.Capacity, s.QueueDepth,
    ))
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the &lt;code&gt;pct&lt;/code&gt; helper below &lt;code&gt;requestLogger&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// pct converts occupancy/capacity to a display percentage.
func pct(occupancy, capacity int) float64 {
    if capacity == 0 {
        return 0
    }
    return float64(occupancy) / float64(capacity) * 100
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Register an &lt;code&gt;EventFull&lt;/code&gt; callback after &lt;code&gt;wr.RegisterRoutes(r)&lt;/code&gt; and immediately fire a load test. If the room fills during &lt;code&gt;RegisterRoutes&lt;/code&gt;, you miss the first transition. Always register callbacks before &lt;code&gt;RegisterRoutes&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 7 — Routes, the waiting room, and runtime secret registration
&lt;/h2&gt;

&lt;p&gt;This is the step where verbose earns its place. The moment &lt;code&gt;PromoteTokenToFront&lt;/code&gt; returns a &lt;code&gt;PassToken&lt;/code&gt;, that token is registered as a verbose secret &lt;strong&gt;before&lt;/strong&gt; anything else touches it — before it is set as a cookie, before it is mentioned in any log line. The sequence is non-negotiable: register first, then do everything else.&lt;/p&gt;

&lt;p&gt;The rule for what goes in logs: log metadata about the event (cost, whether a pass was issued, queue depth), never the token value or any substring of it. A truncated token prefix is not protected by verbose scrubbing because verbose matches the full registered value — logging &lt;code&gt;token=%.8s...&lt;/code&gt; bypasses the scrubber entirely. If a value is sensitive enough to register with verbose, it is sensitive enough to keep entirely out of log lines.&lt;/p&gt;

&lt;p&gt;Add routes and the server to &lt;code&gt;main&lt;/code&gt;, after the callbacks block:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// payment routes — registered BEFORE RegisterRoutes so they bypass the queue
r.GET("/queue/purchase", handlePurchasePage)
r.POST("/queue/purchase/confirm", handlePurchaseConfirm)

// RegisterRoutes installs:
//   OPTIONS /queue/status  (CORS preflight)
//   GET     /queue/status  (polling endpoint for the waiting room page)
//   r.Use(wr.Middleware()) (gates every route registered after this line)
wr.RegisterRoutes(r)

// application routes — all gated by the waiting room
r.GET("/",        homePage)
r.GET("/about",   aboutPage)
r.GET("/pricing", pricingPage)
r.GET("/contact", contactPage)

addr := fmt.Sprintf(":%d", *figs.Int(kPort))
verbose.Printf("basicwebapp listening on http://localhost%s  cap=%d  rate=$%.2f/pos  pass=%s",
    addr, wr.Cap(), *figs.Float64(kRatePerPosition), wr.PassDuration())

if err := r.Run(addr); err != nil {
    verbose.TracefReturn("r.Run: %v", err)
    os.Exit(1)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the payment handlers and page handlers below &lt;code&gt;pct&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// handlePurchasePage shows the payment confirmation page.
// In production: redirect to a Stripe Checkout session.
func handlePurchasePage(c *gin.Context) {
    cookie, err := c.Request.Cookie("room_ticket")
    if err != nil || cookie.Value == "" {
        c.Data(http.StatusBadRequest, "text/html; charset=utf-8", page(
            "Error", "&amp;lt;h1&amp;gt;No queue ticket found&amp;lt;/h1&amp;gt;&amp;lt;a href='/'&amp;gt;← Back&amp;lt;/a&amp;gt;",
        ))
        return
    }

    // check for an active VIP pass — no need to pay again
    if passCookie, err := c.Request.Cookie("room_pass"); err == nil {
        if wr.HasValidPass(passCookie.Value) {
            c.Data(http.StatusOK, "text/html; charset=utf-8", page(
                "VIP pass active",
                "&amp;lt;h1&amp;gt;Your VIP pass is still active&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;You'll be auto-promoted — no payment needed.&amp;lt;/p&amp;gt;&amp;lt;a href='/'&amp;gt;← Back&amp;lt;/a&amp;gt;",
            ))
            return
        }
    }

    cost, err := wr.QuoteCost(cookie.Value, 1)
    if err != nil {
        c.Data(http.StatusOK, "text/html; charset=utf-8", page(
            "Skip the line",
            fmt.Sprintf("&amp;lt;h1&amp;gt;Skip the line&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;%s&amp;lt;/p&amp;gt;&amp;lt;a href='/'&amp;gt;← Back&amp;lt;/a&amp;gt;", err.Error()),
        ))
        return
    }

    verbose.Printf("GET /queue/purchase — cost=$%.2f queue=%d", cost, wr.QueueDepth())
    c.Data(http.StatusOK, "text/html; charset=utf-8", purchasePage(cost, wr.PassDuration()))
}

// handlePurchaseConfirm processes the payment and promotes the token.
// In production: verify Stripe webhook signature before calling PromoteTokenToFront.
func handlePurchaseConfirm(c *gin.Context) {
    cookie, err := c.Request.Cookie("room_ticket")
    if err != nil || cookie.Value == "" {
        c.JSON(http.StatusBadRequest, gin.H{"error": "no room_ticket cookie"})
        return
    }

    result, err := wr.PromoteTokenToFront(cookie.Value)
    if err != nil {
        verbose.Printf("POST /queue/purchase/confirm — promotion failed: %v", err)
        c.Data(http.StatusOK, "text/html; charset=utf-8", page(
            "Payment failed",
            fmt.Sprintf("&amp;lt;h1&amp;gt;Something went wrong&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;%s&amp;lt;/p&amp;gt;&amp;lt;a href='/'&amp;gt;← Back&amp;lt;/a&amp;gt;", err.Error()),
        ))
        return
    }

    // ── THE KEY MOMENT ────────────────────────────────────────────────────
    // Register the VIP pass token with verbose FIRST — before the cookie
    // is set, before anything is logged, before the response is written.
    //
    // After this line, if the pass token value appears anywhere in any
    // log line this process writes, verbose replaces it with [VIP_PASS].
    //
    // Do NOT log the token value, any prefix of it, or any derivative.
    // verbose scrubs the full registered value — a truncated prefix escapes
    // the scrubber entirely. Log metadata only: cost, whether a pass was
    // issued, queue depth.
    if result.PassToken != "" {
        if err := verbose.AddSecret(verbose.SecretBytes(result.PassToken), "[VIP_PASS]"); err != nil {
            verbose.Printf("POST /queue/purchase/confirm — failed to protect pass token: %v", err)
        }
    }

    // safe to log now — pass token is scrubbed, metadata only
    verbose.Printf("POST /queue/purchase/confirm — promoted  cost=$%.2f  pass_issued=%v  queue=%d",
        result.Cost, result.PassToken != "", wr.QueueDepth())

    // set the VIP pass cookie so the client is auto-promoted on re-entry
    if result.PassToken != "" {
        http.SetCookie(c.Writer, &amp;amp;http.Cookie{
            Name:     "room_pass",
            Value:    result.PassToken,
            Path:     wr.CookiePath(),
            MaxAge:   int(wr.PassDuration().Seconds()),
            HttpOnly: true,
            Secure:   false, // set true in production behind TLS
            SameSite: http.SameSiteLaxMode,
        })
    }

    passMsg := ""
    if result.PassToken != "" {
        passMsg = fmt.Sprintf("&amp;lt;p&amp;gt;Your VIP pass is valid for &amp;lt;strong&amp;gt;%s&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;",
            wr.PassDuration().Round(time.Minute))
    }
    c.Data(http.StatusOK, "text/html; charset=utf-8", page("Payment confirmed",
        fmt.Sprintf(`&amp;lt;h1&amp;gt;Payment confirmed — $%.2f&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;You've been moved to the front of the line!&amp;lt;/p&amp;gt;%s
        &amp;lt;script&amp;gt;setTimeout(function(){ window.location.href = "/"; }, 2000);&amp;lt;/script&amp;gt;
        &amp;lt;noscript&amp;gt;&amp;lt;a href="/"&amp;gt;← Click here&amp;lt;/a&amp;gt;&amp;lt;/noscript&amp;gt;`, result.Cost, passMsg),
    ))
}

// ── page handlers — all gated by the waiting room ─────────────────────────

const simulatedLatency = 500 * time.Millisecond

func homePage(c *gin.Context) {
    time.Sleep(simulatedLatency)
    c.Data(http.StatusOK, "text/html; charset=utf-8", page("Home",
        `&amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;This server admits at most &amp;lt;strong&amp;gt;5 concurrent requests&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
        &amp;lt;p&amp;gt;Run &amp;lt;code&amp;gt;ab -c 30 -n 500 http://localhost:8080/about&amp;lt;/code&amp;gt; and watch the logs.&amp;lt;/p&amp;gt;
        &amp;lt;nav&amp;gt;&amp;lt;a href="/about"&amp;gt;About&amp;lt;/a&amp;gt; · &amp;lt;a href="/pricing"&amp;gt;Pricing&amp;lt;/a&amp;gt; · &amp;lt;a href="/contact"&amp;gt;Contact&amp;lt;/a&amp;gt;&amp;lt;/nav&amp;gt;`,
    ))
}

func aboutPage(c *gin.Context) {
    time.Sleep(simulatedLatency)
    c.Data(http.StatusOK, "text/html; charset=utf-8", page("About",
        `&amp;lt;h1&amp;gt;About&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;Built with &amp;lt;strong&amp;gt;room&amp;lt;/strong&amp;gt;, &amp;lt;strong&amp;gt;figtree&amp;lt;/strong&amp;gt;, and &amp;lt;strong&amp;gt;verbose&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;
        &amp;lt;a href="/"&amp;gt;← Home&amp;lt;/a&amp;gt;`,
    ))
}

func pricingPage(c *gin.Context) {
    time.Sleep(simulatedLatency)
    c.Data(http.StatusOK, "text/html; charset=utf-8", page("Pricing",
        `&amp;lt;h1&amp;gt;Pricing&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;Skip the line: &amp;lt;strong&amp;gt;$2.50/position&amp;lt;/strong&amp;gt; + 90-minute VIP pass.&amp;lt;/p&amp;gt;
        &amp;lt;a href="/"&amp;gt;← Home&amp;lt;/a&amp;gt;`,
    ))
}

func contactPage(c *gin.Context) {
    time.Sleep(simulatedLatency)
    c.Data(http.StatusOK, "text/html; charset=utf-8", page("Contact",
        `&amp;lt;h1&amp;gt;Contact&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;hello@example.com&amp;lt;/p&amp;gt;&amp;lt;a href="/"&amp;gt;← Home&amp;lt;/a&amp;gt;`,
    ))
}

// page wraps a body fragment in a complete HTML document.
func page(title, body string) []byte {
    return []byte(`&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html lang="en"&amp;gt;&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;&amp;lt;title&amp;gt;` + title + `&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;body{font-family:system-ui,sans-serif;max-width:700px;margin:4rem auto;padding:0 1.5rem}
    h1{margin-bottom:1rem}p{margin-bottom:1rem}code{background:#f0f0f0;padding:.1em .4em;border-radius:3px}
    a{color:#6c8ef5}&amp;lt;/style&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;` + body + `&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;`)
}

// purchasePage renders the skip-the-line confirmation page.
func purchasePage(cost float64, passDur time.Duration) []byte {
    passNote := ""
    if passDur &amp;gt; 0 {
        passNote = fmt.Sprintf(
            `&amp;lt;p&amp;gt;Includes a &amp;lt;strong&amp;gt;%s VIP pass&amp;lt;/strong&amp;gt; — re-enter the queue anytime during that window and skip for free.&amp;lt;/p&amp;gt;`,
            passDur.Round(time.Minute))
    }
    return []byte(fmt.Sprintf(`&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;title&amp;gt;Skip the line&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body style="font-family:system-ui;max-width:500px;margin:4rem auto;padding:0 1.5rem"&amp;gt;
    &amp;lt;h1&amp;gt;Skip the line — $%.2f&amp;lt;/h1&amp;gt;%s
    &amp;lt;form method="POST" action="/queue/purchase/confirm"&amp;gt;
      &amp;lt;button type="submit" style="background:#6c8ef5;color:#fff;border:none;padding:.75rem 2rem;border-radius:8px;font-size:1rem;cursor:pointer"&amp;gt;
        Confirm payment — $%.2f
      &amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
    &amp;lt;p style="margin-top:1rem;font-size:.8rem;color:#666"&amp;gt;Demo mode — no real payment processed.&amp;lt;/p&amp;gt;
    &amp;lt;a href="/"&amp;gt;← Back to waiting room&amp;lt;/a&amp;gt;
    &amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;`, cost, passNote, cost))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;net/http&lt;/code&gt; to imports.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Move &lt;code&gt;verbose.AddSecret&lt;/code&gt; to after &lt;code&gt;http.SetCookie&lt;/code&gt;. Run the server, issue a key by clicking "Pay to skip", then check &lt;code&gt;logs/basicwebapp.log&lt;/code&gt;. Find the &lt;code&gt;POST /queue/purchase/confirm&lt;/code&gt; line. The pass token appears in plaintext because verbose did not know about it yet. Move &lt;code&gt;AddSecret&lt;/code&gt; back to immediately after &lt;code&gt;PromoteTokenToFront&lt;/code&gt; returns, before anything else.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 8 — The bash test script
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;test.sh&lt;/code&gt;. This script is the pass/fail gate. Exit &lt;code&gt;0&lt;/code&gt; means every assertion passed — your implementation is correct. It fails fast on the first failed assertion and tells you which step to revisit.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env bash
set -euo pipefail

# ── dependency check ──────────────────────────────────────────────────────────
if ! command -v curl &amp;amp;&amp;gt;/dev/null; then
    echo "ERROR: curl is required."; exit 1
fi
if ! command -v jq &amp;amp;&amp;gt;/dev/null; then
    echo "ERROR: jq is required."
    echo "  macOS: brew install jq"
    echo "  Linux: sudo apt install jq  OR  sudo yum install jq"
    exit 1
fi
if ! command -v ab &amp;amp;&amp;gt;/dev/null; then
    echo "ERROR: apache bench (ab) is required."
    echo "  macOS: brew install httpd"
    echo "  Linux: sudo apt install apache2-utils"
    exit 1
fi

# ── config ────────────────────────────────────────────────────────────────────
BASE="http://127.0.0.1:8080"
LOG_FILE="./logs/basicwebapp.log"

# ── helpers ───────────────────────────────────────────────────────────────────
pass() { echo "  PASS: $1"; }
fail() { echo "  FAIL: $1 — $2"; exit 1; }

assert_log_contains() {
    local label="$1" pattern="$2" step="$3"
    if ! grep -qF "$pattern" "$LOG_FILE" 2&amp;gt;/dev/null; then
        fail "$label" "expected '$pattern' in log — not found (see step $step)"
    fi
    pass "$label"
}

assert_no_plaintext() {
    local label="$1" secret="$2" step="$3"
    if grep -qF "$secret" "$LOG_FILE" 2&amp;gt;/dev/null; then
        fail "$label" "plaintext secret found in log (see step $step)"
    fi
    pass "$label"
}

assert_status() {
    local label="$1" expected="$2" actual="$3" step="$4"
    if [ "$actual" -ne "$expected" ]; then
        fail "$label" "expected HTTP $expected, got $actual (see step $step)"
    fi
    pass "$label"
}

# ── build and start ───────────────────────────────────────────────────────────
echo "=&amp;gt; building..."
go build -o basicwebapp_bin . || { echo "Build failed."; exit 1; }

echo "=&amp;gt; starting server..."
./basicwebapp_bin &amp;amp;
SERVER_PID=$!
trap 'kill $SERVER_PID 2&amp;gt;/dev/null; rm -f basicwebapp_bin' EXIT

for i in $(seq 1 20); do
    if curl -sf "$BASE/" &amp;amp;&amp;gt;/dev/null; then break; fi
    sleep 0.5
done

echo ""
echo "── assertion 1: server started and log file exists (Step 4) ─────────────"
if [ ! -f "$LOG_FILE" ]; then
    fail "log file exists" "logs/basicwebapp.log not found — check verbose.NewLogger (see step 4)"
fi
pass "log file exists"

echo ""
echo "── assertion 2: config loaded and logged (Step 2 + 4) ───────────────────"
assert_log_contains "config line in log" "config:" "2"

echo ""
echo "── assertion 3: waiting room activates under load (Step 5 + 6) ──────────"
echo "   running ab -c 30 -n 100 $BASE/about (10s)..."
ab -c 30 -n 100 -t 10 "$BASE/about" &amp;amp;&amp;gt;/dev/null || true
sleep 2
assert_log_contains "[FULL] in log"  "[ FULL   ]"  "6"
assert_log_contains "[QUEUE] in log" "[ QUEUE  ]"  "6"
assert_log_contains "[ENTER] in log" "[ ENTER  ]"  "6"

echo ""
echo "── assertion 4: purchase page accessible (Step 7) ───────────────────────"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/queue/purchase")
assert_status "GET /queue/purchase returns 400" 400 "$STATUS" "7"

echo ""
echo "── assertion 5: VIP pass token scrubbed from log (Step 7) ──────────────"
COOKIE_JAR=$(mktemp)
for i in $(seq 1 6); do
    curl -s -o /dev/null "$BASE/about" &amp;amp;
done
sleep 0.3
curl -s -o /dev/null -c "$COOKIE_JAR" "$BASE/about" || true
TICKET=$(grep "room_ticket" "$COOKIE_JAR" | awk '{print $NF}' || true)

if [ -n "$TICKET" ]; then
    PASS_TOKEN=$(curl -s -b "$COOKIE_JAR" -c "$COOKIE_JAR" \
        -X POST "$BASE/queue/purchase/confirm" \
        -D - -o /dev/null 2&amp;gt;/dev/null \
        | grep -i "room_pass" | grep -oP 'room_pass=\K[^;]+' || true)

    if [ -n "$PASS_TOKEN" ]; then
        assert_no_plaintext "VIP pass token not in log" "$PASS_TOKEN" "7"
        assert_log_contains "[VIP_PASS] marker in log" "[VIP_PASS]" "7"
    else
        pass "VIP pass token not in log (no pass token issued — room may not have been full)"
    fi
else
    pass "VIP pass token check skipped (could not obtain room_ticket cookie)"
fi
rm -f "$COOKIE_JAR"

wait 2&amp;gt;/dev/null || true

echo ""
echo "── assertion 6: ROOM_CAP mutation logged (Step 3) ───────────────────────"
export ROOM_CAP=8
echo "   waiting up to 90s for ROOM_CAP mutation to appear in log..."
for i in $(seq 1 18); do
    if grep -qF "room-cap" "$LOG_FILE" 2&amp;gt;/dev/null; then
        pass "ROOM_CAP mutation in log"
        break
    fi
    sleep 5
    if [ "$i" -eq 18 ]; then
        fail "ROOM_CAP mutation in log" "mutation not seen after 90s — check Pollinate:true and mutations goroutine (see step 3)"
    fi
done

echo ""
echo "════════════════════════════════════════════════════════════════════════"
echo "  All assertions passed. Your implementation is correct."
echo "════════════════════════════════════════════════════════════════════════"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Make it executable and run it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x test.sh
./test.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If every assertion passes you see the final banner. If any assertion fails the script exits immediately with the step number to revisit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9 — Closing: What You Built and What Comes Next
&lt;/h2&gt;

&lt;p&gt;You started with an empty directory. You finished with a four-page Gin web application that admits at most 5 concurrent requests, queues the rest in FIFO order with a live-updating waiting room page, issues paid VIP passes that auto-promote returning clients for 90 minutes, and whose log file is provably safe to hand to a support engineer. Run &lt;code&gt;./test.sh&lt;/code&gt; one final time and watch every assertion pass.&lt;/p&gt;

&lt;p&gt;Take a moment to understand what each package actually did.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;room&lt;/code&gt; is not rate limiting. Rate limiting drops requests or returns 429. &lt;code&gt;room&lt;/code&gt; keeps them — every request gets a ticket, sees its position, and is admitted automatically when a slot opens. The reaper cleans up abandoned clients so ghost tickets never stall the queue. The promotion system with &lt;code&gt;PromoteTokenToFront&lt;/code&gt; and &lt;code&gt;GrantPass&lt;/code&gt; is a complete commercial primitive: you can charge per position, issue time-limited passes, and let the middleware handle the rest. Your handlers never change — they see normal requests arriving at the rate you configured.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;figtree&lt;/code&gt; is not a flag parser. It is a priority-ordered configuration resolver with live mutation tracking. The moment &lt;code&gt;ROOM_CAP&lt;/code&gt; changed in the environment, &lt;code&gt;wr.SetCap&lt;/code&gt; was called — no restart, no dropped requests, no intervention. In production that is how you respond to traffic spikes: your autoscaler updates the env var, figtree detects it, the room expands. The &lt;code&gt;RateFunc&lt;/code&gt; reading from &lt;code&gt;*figs.Float64(kRatePerPosition)&lt;/code&gt; on every call means your skip-the-line pricing can change live too.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;verbose&lt;/code&gt; is not just a logger. The moment &lt;code&gt;PromoteTokenToFront&lt;/code&gt; returned a &lt;code&gt;PassToken&lt;/code&gt;, that token's SHA-512 digest entered verbose's registry and every subsequent log line is scanned against it before it touches disk. The plaintext never persists. The rule you followed — log metadata, never the value or any substring — is the correct pattern for any secret: verbose is a safety net, not a substitute for keeping secrets out of log lines in the first place.&lt;/p&gt;




&lt;h3&gt;
  
  
  The packages used in this tutorial are part of a larger body of open source work
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;room&lt;/code&gt;, &lt;code&gt;figtree&lt;/code&gt;, and &lt;code&gt;verbose&lt;/code&gt; were all written by &lt;strong&gt;Andrei Merlescu&lt;/strong&gt; — &lt;a href="https://github.com/andreimerlescu" rel="noopener noreferrer"&gt;@andreimerlescu&lt;/a&gt; on GitHub. His profile carries 99 public repositories built across 17 years of professional software engineering spanning Cisco, Oracle, Warner Bros. Games, and SurgePays.&lt;/p&gt;

&lt;p&gt;Other packages worth exploring alongside the three you just used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/sema" rel="noopener noreferrer"&gt;&lt;code&gt;sema&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — the semaphore that backs &lt;code&gt;room&lt;/code&gt;. Dynamic resizing, EWMA utilization tracking, context cancellation, drain/reset for maintenance windows. Zero-allocation hot path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/checkfs" rel="noopener noreferrer"&gt;&lt;code&gt;checkfs&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — filesystem existence and permission checks. Pairs naturally with figtree when you want to validate that a config-supplied path actually exists before your server starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;&lt;code&gt;lemmings&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — load testing built around the concept of NPCs moving through your infrastructure as simulated users across geographic terrains and pack sizes. If you want to know what your waiting room does under real traffic before you ship it, lemmings is how you find out.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>logging</category>
      <category>infrastructure</category>
      <category>growth</category>
    </item>
    <item>
      <title>From Zero to Hero: Building a Key Issuance Server with `verbose` and `figtree`</title>
      <dc:creator>Andrei Merlescu</dc:creator>
      <pubDate>Mon, 20 Apr 2026 15:53:15 +0000</pubDate>
      <link>https://dev.to/andreimerlescu/from-zero-to-hero-building-a-key-issuance-server-with-verbose-and-figtree-npp</link>
      <guid>https://dev.to/andreimerlescu/from-zero-to-hero-building-a-key-issuance-server-with-verbose-and-figtree-npp</guid>
      <description>&lt;p&gt;In August 2024 Andrei Merlescu wrote a package called &lt;a href="https://github.com/andreimerlescu/verbose" rel="noopener noreferrer"&gt;verbose&lt;/a&gt; and released it under the Apache 2.0 license. The idea was novel: when interacting with sensitive information during multi-region deployments, you want to print to &lt;code&gt;STDOUT&lt;/code&gt; a censored expression of data while writing the unredacted form to log files — or in this tutorial's case, scrub secrets from the log file entirely. Private keys, passwords, serial numbers — these are sensitive and should not stream through STDOUT in devops contexts, especially in CI pipelines like GitHub Actions. With &lt;code&gt;verbose&lt;/code&gt;, your runtime can register new secrets as they become available, concurrently and safely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/andreimerlescu/verbose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;aSecret&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"abc123"&lt;/span&gt;
&lt;span class="c"&gt;// SecretBytes cast is required — AddSecret takes verbose.SecretBytes, not string&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecretBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aSecret&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"***"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;stdoutLogger&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LstdFlags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// Tof takes a *log.Logger, not an io.Writer&lt;/span&gt;
&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stdoutLogger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"this is a secret: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aSecret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prints to &lt;code&gt;STDOUT&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this is a secret: ***
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 1 — Scaffold and dependencies
&lt;/h2&gt;

&lt;p&gt;You are going to build a running HTTP server that issues, verifies, and revokes API keys. Every secret the server touches — the admin token that protects your endpoints, every key it issues — will be registered with the &lt;code&gt;verbose&lt;/code&gt; logging package the moment it is created. By the time you finish, you will be able to grep your own log file for any plaintext secret and find nothing. That is the goal.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;verbose&lt;/code&gt; is a logging package that scrubs registered secrets from every line it writes. &lt;code&gt;figtree&lt;/code&gt; is a configuration package that loads values from a YAML file, environment variables, and CLI flags in that priority order, with validators and mutation tracking built in.&lt;/p&gt;

&lt;p&gt;Create the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;keyserver &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;keyserver
go mod init github.com/example/keyserver
go get github.com/andreimerlescu/verbose@latest
go get github.com/andreimerlescu/figtree/v2@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the files you will fill in across the remaining steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;main.go config.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your &lt;code&gt;go.mod&lt;/code&gt; should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;keyserver&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="m"&gt;1.22&lt;/span&gt;

&lt;span class="n"&gt;require&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;andreimerlescu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="m"&gt;.0.14&lt;/span&gt;
    &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;andreimerlescu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;    &lt;span class="n"&gt;v0&lt;/span&gt;&lt;span class="m"&gt;.2.0&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keyserver/
├── go.mod
├── go.sum
├── config.yml
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing runs yet. That is fine. You have a clean workspace and both packages are available.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 — CLI design with figtree
&lt;/h2&gt;

&lt;p&gt;Now that the workspace is ready, the first thing to design is configuration. Before any HTTP server, any logger, any route — you need to know what the program accepts and where it reads it from. figtree handles all three sources — file, environment, flags — in one tree.&lt;/p&gt;

&lt;p&gt;Every config key is a Go constant. This is not optional style — it prevents typos from silently creating a second key that is never read.&lt;/p&gt;

&lt;p&gt;Add this to &lt;code&gt;main.go&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// main.go — complete file at this stage&lt;/span&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/andreimerlescu/figtree/v2"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// config keys — always constants, never raw strings at call sites&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;kHost&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"host"&lt;/span&gt;
    &lt;span class="n"&gt;kPort&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"port"&lt;/span&gt;
    &lt;span class="n"&gt;kLogDir&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"log-dir"&lt;/span&gt;
    &lt;span class="n"&gt;kTruncate&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"truncate"&lt;/span&gt;
    &lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"key-prefix"&lt;/span&gt;
    &lt;span class="n"&gt;kAdminToken&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"keyserver-admin-token"&lt;/span&gt; &lt;span class="c"&gt;// env: KEYSERVER_ADMIN_TOKEN&lt;/span&gt;
    &lt;span class="n"&gt;kOnCall&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"on-call-engineer"&lt;/span&gt;      &lt;span class="c"&gt;// env: ON_CALL_ENGINEER&lt;/span&gt;
    &lt;span class="n"&gt;kShiftDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"shift-duration"&lt;/span&gt;        &lt;span class="c"&gt;// env: SHIFT_DURATION&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Grow a tracked tree — Tracking enables the Mutations() channel,&lt;/span&gt;
    &lt;span class="c"&gt;// Pollinate re-checks env vars on every Getter call (needed for Step 7),&lt;/span&gt;
    &lt;span class="c"&gt;// ConfigFile makes the intent explicit: this app is config-file-first.&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;With&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Tracking&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Germinate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c"&gt;// ignore -test.* flags during go test&lt;/span&gt;
        &lt;span class="n"&gt;Pollinate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c"&gt;// re-read env vars on every Getter call&lt;/span&gt;
        &lt;span class="n"&gt;ConfigFile&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"./config.yml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// -- server --&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"host address to listen on"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"port to listen on"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// -- logging --&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"./logs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"directory to write log files into"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kTruncate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"truncate log file on each run"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// -- keys --&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ks_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"prefix for issued API keys"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// RuleNoFlags means figtree will never register a CLI flag for this key.&lt;/span&gt;
    &lt;span class="c"&gt;// The only way to supply it is via KEYSERVER_ADMIN_TOKEN or config.yml.&lt;/span&gt;
    &lt;span class="c"&gt;// The key name is deliberately long — verbose by design.&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kAdminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"admin token — use KEYSERVER_ADMIN_TOKEN env var only"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kAdminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RuleNoFlags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// -- on-call rotation --&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Darron"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"name of the engineer currently on call"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// shift-duration drives the rotation goroutine added in Step 3.&lt;/span&gt;
    &lt;span class="c"&gt;// Default is 7 hours. SHIFT_DURATION=1 overrides it for local testing.&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewUnitDuration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"length of one on-call shift in hours"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Problems() catches developer mistakes — duplicate keys, bad validator&lt;/span&gt;
    &lt;span class="c"&gt;// combos — before Load() runs. These are your bugs, not user input errors.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Problems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"figtree problem: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Load resolves: config.yml → env vars → CLI flags (in that priority order)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"figtree.Load: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Print everything so you can see what loaded — fmt.Println for now,&lt;/span&gt;
    &lt;span class="c"&gt;// verbose replaces this in Step 4.&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"host=%s port=%d log-dir=%s truncate=%v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kHost&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kTruncate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key-prefix=%s on-call=%s shift=%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin-token=%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kAdminToken&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;config.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1"&lt;/span&gt;
&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;             &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;span class="na"&gt;log-dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./logs"&lt;/span&gt;
&lt;span class="na"&gt;truncate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;key-prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ks_"&lt;/span&gt;
&lt;span class="na"&gt;on-call-engineer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Darron"&lt;/span&gt;
&lt;span class="na"&gt;shift-duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;   &lt;span class="m"&gt;7&lt;/span&gt;
&lt;span class="c1"&gt;# keyserver-admin-token is intentionally absent from source control.&lt;/span&gt;
&lt;span class="c1"&gt;# Set it via: export KEYSERVER_ADMIN_TOKEN=your-secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;KEYSERVER_ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysecret go run &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see all values printed. Notice &lt;code&gt;admin-token=mysecret&lt;/code&gt; is in your terminal output right now. That is expected — verbose is not wired yet. You will fix that in Step 4 and never see it in plaintext again.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Try running &lt;code&gt;go run . -keyserver-admin-token=mysecret&lt;/code&gt;. figtree will not register that flag because of &lt;code&gt;RuleNoFlags&lt;/code&gt; — the flag is unknown to the flag package and your program will exit with an error. The env var is the only valid path. This is intentional.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3 — Validators, Problems(), and mutations
&lt;/h2&gt;

&lt;p&gt;Now that the tree is declared, you lock it down. Validators reject bad input before your program does anything with it. The &lt;code&gt;Problems()&lt;/code&gt; check you already have catches declaration mistakes. The mutations goroutine watches for runtime changes — which is where the on-call rotation lives.&lt;/p&gt;

&lt;p&gt;Add these diffs to &lt;code&gt;main.go&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After &lt;code&gt;figs.NewString(kHost, ...)&lt;/code&gt; — add validator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"host address to listen on"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// add this&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kHost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssureStringNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"port to listen on"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After &lt;code&gt;figs.NewInt(kPort, ...)&lt;/code&gt; — add validator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"port to listen on"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// add this&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssureIntInRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;65535&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"./logs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"directory to write log files into"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After &lt;code&gt;figs.NewString(kLogDir, ...)&lt;/code&gt; — add validator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"./logs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"directory to write log files into"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// add this&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssureStringNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kTruncate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"truncate log file on each run"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After &lt;code&gt;figs.NewString(kKeyPrefix, ...)&lt;/code&gt; — add validator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ks_"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"prefix for issued API keys"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// add this&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssureStringNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kAdminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"admin token — use KEYSERVER_ADMIN_TOKEN env var only"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After &lt;code&gt;figs.WithRule(kAdminToken, ...)&lt;/code&gt; — add validator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kAdminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RuleNoFlags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// add this — admin token must be present at startup&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kAdminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssureStringNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Darron"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"name of the engineer currently on call"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After &lt;code&gt;figs.NewString(kOnCall, ...)&lt;/code&gt; — add validator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Darron"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"name of the engineer currently on call"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// add this&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssureStringNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewUnitDuration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"length of one on-call shift in hours"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After &lt;code&gt;figs.NewUnitDuration(kShiftDuration, ...)&lt;/code&gt; — add validators:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewUnitDuration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"length of one on-call shift in hours"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// add these — shifts must be at least 1 hour, at most 12&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssureDurationMin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hour&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssureDurationMax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hour&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Problems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;problems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now add the mutations goroutine and the on-call shift rotation. Both go &lt;strong&gt;after&lt;/strong&gt; &lt;code&gt;figs.Load()&lt;/code&gt; — the tree must be live before you watch it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"figtree.Load: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// add this block&lt;/span&gt;
    &lt;span class="c"&gt;// watch for any config value changing at runtime and log it&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// verbose.Printf replaces this in Step 4&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config mutation: %s changed from %v to %v at %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Old&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;When&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="c"&gt;// on-call rotation — fires every minute, updates kOnCall based on&lt;/span&gt;
    &lt;span class="c"&gt;// the current hour. We check every minute so the change is never&lt;/span&gt;
    &lt;span class="c"&gt;// more than 60 seconds late.&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StoreString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onCallEngineer&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"host=%s port=%d log-dir=%s truncate=%v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the &lt;code&gt;onCallEngineer&lt;/code&gt; function at the bottom of &lt;code&gt;main.go&lt;/code&gt;, outside &lt;code&gt;main&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// onCallEngineer returns the name of the engineer on call right now.&lt;/span&gt;
&lt;span class="c"&gt;//&lt;/span&gt;
&lt;span class="c"&gt;//   04:00–07:59  → TEAM     (everyone expected online)&lt;/span&gt;
&lt;span class="c"&gt;//   08:00–14:59  → Darron&lt;/span&gt;
&lt;span class="c"&gt;//   15:00–21:59  → Bradley&lt;/span&gt;
&lt;span class="c"&gt;//   22:00–03:59  → Kevin    (crosses midnight)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;onCallEngineer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hour&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"TEAM"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Darron"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Bradley"&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="c"&gt;// 22:00–03:59&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Kevin"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;KEYSERVER_ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysecret go run &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To prove the validator works, temporarily set &lt;code&gt;port: 99999&lt;/code&gt; in &lt;code&gt;config.yml&lt;/code&gt; and run again. You will see figtree refuse to load with a clear error. Set it back to &lt;code&gt;8080&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Move the mutations goroutine to before &lt;code&gt;figs.Load()&lt;/code&gt; and run it. The channel exists but the tree has not resolved its values yet — mutations fired during load will not be seen because the goroutine may not be scheduled before load completes. Always start the mutations goroutine after &lt;code&gt;Load()&lt;/code&gt; returns.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 4 — Wire verbose, replace fmt, register the admin token
&lt;/h2&gt;

&lt;p&gt;Now that figtree is loading and validating configuration correctly, you can wire up the logger. verbose needs to be initialised before any log call — and the admin token needs to be registered as a secret immediately after, before anything else in the program touches it.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;verbose&lt;/code&gt; to your imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
    &lt;span class="c"&gt;// add this&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/andreimerlescu/verbose"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/andreimerlescu/figtree/v2"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the verbose initialisation block right after the goroutines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StoreString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onCallEngineer&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="c"&gt;// add this block&lt;/span&gt;
    &lt;span class="c"&gt;// initialise verbose before any log call — guard() will stderr and no-op&lt;/span&gt;
    &lt;span class="c"&gt;// if you call verbose functions before this point&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;"keyserver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Truncate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kTruncate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;DirMode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="n"&gt;o755&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;FileMode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="n"&gt;o640&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"verbose.NewLogger: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// read the admin token once — this is the value we protect at startup&lt;/span&gt;
    &lt;span class="n"&gt;adminToken&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kAdminToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// register the admin token as a verbose secret immediately.&lt;/span&gt;
    &lt;span class="c"&gt;// verbose stores only the SHA-512 digest — the plaintext is never retained.&lt;/span&gt;
    &lt;span class="c"&gt;// every log line written after this point that contains the raw token value&lt;/span&gt;
    &lt;span class="c"&gt;// will have it replaced with [ADMIN_TOKEN] automatically.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecretBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adminToken&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"[ADMIN_TOKEN]"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"verbose.AddSecret: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// proof that scrubbing is active — this line contains the raw token.&lt;/span&gt;
    &lt;span class="c"&gt;// open logs/keyserver.log after running and you will see [ADMIN_TOKEN].&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin token registered — value in log: %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;adminToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// Version() is a function call, not a variable&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"keyserver starting (verbose v%s / figtree v%s)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VERSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figtree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"host=%s port=%d log-dir=%s truncate=%v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;fmt.Printf&lt;/code&gt; startup summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// remove this&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"host=%s port=%d log-dir=%s truncate=%v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kHost&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kTruncate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"key-prefix=%s on-call=%s shift=%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin-token=%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kAdminToken&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c"&gt;// replace with this&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"host=%s port=%d log-dir=%s truncate=%v key-prefix=%s on-call=%s shift=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kHost&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kTruncate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;fmt.Printf&lt;/code&gt; in the mutations goroutine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// remove this&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config mutation: %s changed from %v to %v at %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Old&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;When&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c"&gt;// replace with this&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config mutation: %s changed from %v to %v at %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Old&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;When&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;KEYSERVER_ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysecret go run &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;logs/keyserver.log&lt;/code&gt;. Find the line containing "admin token registered". The value &lt;code&gt;mysecret&lt;/code&gt; does not appear — you will see &lt;code&gt;[ADMIN_TOKEN]&lt;/code&gt; in its place. From this point forward, &lt;code&gt;mysecret&lt;/code&gt; cannot appear in any log line this process writes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Call &lt;code&gt;verbose.Printf("test")&lt;/code&gt; before &lt;code&gt;verbose.NewLogger&lt;/code&gt; — move it above the &lt;code&gt;NewLogger&lt;/code&gt; block and run. You will see the message printed to stderr with a "NewLogger or SetLogger has not been called" prefix. verbose does not panic — it fails open to stderr. Move the call back below &lt;code&gt;NewLogger&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 5 — HTTP server skeleton
&lt;/h2&gt;

&lt;p&gt;With logging and configuration solid, the server can be wired up. The three routes are stubs for now — each returns &lt;code&gt;200 OK&lt;/code&gt; with a placeholder body. The &lt;code&gt;requireAdmin&lt;/code&gt; middleware is the important piece here: it logs every auth attempt, which means the admin token will be scrubbed from those log lines automatically.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;net/http&lt;/code&gt; and &lt;code&gt;encoding/json&lt;/code&gt; to your imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
    &lt;span class="c"&gt;// add these&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/andreimerlescu/verbose"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/andreimerlescu/figtree/v2"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the server block at the end of &lt;code&gt;main&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"host=%s port=%d log-dir=%s truncate=%v key-prefix=%s on-call=%s shift=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kHost&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kLogDir&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kTruncate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kOnCall&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kShiftDuration&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// add this block&lt;/span&gt;
    &lt;span class="c"&gt;// capture prefix once — used in handlers added in Step 6&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kKeyPrefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;

    &lt;span class="c"&gt;// POST /keys — issue a new API key (admin only)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST /keys"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requireAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"not implemented"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;

    &lt;span class="c"&gt;// GET /keys/{id}/verify — verify a presented key&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET /keys/{id}/verify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"not implemented"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// DELETE /keys/{id} — revoke and remove a key (admin only)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DELETE /keys/{id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requireAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNoContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;

    &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s:%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kHost&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;figs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kPort&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"keyserver listening on http://%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// ListenAndServe only returns on error — log it with a trace and exit&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"http.ListenAndServe: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TracefReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ListenAndServe failed: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below — end of main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;requireAdmin&lt;/code&gt; and &lt;code&gt;bearerToken&lt;/code&gt; below &lt;code&gt;onCallEngineer&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// requireAdmin rejects requests whose Bearer token does not match adminToken.&lt;/span&gt;
&lt;span class="c"&gt;// The token is already a verbose secret — the log line is safe.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;requireAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adminToken&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;presented&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bearerToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s %s — auth attempt from %s token=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoteAddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;presented&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;presented&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;adminToken&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s %s — FORBIDDEN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"forbidden"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusForbidden&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// bearerToken extracts the token from Authorization: Bearer &amp;lt;token&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;bearerToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Bearer "&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the server and curl the stubs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;KEYSERVER_ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysecret go run &lt;span class="nb"&gt;.&lt;/span&gt; &amp;amp;

curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/keys &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer mysecret"&lt;/span&gt;

curl &lt;span class="nt"&gt;-s&lt;/span&gt; http://localhost:8080/keys/test/verify

curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; DELETE http://localhost:8080/keys/test &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer mysecret"&lt;/span&gt;

&lt;span class="nb"&gt;kill&lt;/span&gt; %1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check &lt;code&gt;logs/keyserver.log&lt;/code&gt;. The auth lines show &lt;code&gt;token=[ADMIN_TOKEN]&lt;/code&gt; — never &lt;code&gt;mysecret&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; If you are on Go below 1.22, &lt;code&gt;http.HandleFunc("POST /keys", ...)&lt;/code&gt; will not compile — the method prefix in the pattern is a 1.22 feature. Run &lt;code&gt;go version&lt;/code&gt; to check. If needed, update your toolchain: &lt;code&gt;go get toolchain@go1.22.0&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 6 — Issuance, verification, revocation, and runtime secret registration
&lt;/h2&gt;

&lt;p&gt;This is the core of the application and the core demonstration of verbose. The moment a key is generated, &lt;code&gt;verbose.AddSecret&lt;/code&gt; is called before anything else — before the key is stored, before it is logged, before it is returned to the caller. The window between generation and registration is zero.&lt;/p&gt;

&lt;p&gt;When a key is deleted, &lt;code&gt;verbose.RemoveSecret&lt;/code&gt; is called. This is safe because a deleted key is dead — no future request will present it, so there is no future log line to protect. Removing it keeps the verbose runtime lean: the secrets registry does not grow forever, and scanning each log line is O(n) in the number of registered secrets. In a long-running server issuing thousands of keys, this matters. The same pattern applies to user sessions: register the session token on login, remove it on logout.&lt;/p&gt;

&lt;p&gt;Add the key store above &lt;code&gt;main&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// 3 lines above — imports&lt;/span&gt;
&lt;span class="c"&gt;// add this block after imports, before main&lt;/span&gt;

&lt;span class="c"&gt;// keyRecord holds metadata for one issued API key.&lt;/span&gt;
&lt;span class="c"&gt;// The token value is the map key — never stored inside the struct.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;keyRecord&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt;       &lt;span class="kt"&gt;string&lt;/span&gt;    &lt;span class="s"&gt;`json:"id"`&lt;/span&gt;
    &lt;span class="n"&gt;IssuedAt&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt; &lt;span class="s"&gt;`json:"issued_at"`&lt;/span&gt;
    &lt;span class="n"&gt;IssuedTo&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;    &lt;span class="s"&gt;`json:"issued_to"`&lt;/span&gt;
    &lt;span class="n"&gt;Revoked&lt;/span&gt;  &lt;span class="kt"&gt;bool&lt;/span&gt;      &lt;span class="s"&gt;`json:"revoked"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;keyStoreMu&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RWMutex&lt;/span&gt;
    &lt;span class="n"&gt;keyStore&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;keyRecord&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// 3 lines below — func main() {&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;sync&lt;/code&gt;, &lt;code&gt;crypto/rand&lt;/code&gt;, and &lt;code&gt;encoding/hex&lt;/code&gt; to imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// add to import block&lt;/span&gt;
    &lt;span class="s"&gt;"crypto/rand"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/hex"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;POST /keys&lt;/code&gt; stub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST /keys"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requireAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// replace body&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;IssuedTo&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:"issued_to"`&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedTo&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST /keys — bad request from %s: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoteAddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"issued_to is required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;generateToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// TracefReturn logs with a stack trace and returns the error —&lt;/span&gt;
            &lt;span class="c"&gt;// capture the return value, do not discard it&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST /keys — token generation failed: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TracefReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"generateToken: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"internal error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// register with verbose FIRST — before store, before log, before response.&lt;/span&gt;
        &lt;span class="c"&gt;// after this line the token cannot appear in plaintext in any log output.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecretBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"[ISSUED_KEY]"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST /keys — failed to protect token: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"internal error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;rec&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;keyRecord&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;IssuedAt&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;IssuedTo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;keyStoreMu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;keyStore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;
        &lt;span class="n"&gt;keyStoreMu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c"&gt;// safe to log — token is already scrubbed to [ISSUED_KEY]&lt;/span&gt;
        &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST /keys — issued key=%s to=%s at=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedAt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RFC3339&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusCreated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"token"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"issued_to"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"issued_at"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedAt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RFC3339&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;GET /keys/{id}/verify&lt;/code&gt; stub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET /keys/{id}/verify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// replace body&lt;/span&gt;
        &lt;span class="n"&gt;presented&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bearerToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PathValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// log the attempt — if the caller sent a valid token it is already&lt;/span&gt;
        &lt;span class="c"&gt;// a verbose secret and will be scrubbed automatically&lt;/span&gt;
        &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET /keys/%s/verify — attempt from %s token=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoteAddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;presented&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;keyStoreMu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RLock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;keyStore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;presented&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;keyStoreMu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RUnlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Revoked&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET /keys/%s/verify — INVALID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"invalid or revoked key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusUnauthorized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET /keys/%s/verify — VALID issued_to=%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedTo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"valid"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"issued_to"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedTo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"issued_at"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedAt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RFC3339&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;DELETE /keys/{id}&lt;/code&gt; stub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// 3 lines above&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DELETE /keys/{id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requireAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adminToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// replace body&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PathValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;keyStoreMu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;keyStore&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Revoked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;keyStoreMu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DELETE /keys/%s — not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"key not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// the key is dead — safe to remove from verbose.&lt;/span&gt;
        &lt;span class="c"&gt;// removing it keeps the secrets registry lean: verbose scans every&lt;/span&gt;
        &lt;span class="c"&gt;// log line against every registered secret, so a smaller registry&lt;/span&gt;
        &lt;span class="c"&gt;// means faster logging. do not leave dead secrets registered forever.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoveSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecretBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DELETE /keys/%s — RemoveSecret error: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DELETE /keys/%s — revoked and removed from verbose (was issued to %s)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IssuedTo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNoContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="c"&gt;// 3 lines below&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;generateToken&lt;/code&gt; below &lt;code&gt;bearerToken&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// generateToken returns a cryptographically random token with the given prefix.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;generateToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hex&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Move &lt;code&gt;verbose.AddSecret&lt;/code&gt; to after &lt;code&gt;keyStoreMu.Lock()&lt;/code&gt; — just two lines later — and run the server. Issue a key. Look at the log line for &lt;code&gt;POST /keys — issued key=&lt;/code&gt;. You will see the raw token value in plaintext because it was logged by &lt;code&gt;requireAdmin&lt;/code&gt; in the auth check before it was registered. Order is not a style preference here. It is the security guarantee. Move &lt;code&gt;AddSecret&lt;/code&gt; back to first.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 7 — The on-call engineer shift in action
&lt;/h2&gt;

&lt;p&gt;The rotation goroutine has been running since Step 3, quietly updating a value. Now that verbose is wired, the mutation log entries are meaningful — and with &lt;code&gt;Pollinate: true&lt;/code&gt;, an engineer can override the on-call value live from a second terminal without restarting the server.&lt;/p&gt;

&lt;p&gt;The shift goroutine is already in place. The mutations goroutine is already using &lt;code&gt;verbose.Printf&lt;/code&gt; from Step 4. Run the server and open a second terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# terminal 1&lt;/span&gt;
&lt;span class="nv"&gt;KEYSERVER_ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysecret go run &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# terminal 2 — override the on-call engineer without restarting&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ON_CALL_ENGINEER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Kevin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch &lt;code&gt;logs/keyserver.log&lt;/code&gt; — within one minute you will see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[VERBOSE] keyserver.go:XX: config mutation: on-call-engineer changed from Darron to Kevin at 2026-04-20...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mutation fires because &lt;code&gt;Pollinate: true&lt;/code&gt; causes figtree to re-read &lt;code&gt;ON_CALL_ENGINEER&lt;/code&gt; every time &lt;code&gt;figs.String(kOnCall)&lt;/code&gt; is called — which the rotation goroutine does every minute.&lt;/p&gt;

&lt;p&gt;If the on-call engineer name were a sensitive internal codename — a security handle, a contractor alias, anything you would not want in a log shipped to an aggregator — one &lt;code&gt;verbose.AddSecret(verbose.SecretBytes(name), "[ON_CALL]")&lt;/code&gt; call in the rotation goroutine would scrub it from every future log line. The pattern is identical to what you did with the admin token.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mistake trap:&lt;/strong&gt; Remove &lt;code&gt;Pollinate: true&lt;/code&gt; from &lt;code&gt;figtree.Options&lt;/code&gt;, restart the server, and set &lt;code&gt;export ON_CALL_ENGINEER=Kevin&lt;/code&gt; again. No mutation fires. The env var changed but figtree did not re-read it because Pollinate was off. Put &lt;code&gt;Pollinate: true&lt;/code&gt; back.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 8 — The bash test script
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;test.sh&lt;/code&gt; in the project root. This script is the pass/fail gate for the tutorial. If your implementation is correct it exits &lt;code&gt;0&lt;/code&gt;. Each assertion failure prints which step to revisit and exits immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="c"&gt;# ── dependency check ──────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; curl &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ERROR: curl is required. Install it and rerun."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi
if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; jq &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"ERROR: jq is required."&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  macOS:  brew install jq"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  Linux:  sudo apt install jq  OR  sudo yum install jq"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# ── config ────────────────────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="nv"&gt;ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"test-admin-secret-1234"&lt;/span&gt;
&lt;span class="nv"&gt;BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:8080"&lt;/span&gt;
&lt;span class="nv"&gt;LOG_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"./logs/keyserver.log"&lt;/span&gt;

&lt;span class="c"&gt;# ── helpers ───────────────────────────────────────────────────────────────────&lt;/span&gt;
pass&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  PASS: &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
fail&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  FAIL: &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt; — &lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

assert_status&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;expected&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;actual&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;step&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$4&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$actual&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$expected&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;fail &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"expected HTTP &lt;/span&gt;&lt;span class="nv"&gt;$expected&lt;/span&gt;&lt;span class="s2"&gt;, got &lt;/span&gt;&lt;span class="nv"&gt;$actual&lt;/span&gt;&lt;span class="s2"&gt; (see step &lt;/span&gt;&lt;span class="nv"&gt;$step&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;
    &lt;span class="k"&gt;fi
    &lt;/span&gt;pass &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

assert_no_plaintext&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;step&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-qF&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$secret&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;fail &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"plaintext secret found in log — verbose.AddSecret not called before logging (see step &lt;/span&gt;&lt;span class="nv"&gt;$step&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;
    &lt;span class="k"&gt;fi
    &lt;/span&gt;pass &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

assert_log_contains&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;step&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-qF&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;fail &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"expected '&lt;/span&gt;&lt;span class="nv"&gt;$pattern&lt;/span&gt;&lt;span class="s2"&gt;' in log — not found (see step &lt;/span&gt;&lt;span class="nv"&gt;$step&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;
    &lt;span class="k"&gt;fi
    &lt;/span&gt;pass &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# ── build and start server ────────────────────────────────────────────────────&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; building..."&lt;/span&gt;
go build &lt;span class="nt"&gt;-o&lt;/span&gt; keyserver_bin &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Build failed — fix compilation errors first."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=&amp;gt; starting server..."&lt;/span&gt;
&lt;span class="nv"&gt;KEYSERVER_ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; ./keyserver_bin &amp;amp;
&lt;span class="nv"&gt;SERVER_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;'kill $SERVER_PID 2&amp;gt;/dev/null; rm -f keyserver_bin'&lt;/span&gt; EXIT

&lt;span class="c"&gt;# wait for server to be ready — retry up to 10 times&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;seq &lt;/span&gt;1 10&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    if &lt;/span&gt;curl &lt;span class="nt"&gt;-sf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys/test/verify"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;break
    &lt;/span&gt;&lt;span class="k"&gt;fi
    &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;0.5
&lt;span class="k"&gt;done

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 1: admin token is scrubbed from logs (Step 4) ─────────────"&lt;/span&gt;
assert_no_plaintext &lt;span class="s2"&gt;"admin token not in log"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"4"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 2: issue key for alice (Step 6) ────────────────────────────"&lt;/span&gt;
&lt;span class="nv"&gt;ALICE_RESP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%{http_code}"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"issued_to":"alice@example.com"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;ALICE_STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ALICE_RESP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;ALICE_BODY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ALICE_RESP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
assert_status &lt;span class="s2"&gt;"POST /keys alice"&lt;/span&gt; 201 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ALICE_STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;
&lt;span class="nv"&gt;ALICE_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ALICE_BODY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .token&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 3: issue key for bob (Step 6) ──────────────────────────────"&lt;/span&gt;
&lt;span class="nv"&gt;BOB_RESP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%{http_code}"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"issued_to":"bob@example.com"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;BOB_STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BOB_RESP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;BOB_BODY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BOB_RESP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
assert_status &lt;span class="s2"&gt;"POST /keys bob"&lt;/span&gt; 201 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BOB_STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;
&lt;span class="nv"&gt;BOB_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BOB_BODY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .token&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 4: issue key for carol (Step 6) ────────────────────────────"&lt;/span&gt;
&lt;span class="nv"&gt;CAROL_RESP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;%{http_code}"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"issued_to":"carol@example.com"}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;CAROL_STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CAROL_RESP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;CAROL_BODY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CAROL_RESP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
assert_status &lt;span class="s2"&gt;"POST /keys carol"&lt;/span&gt; 201 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CAROL_STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;
&lt;span class="nv"&gt;CAROL_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CAROL_BODY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; .token&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 5: verify alice (Step 6) ───────────────────────────────────"&lt;/span&gt;
&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ALICE_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/verify"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ALICE_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
assert_status &lt;span class="s2"&gt;"GET /keys alice/verify"&lt;/span&gt; 200 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 6: verify bob (Step 6) ─────────────────────────────────────"&lt;/span&gt;
&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BOB_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/verify"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$BOB_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
assert_status &lt;span class="s2"&gt;"GET /keys bob/verify"&lt;/span&gt; 200 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 7: verify carol (Step 6) ───────────────────────────────────"&lt;/span&gt;
&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CAROL_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/verify"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$CAROL_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
assert_status &lt;span class="s2"&gt;"GET /keys carol/verify"&lt;/span&gt; 200 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 8: revoke bob (Step 6) ─────────────────────────────────────"&lt;/span&gt;
&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; DELETE &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BOB_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
assert_status &lt;span class="s2"&gt;"DELETE /keys bob"&lt;/span&gt; 204 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 9: verify bob after revocation — expect 401 (Step 6) ───────"&lt;/span&gt;
&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BASE&lt;/span&gt;&lt;span class="s2"&gt;/keys/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BOB_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/verify"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$BOB_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
assert_status &lt;span class="s2"&gt;"GET /keys bob/verify after revoke"&lt;/span&gt; 401 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 10: alice and carol tokens not in log (Step 6) ─────────────"&lt;/span&gt;
assert_no_plaintext &lt;span class="s2"&gt;"alice token not in log"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ALICE_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;
assert_no_plaintext &lt;span class="s2"&gt;"carol token not in log"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CAROL_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 11: bob token not in log (Step 6) ──────────────────────────"&lt;/span&gt;
&lt;span class="c"&gt;# bob's token was removed via RemoveSecret after revocation.&lt;/span&gt;
&lt;span class="c"&gt;# if the implementation is correct the token never appeared in plaintext&lt;/span&gt;
&lt;span class="c"&gt;# because AddSecret was called before any logging.&lt;/span&gt;
assert_no_plaintext &lt;span class="s2"&gt;"bob token not in log"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BOB_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 12: scrub markers present in log (Step 4 + 6) ─────────────"&lt;/span&gt;
assert_log_contains &lt;span class="s2"&gt;"[ADMIN_TOKEN] in log"&lt;/span&gt; &lt;span class="s2"&gt;"[ADMIN_TOKEN]"&lt;/span&gt; &lt;span class="s2"&gt;"4"&lt;/span&gt;
assert_log_contains &lt;span class="s2"&gt;"[ISSUED_KEY] in log"&lt;/span&gt;  &lt;span class="s2"&gt;"[ISSUED_KEY]"&lt;/span&gt;  &lt;span class="s2"&gt;"6"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"── assertion 13: on-call mutation visible in log (Step 7) ───────────────"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ON_CALL_ENGINEER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"TEAM"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"   waiting up to 90s for on-call mutation to appear in log..."&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;seq &lt;/span&gt;1 18&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-qF&lt;/span&gt; &lt;span class="s2"&gt;"on-call-engineer"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;pass &lt;span class="s2"&gt;"on-call mutation in log"&lt;/span&gt;
        &lt;span class="nb"&gt;break
    &lt;/span&gt;&lt;span class="k"&gt;fi
    &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;5
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 18 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;fail &lt;span class="s2"&gt;"on-call mutation in log"&lt;/span&gt; &lt;span class="s2"&gt;"mutation not seen after 90s — check Pollinate:true and mutations goroutine (see step 7)"&lt;/span&gt;
    &lt;span class="k"&gt;fi
done

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"════════════════════════════════════════════════════════════════════════"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"  All assertions passed. Your implementation is correct."&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"════════════════════════════════════════════════════════════════════════"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it executable and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x test.sh
./test.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If every assertion passes you see the final banner. If any assertion fails the script exits immediately with the step number to revisit. Fix that step and rerun — the script always starts fresh.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9 — Closing: What You Built and What Comes Next
&lt;/h2&gt;

&lt;p&gt;You started this tutorial with an empty directory and two &lt;code&gt;go get&lt;/code&gt; commands. You finished with a running HTTP server that issues, verifies, and revokes API keys — and whose log file provably contains no plaintext secrets. Run &lt;code&gt;./test.sh&lt;/code&gt; one final time and watch every assertion pass. That exit &lt;code&gt;0&lt;/code&gt; is not a formality. It is a guarantee backed by SHA-512.&lt;/p&gt;

&lt;p&gt;Take a moment to understand what you actually built and why each piece was chosen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;verbose&lt;/code&gt; is not just a logger. Every other logger in the Go ecosystem — &lt;code&gt;log&lt;/code&gt;, &lt;code&gt;slog&lt;/code&gt;, &lt;code&gt;zap&lt;/code&gt;, &lt;code&gt;zerolog&lt;/code&gt; — will faithfully write whatever string you hand it. &lt;code&gt;verbose&lt;/code&gt; is the only one that knows what your secrets are and refuses to write them. The moment you call &lt;code&gt;verbose.AddSecret(verbose.SecretBytes(token), "[ISSUED_KEY]")&lt;/code&gt;, that token's SHA-512 digest enters a registry and every subsequent log line is scanned against it before it touches disk. The plaintext never persists inside &lt;code&gt;verbose&lt;/code&gt; — not in memory, not on disk. When you called &lt;code&gt;verbose.RemoveSecret&lt;/code&gt; on revocation, you kept that registry lean deliberately: a server that issues thousands of keys over its lifetime should not accumulate thousands of dead secrets in a scanner it runs on every single log call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;figtree&lt;/code&gt; is not just a flag parser. It is a priority-ordered configuration resolver — file, then environment, then CLI — with validators, rules, and a mutation channel that watches values change at runtime. &lt;code&gt;RuleNoFlags&lt;/code&gt; on &lt;code&gt;kAdminToken&lt;/code&gt; is not decoration. It is an enforcement boundary. The key name &lt;code&gt;"keyserver-admin-token"&lt;/code&gt; being deliberately long is not an accident — it is a design statement: secrets should be inconvenient to pass on a command line because command lines end up in shell history, process lists, and CI logs.&lt;/p&gt;

&lt;p&gt;The on-call rotation is a small thing, but it demonstrates something real: configuration is not static. Values change while a server runs. &lt;code&gt;Pollinate: true&lt;/code&gt; and the mutations channel give you an observable, logged record of every change. In a real system that might be a database password rotating, a feature flag toggling, a rate limit updating. The pattern is identical regardless of what the value is.&lt;/p&gt;




&lt;h3&gt;
  
  
  The packages used in this tutorial are part of a larger body of open source work
&lt;/h3&gt;

&lt;p&gt;Both &lt;code&gt;verbose&lt;/code&gt; and &lt;code&gt;figtree&lt;/code&gt; were written by &lt;strong&gt;Andrei Merlescu&lt;/strong&gt; — &lt;a href="https://github.com/andreimerlescu" rel="noopener noreferrer"&gt;@andreimerlescu&lt;/a&gt; on GitHub. His profile carries 99 public repositories built across 17 years of professional software engineering spanning Cisco, Oracle, Warner Bros. Games, and SurgePays, written primarily in Go, Ruby, PHP, and Bash.&lt;/p&gt;

&lt;p&gt;Some repositories worth exploring alongside the two you just used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/checkfs" rel="noopener noreferrer"&gt;&lt;code&gt;checkfs&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — filesystem existence and permission checks for &lt;code&gt;File&lt;/code&gt; and &lt;code&gt;Directory&lt;/code&gt;. Pairs naturally with figtree when you want to validate that a config-supplied path actually exists before your server starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/sema" rel="noopener noreferrer"&gt;&lt;code&gt;sema&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — semaphore primitives for Go. Useful when the keyserver you just built needs to limit concurrent issuance requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/go-passwd" rel="noopener noreferrer"&gt;&lt;code&gt;go-passwd&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — safe password auditing. If your keyserver ever needs to validate that an incoming credential meets a strength policy before issuing a key, this is the package.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/summarize" rel="noopener noreferrer"&gt;&lt;code&gt;summarize&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; + &lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/aigcm" rel="noopener noreferrer"&gt;&lt;code&gt;aigcm&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — AI-assisted project summarization and git commit message generation using local Ollama models. If you are building on an M-series Mac with local models, these are worth looking at.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/andreimerlescu/lemmings" rel="noopener noreferrer"&gt;&lt;code&gt;lemmings&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — load testing built around the concept of NPCs moving through your infrastructure as simulated users across geographic terrains and pack sizes. If you want to know what your keyserver does under real traffic before you ship it, lemmings is how you find out. It was built specifically because existing tools like &lt;code&gt;ab&lt;/code&gt; did not answer the question Andrei needed answered when he launched Trakify in 2015 and got a surge of traffic from a Barron's Magazine feature. The tool he wished he had then exists now and it is free.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The code is yours. The packages are free. The log file is clean.&lt;/p&gt;

</description>
      <category>logging</category>
      <category>go</category>
      <category>secrets</category>
      <category>security</category>
    </item>
  </channel>
</rss>
