<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>语言 on 山行小记</title>
    <link>https://ruijingan.pages.dev/tags/%E8%AF%AD%E8%A8%80/</link>
    <description>Recent content in 语言 on 山行小记</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <copyright>@2025</copyright>
    <lastBuildDate>Thu, 09 May 2024 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://ruijingan.pages.dev/tags/%E8%AF%AD%E8%A8%80/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Go 泛型用了一年，说说真实感受</title>
      <link>https://ruijingan.pages.dev/posts/2024/go-generics-one-year/</link>
      <pubDate>Thu, 09 May 2024 00:00:00 +0000</pubDate>
      <guid>https://ruijingan.pages.dev/posts/2024/go-generics-one-year/</guid>
      <description>&lt;p&gt;Go 1.18 出泛型的时候，团队讨论过要不要用，当时的结论是观望。去年初我们把最低版本升到 1.21 之后，终于把泛型放进了代码规范，允许使用。一年下来，谈谈真实感受。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;泛型真正帮到我们的地方，比想象中窄。&lt;/strong&gt; 一年下来高频使用的场景其实就三类：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;容器类工具函数。&lt;code&gt;Map&lt;/code&gt;、&lt;code&gt;Filter&lt;/code&gt;、&lt;code&gt;Contains&lt;/code&gt; 这些，以前用 &lt;code&gt;interface{}&lt;/code&gt; + 反射写，又慢又不安全，现在干净多了。&lt;/li&gt;
&lt;li&gt;类型安全的并发原语。我们自己封了个 &lt;code&gt;sync.Map&lt;/code&gt; 的泛型包装，key 和 value 的类型在编译期就确定，用起来踏实。&lt;/li&gt;
&lt;li&gt;数据访问层的通用分页查询，一个 &lt;code&gt;func Query[T any](...)&lt;/code&gt; 替掉了以前代码生成器吐出来的几十行重复代码。&lt;/li&gt;
&lt;/ol&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;code&gt;Service[T]&lt;/code&gt;、&lt;code&gt;Repo[T]&lt;/code&gt; 这种&amp;quot;框架感&amp;quot;的东西一旦放出来，业务代码的可读性会断崖式下跌。领域模型就该是具体的，&lt;code&gt;UserRepo&lt;/code&gt; 比 &lt;code&gt;Repo[User]&lt;/code&gt; 好读得多。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;能用接口解决的不要用泛型。&lt;/strong&gt; 泛型和接口最大的区别是：接口是运行时多态，泛型是编译期展开。大部分业务场景需要的是前者。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个观察：团队里泛型使用量最大的，是以前用 &lt;code&gt;interface{}&lt;/code&gt; 最多的那批代码。这说明泛型在 Go 里解决的主要不是&amp;quot;表达力&amp;quot;问题，而是&amp;quot;以前只能靠反射硬扛&amp;quot;的那部分代码的类型安全问题。从这个角度看，泛型是改良，不是革命。&lt;/p&gt;
&lt;p&gt;最后记录一个实用主义的心得：升级到 1.21 之后 &lt;code&gt;min&lt;/code&gt;/&lt;code&gt;max&lt;/code&gt; 内置函数直接删掉了我们自己写的工具函数，这种小快乐积累起来，也是升级的意义。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
