<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>alchemmist — Go</title><link>https://alchemmist.xyz/tags/go/</link><description>Последние записи в блоге alchemmist</description><generator>Hugo 0.163.3</generator><language>en</language><atom:link href="https://alchemmist.xyz/tags/go/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Tue, 29 Jul 2025 12:09:00 +0300</lastBuildDate><item><title>Predicate Pattern in Go</title><link>https://alchemmist.xyz/articles/predicate-pattern-go/</link><pubDate>Tue, 29 Jul 2025 12:09:00 +0300</pubDate><dc:creator>alchemmist</dc:creator><guid>https://alchemmist.xyz/articles/predicate-pattern-go/</guid><description>If you think this code is idiomatic, elegant and beautiful, read this article!
FindProcess(ByTitle(title)) FindProcess(ByPID(pid)) This code is an example of the result of the predicate pattern. This example is synthetic, but here we’re trying to achieve a similar result here. Firstly, let’s figure out the predicate. Predicate is a function, that returns a boolean value — very simple!
Now, for example, we will write a method findProcess for ProcManager on Go with predicate pattern. The ProcManager has a field processes []*Process, which is slice of processes. And the Process has many unique fields, that we can use to searching. Our method will take a predicate and apply it to all items in the list until the predicate returns true, or the list ends and the search returns hmm... nothing was found.</description><content:encoded><![CDATA[<p>If you think this code is idiomatic, elegant and beautiful, read this article!</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nf">FindProcess</span><span class="p">(</span><span class="nf">ByTitle</span><span class="p">(</span><span class="nx">title</span><span class="p">))</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nf">FindProcess</span><span class="p">(</span><span class="nf">ByPID</span><span class="p">(</span><span class="nx">pid</span><span class="p">))</span><span class="w">
</span></span></span></code></pre></div><p>This code is an example of the result of the predicate pattern. This example is synthetic, but here we’re trying to achieve a similar result here. Firstly, let’s figure out the predicate. <strong>Predicate</strong> is a function, that returns a boolean value — very simple!</p>
<p>Now, for example, we will write a method <code>findProcess</code> for <code>ProcManager</code> on Go with predicate pattern. The <code>ProcManager</code> has a field <code>processes []*Process</code>, which is slice of processes. And the <code>Process</code> has many unique fields, that we can use to searching. Our method will take a <strong>predicate</strong> and apply it to all items in the list until the predicate returns <code>true</code>, or the list ends and the search returns <code>hmm... nothing was found</code>.</p>
<p>For example, in Python we have a standard function <code>filter</code>, which takes an array of items and a predicate function, like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">filter</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">],</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
</span></span></code></pre></div><p>But here we need to handle predicates manually, because this is a more general function. For our case we add intermediate step: a predicate builder. Finally we will get this scheme:
<img src="/images/predicate-pattern-schema.svg" class="content-img" style="width:900px" alt="" loading="lazy" decoding="async" />
Let’s write a method <code>findProcess</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">pm</span><span class="w"> </span><span class="o">*</span><span class="nx">ProcManager</span><span class="p">)</span><span class="w"> </span><span class="nf">findProcess</span><span class="p">(</span><span class="nx">searchPredicate</span><span class="w"> </span><span class="nx">ProcessSearchPredicate</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="nx">Process</span><span class="p">,</span><span class="w"> </span><span class="kt">error</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="nx">pm</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nf">RLock</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">defer</span><span class="w"> </span><span class="nx">pm</span><span class="p">.</span><span class="nx">mu</span><span class="p">.</span><span class="nf">RUnlock</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">proc</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">pm</span><span class="p">.</span><span class="nx">processes</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">if</span><span class="w"> </span><span class="nf">searchPredicate</span><span class="p">(</span><span class="nx">proc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">			</span><span class="k">return</span><span class="w"> </span><span class="nx">proc</span><span class="p">,</span><span class="w"> </span><span class="kc">nil</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="p">,</span><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;no process with this parameter&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>This method takes one argument: <code>searchPredicate</code> with specific type <code>ProcessSearchPreciate</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">ProcessSearchPredicate</span><span class="w"> </span><span class="kd">func</span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o">*</span><span class="nx">Process</span><span class="p">)</span><span class="w"> </span><span class="kt">bool</span><span class="w">
</span></span></span></code></pre></div><p>Let’s see: it’s function from <code>Process</code> to <code>bool</code> — a predicate. Then we can write a predicate builder functions, like filter options:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">ByTitle</span><span class="p">(</span><span class="nx">title</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="nx">ProcessSearchPredicate</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="kd">func</span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o">*</span><span class="nx">Process</span><span class="p">)</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="nx">p</span><span class="p">.</span><span class="nx">Title</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">title</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">ByPID</span><span class="p">(</span><span class="nx">pid</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="nx">ProcessSearchPredicate</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="kd">func</span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o">*</span><span class="nx">Process</span><span class="p">)</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="nx">p</span><span class="p">.</span><span class="nx">PID</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">pid</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>It will work like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">proc</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">pm</span><span class="p">.</span><span class="nf">findProcess</span><span class="p">(</span><span class="nf">ByTitle</span><span class="p">(</span><span class="nx">title</span><span class="p">))</span><span class="w">
</span></span></span></code></pre></div><p>This is already good, but I want to use autocomplete in my code editor for filter options. To make it we can rewrite filter options from <em>functions</em> to <em>methods</em> and use one empty object to call it, like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">type</span><span class="w"> </span><span class="nx">ProcessSearchFilter</span><span class="w"> </span><span class="kd">struct</span><span class="p">{}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">var</span><span class="w"> </span><span class="nx">filter</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">ProcessSearchFilter</span><span class="p">{}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">f</span><span class="w"> </span><span class="nx">ProcessSearchFilter</span><span class="p">)</span><span class="w"> </span><span class="nf">ByTitle</span><span class="p">(</span><span class="nx">title</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="nx">ProcessSearchPredicate</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="kd">func</span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o">*</span><span class="nx">Process</span><span class="p">)</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="nx">p</span><span class="p">.</span><span class="nx">Title</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">title</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="p">(</span><span class="nx">f</span><span class="w"> </span><span class="nx">ProcessSearchFilter</span><span class="p">)</span><span class="w"> </span><span class="nf">ByPID</span><span class="p">(</span><span class="nx">pid</span><span class="w"> </span><span class="kt">int</span><span class="p">)</span><span class="w"> </span><span class="nx">ProcessSearchPredicate</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="k">return</span><span class="w"> </span><span class="kd">func</span><span class="p">(</span><span class="nx">p</span><span class="w"> </span><span class="o">*</span><span class="nx">Process</span><span class="p">)</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">		</span><span class="k">return</span><span class="w"> </span><span class="nx">p</span><span class="p">.</span><span class="nx">PID</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">pid</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p>After that we can use like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">proc</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">pm</span><span class="p">.</span><span class="nf">findProcess</span><span class="p">(</span><span class="nx">filter</span><span class="p">.</span><span class="nf">ByTitle</span><span class="p">(</span><span class="nx">title</span><span class="p">))</span><span class="w">
</span></span></span></code></pre></div><p>And my workflow in my code editor is very comfortable:
<img src="/images/predicate-pattern-demo.gif" class="content-img" alt="" loading="lazy" decoding="async" /></p>
<blockquote class="markdown-blockquote">
  <p>If you like my code editor view you can use my Neovim theme: <a href="https://github.com/alchemmist/nothing.nvim">nothing</a>. And you can use my nvim config, find it in my <a href="https://github.com/alchemmist/dotfiles">dotfiles</a></p>

</blockquote>
]]></content:encoded><category>Go</category></item></channel></rss>