diff options
| author | a73x <[email protected]> | 2024-12-08 20:27:32 +0000 |
|---|---|---|
| committer | a73x <[email protected]> | 2024-12-09 06:04:19 +0000 |
| commit | 9c98a8e3c2794e3a2b6d085e9cb7787108d8745e (patch) | |
| tree | c33d6af9ef40e00bfa7d30c32f9fd6e3766b027f /public/posts | |
| parent | 8358c0765be412b1616aa978667f5d582e9e4901 (diff) | |
new posts
Diffstat (limited to 'public/posts')
| -rw-r--r-- | public/posts/2024-12-08-01.html | 101 | ||||
| -rw-r--r-- | public/posts/2024-12-08-02.html | 70 |
2 files changed, 171 insertions, 0 deletions
diff --git a/public/posts/2024-12-08-01.html b/public/posts/2024-12-08-01.html new file mode 100644 index 0000000..919339c --- /dev/null +++ b/public/posts/2024-12-08-01.html @@ -0,0 +1,101 @@ + +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta name="description" content="Home for a73x" /> + <meta name="author" content="a73x" /> + <meta name="viewport" + content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" /> + <title>a73x</title> + <link rel="stylesheet" href="/static/styles.css"> + <link rel="stylesheet" href="/static/syntax.css"> +</head> + +<body> + <main> + <h1>a73x</h1> + <sub>high effort, low reward</sub> + <nav class="nav"> + <ul> + + + <li><a class="no-decorations" href="/">home</a></li> + + + + <li><a class="no-decorations" href="/posts">posts</a></li> + + + + <li><a class="no-decorations" href="/ethos">ethos</a></li> + + + </ul> + </nav> + +<h1>Simplifying Interfaces with Function Types</h1> +<p>In Go, you can define methods on type aliases, which means that we can define a type alias of a function, and then define methods on that function.</p> + +<h2 id="example">Example</h2> + +<p>Given the following interface</p> +<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">DB</span> <span class="kd">interface</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nf">Get</span><span class="p">(</span><span class="kt">string</span><span class="p">)</span> <span class="p">(</span><span class="kt">string</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre> +<p>You can fulfill it using a function type like this:</p> +<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">GetFn</span> <span class="kd">func</span><span class="p">(</span><span class="kt">string</span><span class="p">)</span> <span class="p">(</span><span class="kt">string</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">f</span> <span class="nx">GetFn</span><span class="p">)</span> <span class="nf">Get</span><span class="p">(</span><span class="nx">a</span> <span class="kt">string</span><span class="p">)</span> <span class="p">(</span><span class="kt">string</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nf">f</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"><span class="p">}</span> +</span></span></code></pre> +<p>Now you can use GetFn whenever a DB is required:</p> +<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="kd">var</span> <span class="nx">storeFn</span> <span class="nx">DB</span> <span class="p">=</span> <span class="nf">GetFn</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">s</span> <span class="kt">string</span><span class="p">)</span> <span class="p">(</span><span class="kt">string</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="s">"bar"</span><span class="p">,</span> <span class="kc">nil</span> +</span></span><span class="line"><span class="cl"> <span class="p">})</span> +</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">storeFn</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="s">"Foo"</span><span class="p">))</span> <span class="c1">// Outputs: bar +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre> +<p>You can try this example in this [Go Playground](<a href="https://go.dev/play/p/hyBNIMblafs">https://go.dev/play/p/hyBNIMblafs</a></p> + +<h2 id="how-it-works">How it works</h2> + +<p>In Go, interfaces are implicitly through method sets, which means any type (including a function type) that defines the required methods satisfies the interface. By defining the <code>Get</code> method on the <code>GetFn</code> type, the compiler treats <code>GetFn</code> as a valid implementation of the DB interface.</p> + +<p>This flexibility allows you to use function types as lightweight, dynamic implementations of interfaces, without the need for full struct definitions.</p> + +<h2 id="application">Application</h2> + +<p>One common use case for this pattern is testing. Instead of implementing a full mock, you can use an inline function to provide test specific behavior.</p> +<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">TestHandler</span><span class="p">()</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="nx">mockDB</span> <span class="o">:=</span> <span class="nf">GetFn</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">key</span> <span class="kt">string</span><span class="p">)</span> <span class="p">(</span><span class="kt">string</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">key</span> <span class="o">==</span> <span class="s">"foo"</span> <span class="p">{</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="s">"bar"</span><span class="p">,</span> <span class="kc">nil</span> +</span></span><span class="line"><span class="cl"> <span class="p">}</span> +</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="s">""</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"not found"</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="p">})</span> +</span></span><span class="line"><span class="cl"> +</span></span><span class="line"><span class="cl"> <span class="nx">result</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">mockDB</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="s">"foo"</span><span class="p">)</span> +</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">result</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="c1">// Outputs: bar, <nil> +</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="p">}</span> +</span></span></code></pre> +<p>This approach is not limited to testing. It’s also useful for dependency injection, where you can pass in lightweight or context specific implementations of an interface.</p> + +<p>This pattern is similar to how <code>http.HandleFunc</code> works. In the HTTP package, <code>http.HandlerFunc</code> is a function type that fulfills the <code>http.Handler</code> interface by implementing its <code>ServeHTTP</code> method. This allows functions to act as handlers, providing great flexibility in designing web servers.</p> + + + <footer> + <br /> + <hr /> + <br /> + <p>see something you disagree with? email: <a href="mailto:[email protected]">[email protected]</a></p> + </footer> + </main> +</body> + +</html> + diff --git a/public/posts/2024-12-08-02.html b/public/posts/2024-12-08-02.html new file mode 100644 index 0000000..f4e67c4 --- /dev/null +++ b/public/posts/2024-12-08-02.html @@ -0,0 +1,70 @@ + +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta name="description" content="Home for a73x" /> + <meta name="author" content="a73x" /> + <meta name="viewport" + content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" /> + <title>a73x</title> + <link rel="stylesheet" href="/static/styles.css"> + <link rel="stylesheet" href="/static/syntax.css"> +</head> + +<body> + <main> + <h1>a73x</h1> + <sub>high effort, low reward</sub> + <nav class="nav"> + <ul> + + + <li><a class="no-decorations" href="/">home</a></li> + + + + <li><a class="no-decorations" href="/posts">posts</a></li> + + + + <li><a class="no-decorations" href="/ethos">ethos</a></li> + + + </ul> + </nav> + +<h1>You and Your Career</h1> +<blockquote> +<p>The unexamined life is not worth living</p> +<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl">- Socrates (probably) +</span></span></code></pre></blockquote> + +<p>If you’ve not listened to <a href="https://www.youtube.com/watch?v=a1zDuOPkMSw">You and Your Research</a> by Richard Hamming, I highly recommend it—you can also read the transcript <a href="https://www.cs.virginia.edu/~robins/YouAndYourResearch.html">here</a>. Hamming’s talk emphasises the importance of examining your career and the choices you make. Whilst the talk specifically speaks about research, it’s fairly easy to draw parallels to software engineering—you only have one life, so why not do significant work?</p> + +<p>Hamming doesn’t define significant work, nor will I—it’s deeply personal and varies for each individual. Instead, he outlines traits he’s seen in others that have accomplished significant work.</p> + +<ol> +<li>Doing significant work often involves an element of luck, but as Hamming puts it, ‘luck favours the prepared mind’. Being in the right place at the right time will only matter if you have the knowledge or skills to execute. Creating opportunities is important but wasted if you aren’t ready to perform. Conversely, having the ability to perform but no opportunities can feel just as futile. The key lies in striking a balance—cultivating both readiness and the conditions where luck can find you.</li> +<li>Knowledge and productivity are like compound interest—consistent effort applied over time leads to exponential growth. In a field as vast as software, even a surface-level awareness of an idea can prove valuable when the time comes to use it, while deeper understanding builds expertise. Mastering the fundamentals is crucial; they are learned once and applied repeatedly in various contexts.</li> +<li>Maintain enough self-belief to persist, but enough self-awareness to recognise and adapt to mistakes. Software is more akin to an art than a science—there are no perfect solutions, only trade-offs. Success often lies in minimising the disadvantages rather than chasing absolutes.</li> +<li>To do important work, focus on important problems. What do you care about deeply? How can you work to address it? The answer is personal, but taking time to reflect is crucial.</li> +</ol> + +<p>These aren’t all the points Hamming raises, but some points that stuck with me; I highly recommend listening to the talk yourself so that you may draw your own conclusions.</p> + +<p>The average career is only 80,000 hours, so spend it well.</p> + + + <footer> + <br /> + <hr /> + <br /> + <p>see something you disagree with? email: <a href="mailto:[email protected]">[email protected]</a></p> + </footer> + </main> +</body> + +</html> + |
