<?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>Forem: Leon</title>
    <description>The latest articles on Forem by Leon (@leon-heung).</description>
    <link>https://forem.com/leon-heung</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%2F2546436%2Faf2b9e3d-37ca-41f7-8772-0d5e99b07ee0.jpeg</url>
      <title>Forem: Leon</title>
      <link>https://forem.com/leon-heung</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/leon-heung"/>
    <language>en</language>
    <item>
      <title>Go: Ticker</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Fri, 15 Aug 2025 03:54:46 +0000</pubDate>
      <link>https://forem.com/leon-heung/go-ticker-1nhf</link>
      <guid>https://forem.com/leon-heung/go-ticker-1nhf</guid>
      <description>&lt;p&gt;&lt;code&gt;time.Ticker&lt;/code&gt; 是 Go 语言标准库 &lt;code&gt;time&lt;/code&gt; 包中一个强大的工具，用于实现周期性的任务。它以固定的时间间隔向一个通道发送事件，非常适合用于轮询、定时刷新缓存、心跳检测等多种场景。然而，不当的使用也可能导致 goroutine 泄漏和程序性能问题。本文将全面总结 &lt;code&gt;time.Ticker&lt;/code&gt; 的使用技巧，从基础用法到高级模式，帮助您高效、安全地在项目中使用它。&lt;/p&gt;




&lt;h2&gt;
  
  
  1. 基础用法：创建和接收事件
&lt;/h2&gt;

&lt;p&gt;创建一个 &lt;code&gt;Ticker&lt;/code&gt; 非常简单，只需调用 &lt;code&gt;time.NewTicker()&lt;/code&gt; 并传入一个 &lt;code&gt;time.Duration&lt;/code&gt; 类型的参数作为时间间隔。&lt;/p&gt;

&lt;h3&gt;
  
  
  Go
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&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;"time"&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;// 创建一个每秒触发一次的 ticker&lt;/span&gt;
    &lt;span class="n"&gt;ticker&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;NewTicker&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="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// 确保在不需要时停止 ticker&lt;/span&gt;

    &lt;span class="n"&gt;done&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;bool&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="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;done&lt;/span&gt;&lt;span class="o"&gt;:&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;t&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;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C&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;"Tick at"&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="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;// 运行一段时间后停止&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;Sleep&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="n"&gt;done&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;true&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;"Ticker stopped"&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;核心要点:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;time.NewTicker(duration)&lt;/code&gt; 返回一个 &lt;code&gt;time.Ticker&lt;/code&gt; 对象。&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ticker.C&lt;/code&gt; 是一个通道 (&lt;code&gt;&amp;lt;-chan time.Time&lt;/code&gt;)，会按设定的时间间隔接收到当前时间。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;必须调用 &lt;code&gt;ticker.Stop()&lt;/code&gt;&lt;/strong&gt; 来释放相关资源。通常使用 &lt;code&gt;defer&lt;/code&gt; 语句来确保在函数退出时执行。&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. 安全停止 Ticker：避免 Goroutine 泄漏
&lt;/h2&gt;

&lt;p&gt;忘记调用 &lt;code&gt;ticker.Stop()&lt;/code&gt; 是一个常见的错误，这会导致底层的 goroutine 无法被垃圾回收，从而造成 goroutine 泄漏。特别是在一个长期运行的程序中，这会逐渐消耗系统资源。&lt;/p&gt;

&lt;h3&gt;
  
  
  优雅关闭模式 (Graceful Shutdown)
&lt;/h3&gt;

&lt;p&gt;在实际应用中，我们常常需要在程序退出时，或者某个模块不再需要时，优雅地停止正在运行的 ticker。这通常通过一个额外的 &lt;code&gt;done&lt;/code&gt; 或 &lt;code&gt;quit&lt;/code&gt; 通道来实现。&lt;/p&gt;

&lt;h3&gt;
  
  
  Go
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&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;"time"&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;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ticker&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;NewTicker&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="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&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;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C&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;"Doing periodic work..."&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;stop&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;"Worker stopping..."&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="p"&gt;}&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;stop&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;bool&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;worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stop&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;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&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="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="c"&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;Sleep&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="c"&gt;// 等待 worker 退出&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;"Main finished"&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;code&gt;select&lt;/code&gt; 结构允许 goroutine 同时监听 ticker 事件和停止信号，实现了对 goroutine 生命周期的精确控制。&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Ticker 与 &lt;code&gt;time.Sleep&lt;/code&gt; 的对决
&lt;/h2&gt;

&lt;p&gt;初学者可能会使用 &lt;code&gt;for&lt;/code&gt; 循环配合 &lt;code&gt;time.Sleep()&lt;/code&gt; 来实现周期性任务。然而，&lt;code&gt;time.Ticker&lt;/code&gt; 在精确性和效率上通常更胜一筹。&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;&lt;code&gt;time.Ticker&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;for&lt;/code&gt; + &lt;code&gt;time.Sleep(d)&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;精确性&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;高&lt;/strong&gt;。Ticker 会自动调整下一次触发的时间，以弥补任务执行所花费的时间，尽可能保证平均间隔为 &lt;code&gt;d&lt;/code&gt;。&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;低&lt;/strong&gt;。实际的执行间隔是 &lt;code&gt;任务执行时间 + d&lt;/code&gt;，会导致周期逐渐漂移。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;资源使用&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;较为高效，底层由 Go runtime 的定时器统一管理。&lt;/td&gt;
&lt;td&gt;简单直接，但不够精确。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;控制&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;可以通过 &lt;code&gt;Stop()&lt;/code&gt; 和 &lt;code&gt;Reset()&lt;/code&gt; 进行灵活控制。&lt;/td&gt;
&lt;td&gt;只能在循环中通过 &lt;code&gt;break&lt;/code&gt; 或 &lt;code&gt;return&lt;/code&gt; 退出。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;结论：&lt;/strong&gt; 对于需要精确周期的任务，&lt;strong&gt;强烈推荐使用 &lt;code&gt;time.Ticker&lt;/code&gt;&lt;/strong&gt;。&lt;code&gt;time.Sleep&lt;/code&gt; 更适用于简单的、对周期精度要求不高的延时场景。&lt;/p&gt;




&lt;h2&gt;
  
  
  4. 应对慢消费者 (Slow Receiver)
&lt;/h2&gt;

&lt;p&gt;如果接收 &lt;code&gt;ticker.C&lt;/code&gt; 的任务执行时间超过了 ticker 的间隔时间，会发生什么？&lt;/p&gt;

&lt;p&gt;&lt;code&gt;time.Ticker&lt;/code&gt; 的内部通道只有一个缓冲区。如果上一个 tick 还没有被消费，而新的 tick 又到了，Ticker 会&lt;strong&gt;丢弃&lt;/strong&gt;这个新的 tick，等待消费者处理完当前 tick 后再发送下一个。这可以防止 tick 在通道中无限堆积，但也意味着&lt;strong&gt;任务的执行频率会降低&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;示例：&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Go
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;ticker&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;NewTicker&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="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stop&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;ticker&lt;/span&gt;&lt;span class="o"&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;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;"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;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&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="c"&gt;// 任务耗时超过了 ticker 间隔&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// 输出会是每 2 秒一个 "Tick!"，而不是每秒一个&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;应对策略：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;优化任务性能&lt;/strong&gt;：从根本上减少每次任务的执行时间。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;解耦&lt;/strong&gt;：如果任务确实耗时，可以考虑将任务放入一个工作池 (worker pool) 中异步执行，让 ticker 的接收者只负责分发任务，避免阻塞。&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. 动态调整 Ticker 间隔
&lt;/h2&gt;

&lt;p&gt;在某些场景下，我们可能需要根据程序的运行状态动态调整定时任务的频率。这时可以使用 &lt;code&gt;ticker.Reset()&lt;/code&gt; 方法。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ticker.Reset(newDuration)&lt;/code&gt; 会停止当前的 ticker，并将其周期重置为新的时长。下一个 tick 会在 &lt;code&gt;newDuration&lt;/code&gt; 之后到达。&lt;/p&gt;

&lt;h3&gt;
  
  
  Go
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&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;"time"&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;ticker&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;NewTicker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&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;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stop&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;t&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;ticker&lt;/span&gt;&lt;span class="o"&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;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;"Tick at"&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="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;"Ticker started with 3s interval."&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;Sleep&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="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="c"&gt;// 将间隔重置为 1 秒&lt;/span&gt;
    &lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reset&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="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;"Ticker interval reset to 1s."&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;Sleep&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="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Go 1.23 的重要变化：自动垃圾回收
&lt;/h2&gt;

&lt;p&gt;在 &lt;strong&gt;Go 1.23 之前&lt;/strong&gt;，如果忘记调用 &lt;code&gt;ticker.Stop()&lt;/code&gt;，&lt;code&gt;Ticker&lt;/code&gt; 对象将永远不会被垃圾回收，导致资源泄漏。&lt;/p&gt;

&lt;p&gt;从 &lt;strong&gt;Go 1.23 开始&lt;/strong&gt;，Go 的垃圾回收器变得更加智能，&lt;strong&gt;能够回收未被引用的、且未被停止的 &lt;code&gt;Ticker&lt;/code&gt;&lt;/strong&gt;。这意味着即使忘记调用 &lt;code&gt;Stop()&lt;/code&gt;，也不再会导致永久的资源泄漏。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;尽管如此，最佳实践仍然是：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;显式调用 &lt;code&gt;Stop()&lt;/code&gt;&lt;/strong&gt;：这使得代码意图更加清晰，表明你已经完成了对这个 &lt;code&gt;Ticker&lt;/code&gt; 的使用。&lt;/li&gt;
&lt;li&gt;在不再需要 &lt;code&gt;Ticker&lt;/code&gt; 时立即停止它，可以更早地释放资源，而不是等待 GC。&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. 常见使用场景
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;心跳检测&lt;/strong&gt;：客户端或服务器定时发送心跳包以维持连接。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;数据轮询&lt;/strong&gt;：定时从数据库、API 或其他数据源拉取更新。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;缓存刷新&lt;/strong&gt;：定期清理或更新内存中的缓存数据。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;监控和度量&lt;/strong&gt;：周期性地收集系统性能指标。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;超时控制&lt;/strong&gt;：结合 &lt;code&gt;select&lt;/code&gt; 语句，为某个操作设置一个周期性的检查点。&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  总结
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;time.Ticker&lt;/code&gt; 是 Go 并发编程中不可或缺的工具。掌握其正确的使用方法，特别是&lt;strong&gt;优雅地停止它&lt;/strong&gt;，是编写健壮、可维护的 Go 程序的关键。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;核心技巧回顾：&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;创建与停止&lt;/strong&gt;：使用 &lt;code&gt;time.NewTicker()&lt;/code&gt; 创建，并用 &lt;code&gt;defer ticker.Stop()&lt;/code&gt; 确保释放。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;优雅关闭&lt;/strong&gt;：结合 &lt;code&gt;select&lt;/code&gt; 和一个额外的 &lt;code&gt;done&lt;/code&gt; 通道来安全地终止 goroutine。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;精确周期&lt;/strong&gt;：优先选择 &lt;code&gt;Ticker&lt;/code&gt; 而不是 &lt;code&gt;time.Sleep&lt;/code&gt; 来保证周期的准确性。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;注意慢消费&lt;/strong&gt;：理解慢消费会导致 tick 被丢弃，并据此设计你的任务逻辑。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;动态调整&lt;/strong&gt;：使用 &lt;code&gt;ticker.Reset()&lt;/code&gt; 灵活改变任务频率。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;了解版本差异&lt;/strong&gt;：知晓 Go 1.23 在 GC 方面的改进，但仍坚持显式调用 &lt;code&gt;Stop()&lt;/code&gt; 的好习惯。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;通过遵循这些技巧，你可以充满信心地在你的 Go 项目中发挥 &lt;code&gt;time.Ticker&lt;/code&gt; 的最大效用。&lt;/p&gt;




</description>
      <category>go</category>
    </item>
    <item>
      <title>Rust: Ownership, Borrowing (References), Lifetimes, Move/Copy/Clone semantics</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Tue, 13 May 2025 09:43:51 +0000</pubDate>
      <link>https://forem.com/leon-heung/rust-ownership-borrowingreferences-lifetimesmovecopyclone-semantics-dfb</link>
      <guid>https://forem.com/leon-heung/rust-ownership-borrowingreferences-lifetimesmovecopyclone-semantics-dfb</guid>
      <description>&lt;h2&gt;
  
  
  🧠 Why Care About These Concepts?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reliability&lt;/strong&gt;&lt;br&gt;
These concepts allow the Rust compiler to prevent common resource errors such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory leaks&lt;/li&gt;
&lt;li&gt;Dangling pointers&lt;/li&gt;
&lt;li&gt;Double frees&lt;/li&gt;
&lt;li&gt;Accessing uninitialized memory&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Convenience&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The Rust compiler can automatically free resources using these concepts — no need for manual &lt;code&gt;free&lt;/code&gt; or a garbage collector.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;br&gt;
Resource management without a garbage collector enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster performance&lt;/li&gt;
&lt;li&gt;Suitability for real-time systems&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ How to Use These Features?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;These features are &lt;strong&gt;enforced by the compiler&lt;/strong&gt; through compile-time checks.&lt;/li&gt;
&lt;li&gt;You don't usually &lt;em&gt;do&lt;/em&gt; something manually — instead, you follow Rust's rules.&lt;/li&gt;
&lt;li&gt;Understanding these concepts is essential to &lt;strong&gt;fix compiler error messages&lt;/strong&gt; during development.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧾 Basic Memory Management Terminology
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A &lt;strong&gt;variable&lt;/strong&gt; is a name for a memory location holding a value of some type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Memory&lt;/strong&gt; can be allocated in three regions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stack&lt;/strong&gt;:
Automatically allocated when a function is called, and freed when the function returns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heap&lt;/strong&gt;:
Requires explicit allocation and deallocation (handled by Rust’s ownership model).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static memory&lt;/strong&gt;:
Lives for the entire duration of the program.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  🐞 Common Memory Errors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dangling Pointer&lt;/strong&gt;:&lt;br&gt;
A pointer to memory that has been freed or was never initialized.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory Leak&lt;/strong&gt;:&lt;br&gt;
Memory allocated on the heap is never freed — e.g., forgetting to release memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Uninitialized Memory&lt;/strong&gt;:&lt;br&gt;
Using memory before it has been properly allocated or assigned a value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Double Free&lt;/strong&gt;:&lt;br&gt;
Attempting to free the same memory more than once — either on the same variable or on a copy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ What Can Go Wrong on the Stack?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Since memory is automatically allocated and freed, there are &lt;strong&gt;no memory leaks&lt;/strong&gt;, &lt;strong&gt;uninitialized memory&lt;/strong&gt;, or &lt;strong&gt;double free&lt;/strong&gt; problems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The function &lt;strong&gt;might return a pointer to a value on the stack&lt;/strong&gt;, leading to a &lt;strong&gt;dangling pointer&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rust prevents this by simply checking that &lt;strong&gt;no such references are returned&lt;/strong&gt; — see &lt;code&gt;stack-dangling-pointer.rs&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Example: Returning a reference to a local variable
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_ref&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="nb"&gt;i32&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;number&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="c1"&gt;// ❌ This will cause a compile error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Compiler Error:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error[E0515]: cannot return reference to local variable `number`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t return references to local function variables&lt;/strong&gt; — copy or move the value out of the function.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Correct version: Move the value out
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;create_value&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;i32&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;number&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="n"&gt;number&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Move the value instead of returning a reference&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💾 What Can Go Wrong on the Heap?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A reference might be used &lt;strong&gt;after the memory was reallocated or freed&lt;/strong&gt;, leading to a &lt;strong&gt;dangling pointer&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;borrow checker&lt;/strong&gt; prevents the reallocation by not allowing a mutable and other reference at the same time.&lt;br&gt;
An &lt;strong&gt;immutable reference is needed to push on a vector and possibly reallocate it&lt;/strong&gt; — see &lt;code&gt;heap-reallocation-dangling-pointer.rs&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Example: Reallocation with active immutable borrow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;vec&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="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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;first&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;vec&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;// Immutable borrow&lt;/span&gt;
    &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="nf"&gt;.push&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="c1"&gt;// ❌ May cause reallocation&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;first&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// Use after potential reallocation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Compiler Error:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t do it&lt;/strong&gt;, and if you really need a mutable reference paired with other references, use the &lt;code&gt;std::cell&lt;/code&gt; module.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Correct version: Borrow after mutation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;vec&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="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="n"&gt;vec&lt;/span&gt;&lt;span class="nf"&gt;.push&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="c1"&gt;// ✅ Mutate first&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;first&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;vec&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;// Borrow afterwards&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;first&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;ul&gt;
&lt;li&gt;Rust prevents the &lt;strong&gt;use after free&lt;/strong&gt; case by making sure &lt;strong&gt;no reference is used after its lifetime has ended&lt;/strong&gt;, i.e. the value was dropped — see &lt;code&gt;heap-dropped-dangling-pointer.rs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Example: Reference lives longer than the value
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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;r&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;vec&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="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="n"&gt;r&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;vec&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;// ❌ `vec` goes out of scope here&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;r&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Use after drop&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Compiler Error:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error[E0597]: `vec` does not live long enough
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t do it&lt;/strong&gt;, or if you really run into this problem, you might need &lt;strong&gt;shared ownership&lt;/strong&gt; with the &lt;code&gt;std::rc&lt;/code&gt; module.&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;The borrow checker also does not allow a value to be &lt;strong&gt;moved to another variable&lt;/strong&gt; that could reallocate or free the memory &lt;strong&gt;while there are references&lt;/strong&gt; — see &lt;code&gt;heap-move-dangling-pointer.rs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Example: Move after borrow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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;vec&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="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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;r&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;vec&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;moved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Moving vec while r still exists&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;r&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;h4&gt;
  
  
  Compiler Error:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error[E0505]: cannot move out of `vec` because it is borrowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Don’t move a value to another variable and then use a reference to it you created before.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Correct version: Use after move or avoid borrowing before move
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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;vec&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="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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;moved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Move without borrowing first&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;moved&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;h2&gt;
  
  
  🔑 What Is Ownership?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rust &lt;strong&gt;automatically frees memory&lt;/strong&gt;, so there are no &lt;strong&gt;memory leaks&lt;/strong&gt; or &lt;strong&gt;double free&lt;/strong&gt; calls.&lt;/li&gt;
&lt;li&gt;Rust does this &lt;strong&gt;without a garbage collector&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧹 How Does Rust Manage Memory?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The concept is simple:
Rust &lt;strong&gt;calls a destructor&lt;/strong&gt; (&lt;code&gt;drop&lt;/code&gt;) whenever the &lt;strong&gt;lifetime of a value ends&lt;/strong&gt;, i.e., when the value goes &lt;strong&gt;out of scope&lt;/strong&gt; (&lt;code&gt;{}&lt;/code&gt; block ends).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;_s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&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="c1"&gt;// `_s` is dropped here automatically&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// memory is freed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ❌ The Problem with Shallow Copies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Some values, like a &lt;code&gt;Vec&lt;/code&gt;, contain &lt;strong&gt;heap-allocated data&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;shallow copy&lt;/strong&gt; (only copying pointer and metadata) would cause a &lt;strong&gt;double free&lt;/strong&gt; error if both copies tried to free the same memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ✅ Rust prevents this with &lt;strong&gt;Move Semantics&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When you assign one variable to another, Rust &lt;strong&gt;moves&lt;/strong&gt; the value instead of copying it (unless it implements &lt;code&gt;Copy&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔁 Move Example (&lt;code&gt;move-semantics.rs&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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;vec&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="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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;moved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// vec is moved&lt;/span&gt;
    &lt;span class="c1"&gt;// println!("{:?}", vec); // ❌ error: use of moved value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧠 Compiler Error:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error[E0382]: borrow of moved value: `vec`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t use a value after it was moved&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If you &lt;strong&gt;really need a deep copy&lt;/strong&gt;, use &lt;code&gt;.clone()&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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;vec&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="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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;cloned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vec&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;// deep copy&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;vec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// ✅ ok to use&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;code&gt;.clone()&lt;/code&gt; is often &lt;strong&gt;unnecessary&lt;/strong&gt; and can lead to &lt;strong&gt;performance issues&lt;/strong&gt; if overused.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📦 Copy vs Move
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Primitive types&lt;/strong&gt; (e.g., &lt;code&gt;i32&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;char&lt;/code&gt;) are &lt;strong&gt;copied by default&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No heap data → no double free risk.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&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;a&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="k"&gt;let&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;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// a is copied, not moved&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;"a = {}, b = {}"&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="c1"&gt;// ✅ both are usable&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Types with heap data&lt;/strong&gt; (e.g., &lt;code&gt;Vec&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;) are &lt;strong&gt;moved by default&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can make your own types &lt;strong&gt;Copy-able&lt;/strong&gt; by implementing the &lt;code&gt;Copy&lt;/code&gt; trait:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: &lt;code&gt;Copy&lt;/code&gt; trait (&lt;code&gt;copy-semantics.rs&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Copy,&lt;/span&gt; &lt;span class="nd"&gt;Clone)]&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;i32&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;i32&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;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="mi"&gt;1&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="mi"&gt;2&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;p2&lt;/span&gt; &lt;span class="o"&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;// p1 is copied, not moved&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;"p1: {}, {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="py"&gt;.x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p1&lt;/span&gt;&lt;span class="py"&gt;.y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ✅ still valid&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If a type is not &lt;code&gt;Copy&lt;/code&gt;, Rust will give an error like:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;move occurs because `config` has type `Config`, which does not implement the `Copy` trait
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Don’t implement &lt;code&gt;Copy&lt;/code&gt;&lt;/strong&gt; if you can live with using references.&lt;/p&gt;

&lt;p&gt;✅ You can also just implement &lt;code&gt;Clone&lt;/code&gt; and call &lt;code&gt;.clone()&lt;/code&gt; explicitly — see &lt;code&gt;clone-semantics.rs&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📌 Summary and Miscellaneous Info
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ownership&lt;/strong&gt;, &lt;strong&gt;borrowing&lt;/strong&gt;, and &lt;strong&gt;lifetimes&lt;/strong&gt; enable the Rust compiler to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect and prevent memory errors&lt;/li&gt;
&lt;li&gt;Handle memory &lt;strong&gt;automatically and safely&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Safe Rust guarantees memory safety&lt;/strong&gt; — no undefined behavior from memory misuse.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;You can use &lt;strong&gt;unsafe Rust&lt;/strong&gt; inside an &lt;code&gt;unsafe {}&lt;/code&gt; block if needed.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Rust understands how to free memory even in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loops&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;if&lt;/code&gt;/&lt;code&gt;match&lt;/code&gt; clauses&lt;/li&gt;
&lt;li&gt;Iterators&lt;/li&gt;
&lt;li&gt;Partial moves from structs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;✅ If your program &lt;strong&gt;compiles&lt;/strong&gt;, you get these memory safety guarantees &lt;strong&gt;without a runtime garbage collector&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introducing LoConn: local area network chatting app written in GO</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Fri, 09 May 2025 15:25:42 +0000</pubDate>
      <link>https://forem.com/leon-heung/introducing-loconn-local-area-network-chatting-app-written-in-go-8f6</link>
      <guid>https://forem.com/leon-heung/introducing-loconn-local-area-network-chatting-app-written-in-go-8f6</guid>
      <description>&lt;h1&gt;
  
  
  Golan
&lt;/h1&gt;

&lt;p&gt;Go implementation of local area network communications based on protocols like UDP, HTTPS, WebSocket, etc.&lt;/p&gt;

&lt;p&gt;Try the desktop GUI app for lan-chatting/document transferring:&lt;a href="https://github.com/leoxiang66/golan/releases" rel="noopener noreferrer"&gt;https://github.com/leoxiang66/golan/releases&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  General roadmap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[x] basic GUI app that supports peer2peer lan-chatting&lt;/li&gt;
&lt;li&gt;[x] support multiple conversations at the same time&lt;/li&gt;
&lt;li&gt;[ ] support copying chat messages&lt;/li&gt;
&lt;li&gt;[ ] support random user names&lt;/li&gt;
&lt;li&gt;[ ] GUI notifications for system information such as "socket disconnected"&lt;/li&gt;
&lt;li&gt;[ ] support disconnecting sockets by users&lt;/li&gt;
&lt;li&gt;[ ] support file transferring&lt;/li&gt;
&lt;li&gt;[ ] support blacklist&lt;/li&gt;
&lt;li&gt;[ ] encryption/decryption&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Some screenshots
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Peer2Peer chat&lt;br&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%2F57qxfgzaqdz0bt29d3w6.png" 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%2F57qxfgzaqdz0bt29d3w6.png" alt="image" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Invite for socket connection&lt;br&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%2Fl1l2lvs7t7oq5mtwqbqz.png" 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%2Fl1l2lvs7t7oq5mtwqbqz.png" alt="image" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Received invitation&lt;br&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%2Fxwh01j9xwvo1h2vnaeh8.png" 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%2Fxwh01j9xwvo1h2vnaeh8.png" alt="image" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Go vs C++ 变量生存周期对比</title>
      <dc:creator>Leon</dc:creator>
      <pubDate>Tue, 06 May 2025 08:00:12 +0000</pubDate>
      <link>https://forem.com/leon-heung/go-vs-c-bian-liang-sheng-cun-zhou-qi-dui-bi-1idc</link>
      <guid>https://forem.com/leon-heung/go-vs-c-bian-liang-sheng-cun-zhou-qi-dui-bi-1idc</guid>
      <description>&lt;h2&gt;
  
  
  1. 变量分配位置：栈（Stack） vs 堆（Heap）
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;栈上分配&lt;/td&gt;
&lt;td&gt;默认；逃逸分析判断不外泄的局部变量&lt;/td&gt;
&lt;td&gt;默认；函数作用域内局部变量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;堆上分配&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;amp;T{}&lt;/code&gt; 语法，根据逃逸分析结果决定&lt;/td&gt;
&lt;td&gt;必须显式 &lt;code&gt;new&lt;/code&gt; / &lt;code&gt;malloc&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;栈/堆 切换逻辑&lt;/td&gt;
&lt;td&gt;编译期逃逸分析自动决定&lt;/td&gt;
&lt;td&gt;由程序员通过不同语法手动选择&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Go 的逃逸分析&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;编译时分析：如果一个变量的引用“逃逸”出函数作用域（例如被返回或存入外部结构），则在堆上分配；否则留在栈上。&lt;/li&gt;
&lt;li&gt;无需手动标注或调用函数，&lt;code&gt;&amp;amp;T{}&lt;/code&gt; 语句自动触发逃逸检测。&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;C++ 的显式分配&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;栈分配：&lt;code&gt;T obj;&lt;/code&gt; 在函数结束时自动销毁。&lt;/li&gt;
&lt;li&gt;堆分配：&lt;code&gt;new T&lt;/code&gt; 或 &lt;code&gt;malloc&lt;/code&gt;，需要手动 &lt;code&gt;delete&lt;/code&gt; 或 &lt;code&gt;free&lt;/code&gt;，否则产生内存泄漏。&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. 内存回收：垃圾回收 vs 手动管理
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;内存回收方式&lt;/td&gt;
&lt;td&gt;并发标记-清除（Garbage Collection）&lt;/td&gt;
&lt;td&gt;手动 &lt;code&gt;delete&lt;/code&gt; / &lt;code&gt;free&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;开发者负担&lt;/td&gt;
&lt;td&gt;低：无需关注何时释放&lt;/td&gt;
&lt;td&gt;高：必须谨慎配对分配与释放&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;内存泄漏风险&lt;/td&gt;
&lt;td&gt;极低，只要无引用即可回收&lt;/td&gt;
&lt;td&gt;较高：忘记释放或多次释放都可能出错&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;性能开销&lt;/td&gt;
&lt;td&gt;GC 偶发停顿；现代 Go GC 已大幅优化&lt;/td&gt;
&lt;td&gt;几乎零开销，但需额外编码与审查成本&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Go 的 GC 特点&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;并发执行、不停机：大对象标记与清除在后台进行。&lt;/li&gt;
&lt;li&gt;只要变量不再被任何活动引用，内存即被回收。&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;C++ 的手动管理&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;new&lt;/code&gt;/&lt;code&gt;malloc&lt;/code&gt; 与 &lt;code&gt;delete&lt;/code&gt;/&lt;code&gt;free&lt;/code&gt; 必须成对出现。&lt;/li&gt;
&lt;li&gt;智能指针（&lt;code&gt;std::unique_ptr&lt;/code&gt;、&lt;code&gt;std::shared_ptr&lt;/code&gt;）可减轻部分负担，但仍需理解引用计数与生命周期。&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. 指针安全性与悬空指针
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;返回本地变量地址&lt;/td&gt;
&lt;td&gt;安全：自动逃逸到堆&lt;/td&gt;
&lt;td&gt;危险：返回栈上变量地址导致悬空指针&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;悬空指针风险&lt;/td&gt;
&lt;td&gt;不存在（逃逸分析保证）&lt;/td&gt;
&lt;td&gt;普遍：需小心谨慎&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;空指针检测&lt;/td&gt;
&lt;td&gt;无需手动；引用失效后不可达&lt;/td&gt;
&lt;td&gt;访问悬空或空指针未定义行为&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go 示例（安全）&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;  &lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;createNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ListNode&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;ListNode&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;val&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;无论 &lt;code&gt;createNode&lt;/code&gt; 返回什么，节点都在堆上，由 GC 管理。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C++ 示例（危险）&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;  &lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;createNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&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="n"&gt;ListNode&lt;/span&gt; &lt;span class="n"&gt;node&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="c1"&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;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// 返回栈上地址 -&amp;gt; 悬空指针&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. 示例对比：追加链表节点
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Go 版
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;appendNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&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="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&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;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&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;curr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&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;ListNode&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;val&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="c"&gt;// 调用后，无需担心内存释放，GC 自动管理&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  C++ 版
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;appendNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&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="n"&gt;ListNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ListNode&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="c1"&gt;// 手动分配&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// 需要在适当时机 delete 整个链表，避免内存泄漏&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. 小结
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;分配简便 vs 灵活自由&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Go：&lt;code&gt;&amp;amp;T{}&lt;/code&gt; 一行搞定分配位置，兼顾性能与安全。&lt;/li&gt;
&lt;li&gt;C++：细粒度控制，但需程序员自行选择并管理。&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;自动回收 vs 手动回收&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Go 的并发 GC 降低开发者负担，适合快速迭代。&lt;/li&gt;
&lt;li&gt;C++ 的手动管理零 GC 开销，但易错、调试成本高。&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;指针安全&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Go 强制逃逸分析与 GC，几乎消除悬空指针风险。&lt;/li&gt;
&lt;li&gt;C++ 强大灵活，却要时刻提防野指针与内存泄漏。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;两者各有优劣：Go 在安全性和开发体验上更胜一筹，而 C++ 在性能控制和底层能力上更具优势。根据项目需求和团队背景，选择最合适的语言与记忆模型即可。&lt;/p&gt;

</description>
      <category>go</category>
      <category>cpp</category>
    </item>
  </channel>
</rss>
