<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Byron Cabrera on Medium]]></title>
        <description><![CDATA[Stories by Byron Cabrera on Medium]]></description>
        <link>https://medium.com/@ullauri.byron?source=rss-b540ad628920------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*A99UrjT5Fs6o5TT-</url>
            <title>Stories by Byron Cabrera on Medium</title>
            <link>https://medium.com/@ullauri.byron?source=rss-b540ad628920------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 23 Jun 2026 09:44:47 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@ullauri.byron/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[The Signal Infrastructure of Agentic Coding]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@ullauri.byron/feedforward-and-feedback-the-signal-infrastructure-behind-effective-agentic-coding-0be6ef44cd0a?source=rss-b540ad628920------2"><img src="https://cdn-images-1.medium.com/max/1376/1*2fBJYxEfGaThHFOuwx4bXw.png" width="1376"></a></p><p class="medium-feed-snippet">Most developers using AI coding tools eventually run into the same frustration. The agent makes a decision that contradicts an&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/@ullauri.byron/feedforward-and-feedback-the-signal-infrastructure-behind-effective-agentic-coding-0be6ef44cd0a?source=rss-b540ad628920------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@ullauri.byron/feedforward-and-feedback-the-signal-infrastructure-behind-effective-agentic-coding-0be6ef44cd0a?source=rss-b540ad628920------2</link>
            <guid isPermaLink="false">https://medium.com/p/0be6ef44cd0a</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[developer-tools]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Byron Cabrera]]></dc:creator>
            <pubDate>Tue, 12 May 2026 03:50:51 GMT</pubDate>
            <atom:updated>2026-05-16T23:52:49.661Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Error Handling in Go: Making the Most of As Is]]></title>
            <link>https://medium.com/@ullauri.byron/error-handling-in-go-making-the-most-of-as-is-ecc971a7f7f7?source=rss-b540ad628920------2</link>
            <guid isPermaLink="false">https://medium.com/p/ecc971a7f7f7</guid>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[golang-tutorial]]></category>
            <category><![CDATA[error-handling]]></category>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[go]]></category>
            <dc:creator><![CDATA[Byron Cabrera]]></dc:creator>
            <pubDate>Thu, 26 Dec 2024 00:47:29 GMT</pubDate>
            <atom:updated>2024-12-26T00:47:29.086Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4ygaDC3a77IElKo8D2dxYg.png" /></figure><p>Error handling in Go has evolved since the introduction of Go 1.13, bringing two essential functions to the standard library: errors.Is and errors.As. These tools enable developers to handle errors more robustly, allowing for better error inspection and handling in a structured, type-safe manner. This article explores how you can make the most of these two functions for cleaner and more efficient error handling in Go applications while avoiding anti-patterns that hinder readability.</p><h3>The Problem with Traditional Error Checking</h3><p>A common practice in error handling involves having to check for the types of errors being returned from a function. Knowing how to check for types is dependent on whether they are standard error instances or custom structs that implement the error interface.</p><p>Before Go 1.13, error handling typically relied on comparing errors directly using equality == checks. This approach works well for simple error values but becomes problematic with wrapped errors as many functions return errors that wrap the original ones.</p><p>Here’s an example of the above :</p><pre>if err == io.EOF {<br>    // handle EOF error<br>}</pre><p>This works fine if err is exactly io.EOF, but if err wraps io.EOF (for example, when using fmt.Errorf with %w), the direct comparison fails:</p><pre>err := fmt.Errorf(&quot;read failed: %w&quot;, io.EOF)<br>if err == io.EOF {<br>    // This won&#39;t work because err wraps io.EOF<br>}</pre><p>Likewise, another common practice in error handling is being able to extend data captured within an error by creating a custom error type which implements the error interface</p><p>For example:</p><pre>type AppError struct {<br>    message string<br>    statusCode int<br>}<br><br>func NewAppError(message string, statusCode int) *AppError {<br>    return &amp;AppError{essage, statusCode}<br>}<br><br>func (e AppError) Error() string {<br>    return e.message<br>}<br><br>func (e AppError) StatusCode() int {<br>    return e.statusCode<br>}</pre><p>Prior to Go 1.13, checking if an error was an AppError required doing something like the following:</p><pre>err := Foobar()<br>if appErr, ok := err.(*AppError); err != nil &amp;&amp; ok {<br>    // handle AppError instance<br>}</pre><p>It’s not rare to still find the above being done or even direct string comparisons of error content to identify specific errors. Here’s where errors.Is and errors.As come in to handle errors more effectively…</p><h3>Understanding errors.Is</h3><p>errors.Is allows you to check if an error is or wraps a specific error, even when it’s been wrapped by another error.</p><p>Here’s an example of errors.Is:</p><pre>package main<br><br>import (<br>    &quot;errors&quot;<br>    &quot;fmt&quot;<br>    &quot;io&quot;<br>)<br><br>func main() {<br>    err := fmt.Errorf(&quot;read failed: %w&quot;, io.EOF)<br>    // Using errors.Is to check if err wraps io.EOF<br>    if errors.Is(err, io.EOF) {<br>        fmt.Println(&quot;EOF error detected&quot;)<br>    } else {<br>        fmt.Println(&quot;Different error&quot;)<br>    }<br>}</pre><p>In this case, errors.Is successfully identifies that err wraps io.EOF. This is particularly useful when you’re dealing with libraries or functions that return wrapped errors and you need to inspect the underlying cause.</p><h3>Practical Use Case for errors.Is</h3><p>Consider a scenario where a function interacts with a file and may encounter multiple types of errors. Some of these errors may be more severe than others. You may want to handle `os.ErrNotExist` errors (file not found) differently from `io.EOF` (end of file).</p><pre>package main<br><br>import (<br>    &quot;errors&quot;<br>    &quot;fmt&quot;<br>    &quot;os&quot;<br>)<br><br>func main() {<br>    _, err := os.Open(&quot;non-existent-file.txt&quot;)<br>    if err != nil {<br>        if errors.Is(err, os.ErrNotExist) {<br>            fmt.Println(&quot;File does not exist&quot;)<br>        } else {<br>            fmt.Println(&quot;An unexpected error occurred:&quot;, err)<br>        }<br>    }<br>}</pre><p>In this example, errors.Is enables you to identify the specific error without worrying about how deeply it may be wrapped.</p><h3>Using errors.As for Type-Specific Error Handling</h3><p>While errors.Is checks if an error is or wraps a specific error, errors.As is used to check if an error can be assigned to a variable of a particular error type. This is valuable when you need to interact with custom error types or perform operations based on the specific properties of the underlying error.</p><p>Here’s an example using the AppError defined earlier:</p><pre>func main() {<br>    err := fmt.Errorf(&quot;some context: %w&quot;, NewAppError(&quot;something went wrong&quot;, http.StatusInternalServerError))<br>    var myErr *AppErr<br>    if errors.As(err, &amp;myErr) {<br>        fmt.Println(&quot;AppErr detected:&quot;, myErr.Msg)<br>    } else {<br>        fmt.Println(&quot;Different error&quot;)<br>    }<br>}</pre><p>In this case, errors.As unwraps the error and assigns the underlying MyError to myErr, allowing you to handle it based on its type.</p><h3>Practical Use Case for `errors.As`</h3><p>Consider a situation where you need to handle errors from a third-party library/API. It might return errors with specific types, and you want to inspect the properties of those errors to take action. Using errors.As, you can extract and interact with these error types:</p><pre>// insert a user into the table<br>_, err = db.Exec(&quot;INSERT INTO users (email) VALUES ($1)&quot;, &quot;test@example.com&quot;)<br><br>// check for constraint violation errors using errors.As<br>if err != nil {<br>    var pqErr *pq.Error<br>    if errors.As(err, &amp;pqErr) { // handle specific PostgreSQL error<br>        if pqErr.Code == &quot;23505&quot; { // 23505 is the PostgreSQL code for unique_violation<br>            fmt.Printf(&quot;Unique constraint violation on column %s\n&quot;, pqErr.Column)<br>        } else {<br>            fmt.Printf(&quot;PostgreSQL Error: Code=%s, Message=%s\n&quot;, pqErr.Code, pqErr.Message)<br>        }<br>    } else {<br>        fmt.Printf(&quot;Unknown error occurred: %v\n&quot;, err)<br>    }<br>} else {<br>    fmt.Println(&quot;Insert succeeded!&quot;)<br>}</pre><p>In this example, errors.As allows you to extract the postgres pq error type and act based on its properties, such as its error code or message.</p><h3>Conclusion</h3><p>The errors.Is and errors.As functions introduced in Go 1.13 provide a more powerful way to handle errors, especially when dealing with wrapped or custom error types. By leveraging these functions, you can write more maintainable and expressive error-handling logic, making your Go applications more robust and easier to debug.</p><h3>Benefits of Using errors.Is and errors.As</h3><ul><li><strong>Enhanced Error Inspection</strong>: You can inspect and match both specific and wrapped errors, leading to more robust error handling.</li><li><strong>Type-Specific Logic</strong>: With errors.As, you can differentiate and handle custom error types, improving your ability to respond appropriately to different error conditions.</li><li><strong>Compatibility with Existing Code</strong>: These functions work seamlessly with older Go code, making it easy to adopt them incrementally.</li></ul><h3>When to Use errors.Is vs. errors.As</h3><ul><li>Use errors.Is when you need to check if an error is or wraps a particular error value (e.g., io.EOF or os.ErrNotExist).</li><li>Use errors.As when you need to check if an error can be cast to a specific type and access its underlying properties.</li></ul><p>Incorporating these practices into your codebase can improve error diagnostics and provide better control over how errors are handled across your application, especially when dealing with third-party libraries or complex, multi-layered systems.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ecc971a7f7f7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Struct Tags in Go: Implementing Custom Tag Functionality]]></title>
            <link>https://medium.com/@ullauri.byron/struct-tags-in-go-implementing-custom-tag-functionality-b32c3c87423d?source=rss-b540ad628920------2</link>
            <guid isPermaLink="false">https://medium.com/p/b32c3c87423d</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[golang-development]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[golang-tutorial]]></category>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Byron Cabrera]]></dc:creator>
            <pubDate>Mon, 25 Nov 2024 20:22:08 GMT</pubDate>
            <atom:updated>2024-11-25T20:22:08.457Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5WqrBcL4cfdVUy5SSYBgIw.png" /></figure><p>Go’s struct tags offer a way to define metadata for struct fields allowing developers to specify how these fields should be handled during operations like serialization or validation. A common use case is the json tag, which tells the Go JSON package how to map struct fields to JSON keys. For example:</p><pre>type User struct {<br>    ID int `json:&quot;id&quot;`<br>    Name string `json:&quot;name&quot;`<br>    Email string `json:&quot;email&quot;`<br>}</pre><p>In this article, we’ll explore how to create custom struct tags to implement custom functionality. We will use the use case of sanitizing HTML content — an important task in many web applications to prevent cross-site scripting (XSS) attacks. You’ll learn how to define custom tags, implement custom tag logic, and integrate them into your Go structs seamlessly.</p><h3>What are Struct Tags?</h3><p>In Go, struct tags are metadata defined in backticks `` after the field declarations in a struct. These tags can be processed using the reflect package, which allows introspection of Go types at runtime. The general format for struct tags looks like this:</p><pre>type StructName struct {<br>    FieldName FieldType `tagName:&quot;value&quot;`<br>}</pre><p>You can define multiple tags on a single field, for example, json and a custom tag for sanitization sanitize:</p><pre>type Comment struct {<br>    Body string `json:&quot;body&quot; sanitize:&quot;stripall&quot;`<br>}</pre><p>In this example, stripall could be a custom sanitization instruction that indicates the field should be stripped of all HTML content before it’s stored or processed.</p><h3>Implementing HTML Sanitization Using Struct Tags</h3><p>Let’s build a custom solution to sanitize HTML content from struct fields using struct tags. Our goal is to create a function that inspects each field of a struct and applies the necessary sanitization based on the tag’s value.</p><p><strong>Step 1: Defining the Custom Tag Values</strong></p><p>The sanitize tag will instruct our code to strip all HTML or allow some safe HTML tags, based on its value:</p><ul><li>stripall: Remove all HTML tags.</li><li>safeugc: Allow user-generated content (UGC) with limited safe HTML tags (e.g., &lt;b&gt;, &lt;i&gt;).</li></ul><p>Here’s how the struct might look:</p><pre>type Comment struct {<br>    Body string `json:&quot;body&quot; sanitize:&quot;stripall&quot;`<br>    Title string `json:&quot;title&quot; sanitize:&quot;safeugc&quot;`<br>}</pre><p><strong>Step 2: Writing the Sanitization Function</strong></p><p>We’ll write a SanitizeStruct function that uses Go’s reflect package to process the struct tags and sanitize fields accordingly:</p><pre>func getCleansedValue(tag string, value string) (string, error) {<br> var cleanedValue string<br> switch TagValue(tag) {<br> case StripAll:<br>  cleanedValue = config.StripAll(value)<br> case SafeUGC:<br>  cleanedValue = config.SafeUGC(value)<br> default:<br>  return &quot;&quot;, ErrInvalidTagValue<br> }<br><br> return cleanedValue, nil<br>}<br><br>// SanitizeStruct takes a struct and sanitizes it based on `sanitize` tags<br>func SanitizeStruct(s interface{}) error {<br> val := reflect.ValueOf(s).Elem()<br> typ := val.Type()<br><br> for i := 0; i &lt; val.NumField(); i++ {<br>  field := val.Field(i)<br>  fieldType := typ.Field(i)<br>  fieldKind := field.Kind()<br><br>  tag := fieldType.Tag.Get(&quot;sanitize&quot;)<br>  if tag == &quot;&quot; {<br>   if fieldKind == reflect.Struct {<br>    if err := SanitizeStruct(field.Addr().Interface()); err != nil {<br>     return err<br>    }<br>   }<br>   continue<br>  } else if fieldKind == reflect.Struct {<br>   return ErrInvalidPropertyType<br>  } else if fieldKind != reflect.String &amp;&amp; !(fieldKind == reflect.Slice &amp;&amp; field.Type().Elem().Kind() == reflect.String) {<br>   return ErrInvalidPropertyType<br>  }<br><br>  if fieldKind == reflect.Slice {<br>   for j := 0; j &lt; field.Len(); j++ {<br>    cleanedValue, err := getCleansedValue(tag, field.Index(j).String())<br>    if err != nil {<br>     return err<br>    }<br>    field.Index(j).SetString(cleanedValue)<br>   }<br>  } else {<br>   cleanedValue, err := getCleansedValue(tag, field.String())<br>   if err != nil {<br>    return err<br>   }<br>   field.SetString(cleanedValue)<br>  }<br> }<br><br> return nil<br>}</pre><p>Leveraging the above function would then be as easy as the following:</p><pre>func main() {<br> comment:= &amp;Comment{<br>  Body: &quot;&lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;&quot;,<br>  Title: &quot;&lt;b&gt;Bold Title&lt;/b&gt;&quot;,<br> }<br> <br> err := SanitizeStruct(comment)<br> if err != nil {<br>  fmt.Println(&quot;Error:&quot;, err)<br> }<br> <br> fmt.Printf(&quot;Sanitized Comment: %+v\n&quot;, comment)<br>}</pre><p>In this example:</p><ul><li>SanitizeStruct iterates over the fields of a struct and applies the relevant sanitization function based on the sanitize tag.</li><li>StripAllHTML removes all HTML from the field’s value, and SafeUGC removes only unsafe HTML tags.</li></ul><p>The output is as follow:</p><p>Sanitized Comment: &amp;{Body: Title:&lt;b&gt;Bold Title&lt;/b&gt;}</p><h3>When not to use struct tags</h3><p>Struct tags are not always the best tool for more complex logic or scenarios requiring dynamic behavior. Since struct tags are static and evaluated at runtime using reflection, they lack flexibility in cases where business logic might change frequently or needs to be conditionally applied. Moreover, tags aren’t suitable for implementing more complex validation workflows, error handling, or behavior that depends on external factors, as reflection can become slower and harder to debug when logic becomes more intricate. For more advanced or changing needs, embedding such logic elsewhere in your code, like in dedicated functions or middleware, might be a better approach.</p><h3>Conclusion</h3><p>Go’s struct tags offer a flexible and declarative way to add special field logic directly into your data structures. By combining custom struct tags with reflection, you can create reusable solutions that can be easily implemented across struct properties. Please note, using reflection to inspect struct tags adds overhead, so use this approach carefully in performance-sensitive areas!</p><p>For the full code used above please click <a href="https://github.com/Ullauri/sanitags">here</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b32c3c87423d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using httptest.Server in Go to Mock and Test External API Calls]]></title>
            <link>https://medium.com/@ullauri.byron/using-httptest-server-in-go-to-mock-and-test-external-api-calls-68ce444cf934?source=rss-b540ad628920------2</link>
            <guid isPermaLink="false">https://medium.com/p/68ce444cf934</guid>
            <category><![CDATA[golang-tutorial]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[testing]]></category>
            <dc:creator><![CDATA[Byron Cabrera]]></dc:creator>
            <pubDate>Tue, 29 Oct 2024 00:37:28 GMT</pubDate>
            <atom:updated>2024-10-29T00:37:28.093Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cYIYfyxTkpYvcdEZy3kKVg.png" /></figure><p>When building applications that interact with external APIs, it’s crucial to verify that your code makes the correct requests and handles responses appropriately. Testing such code can be challenging due to the reliance on external services. Luckily, Go’s httptest package offers the httptest.Server tool, allowing you to simulate external services within your tests seamlessly.</p><p>In this article, we’ll cover the basics of httptest.Server, how to set it up, and explore various strategies for simulating external responses to ensure your application behaves as expected.</p><h3>What is httptest.Server?</h3><p>The httptest.Server is a utility that enables you to create an in-memory HTTP server for testing purposes. It mimics the behavior of an actual web server, allowing you to test how your code interacts with an API without needing a live external service. This can help verify request correctness, response handling, and error scenarios efficiently and reliably.</p><p>Here’s a basic example:</p><pre>package main<br><br>import (<br> &quot;fmt&quot;<br> &quot;net/http&quot;<br> &quot;net/http/httptest&quot;<br> &quot;testing&quot;<br>)<br><br>func TestBasicExample(t *testing.T) {<br> // create a new test server with a simple handler<br> server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {<br>  fmt.Fprintln(w, `{&quot;message&quot;: &quot;hello world&quot;}`)<br> }))<br> defer server.Close()<br><br> // make an HTTP request to the test server<br> resp, err := http.Get(server.URL)<br> if err != nil {<br>  t.Fatalf(&quot;Failed to make request: %v&quot;, err)<br> }<br> defer resp.Body.Close()<br><br> // check the response<br> if resp.StatusCode != http.StatusOK {<br>  t.Fatalf(&quot;Expected status 200 OK, got %v&quot;, resp.Status)<br> }<br>}</pre><p>the above code can be thought of as three parts:</p><ol><li>setting up the test server and responses</li><li>having whatever client code you write point to the test server</li><li>verifying responses</li></ol><h3>Simulating Different Responses</h3><p>A powerful feature of httptest.Server is the ability to define custom responses, allowing you to simulate different API responses and status codes. This is invaluable for testing how your code handles various scenarios, including both success and failure cases.</p><p>Example: Custom Responses and Status Codes</p><pre>func TestAPIClient_HandleErrorResponse(t *testing.T) {<br> server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {<br>  http.Error(w, `{&quot;error&quot;: &quot;not found&quot;}`, http.StatusNotFound)<br> }))<br> defer server.Close()<br><br> client := &amp;APIClient{BaseURL: server.URL}<br> _, err := client.GetMessage()<br><br> if err == nil {<br>  t.Error(&quot;Expected an error, got none&quot;)<br> }<br>}</pre><h3>Handling Configurations in Tests</h3><p>Depending on how your application is configured, you’ll need to ensure that your API client points to the httptest.Server instance rather than the actual external API during testing. You can handle this in a few ways:</p><ul><li><strong>Updating Configurations Temporarily:</strong> If your API base URL is defined in a configuration file or environment variable, you can temporarily update this value in your tests to point to the httptest.Server‘s base URL and then reset it once done as needed.</li><li><strong>Passing Base URL Directly:</strong> Alternatively, if your functions accept the URL as a parameter, you can simply pass httptest.Server’s base URL during the test.</li></ul><h3>Complete Basic Example</h3><p>Combining the concepts above, let’s walk through a basic test setup that verifies different response handling:</p><pre>type APIClient struct {<br> BaseURL string<br>}<br><br>type APIResponse struct {<br> Message string `json:&quot;message&quot;`<br> Error   string `json:&quot;error&quot;`<br>}<br><br>func (client *APIClient) GetData() (*APIResponse, error) {<br> resp, err := http.Get(client.BaseURL + &quot;/data&quot;)<br> if err != nil {<br>  return nil, fmt.Errorf(&quot;failed to make request: %w&quot;, err)<br> }<br> defer resp.Body.Close()<br><br> var apiResp APIResponse<br> if err := json.NewDecoder(resp.Body).Decode(&amp;apiResp); err != nil {<br>  return nil, fmt.Errorf(&quot;failed to decode response: %w&quot;, err)<br> }<br><br> return &amp;apiResp, nil<br>}<br><br>func TestAPIClient_GetData(t *testing.T) {<br> tests := []struct {<br>  name           string<br>  serverResponse string<br>  serverStatus   int<br>  expectedMsg    string<br>  expectedErrMsg string<br>  expectedCode   int<br> }{<br>  {<br>   name:           &quot;Successful response&quot;,<br>   serverResponse: `{&quot;message&quot;: &quot;success&quot;}`,<br>   serverStatus:   http.StatusOK,<br>   expectedMsg:    &quot;success&quot;,<br>  },<br>  {<br>   name:           &quot;Not Found response&quot;,<br>   serverResponse: `{&quot;error&quot;: &quot;not found&quot;}`,<br>   serverStatus:   http.StatusNotFound,<br>   expectedErrMsg: &quot;not found&quot;,<br>  },<br>  {<br>   name:           &quot;Internal Server Error&quot;,<br>   serverResponse: `{&quot;error&quot;: &quot;internal error&quot;}`,<br>   serverStatus:   http.StatusInternalServerError,<br>   expectedErrMsg: &quot;internal error&quot;,<br>  },<br> }<br><br> for _, test := range tests {<br>  // create a new HTTP test server for each test case<br>  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {<br>   w.WriteHeader(test.serverStatus)<br>   w.Write([]byte(test.serverResponse))<br>  }))<br>  defer server.Close()<br><br>  client := &amp;APIClient{BaseURL: server.URL}<br><br>  t.Run(test.name, func(t *testing.T) {<br>   resp, err := client.GetData()<br><br>   if resp == nil {<br>    t.Fatal(&quot;Expected response, got nil&quot;)<br>   } else if err != nil {<br>    t.Fatalf(&quot;Expected no error, got %v&quot;, err)<br>   }<br><br>   // check the response message or error message<br>   if test.expectedMsg != &quot;&quot; &amp;&amp; resp.Message != test.expectedMsg {<br>    t.Errorf(&quot;Expected message &#39;%s&#39;, got &#39;%s&#39;&quot;, test.expectedMsg, resp.Message)<br>   } else if test.expectedErrMsg != &quot;&quot; &amp;&amp; resp.Error != test.expectedErrMsg {<br>    t.Errorf(&quot;Expected error message &#39;%s&#39;, got &#39;%s&#39;&quot;, test.expectedErrMsg, resp.Error)<br>   }<br>  })<br> }<br>}</pre><h3>Best Practices for httptest.Server</h3><ol><li><strong>Close Test Servers:</strong> Always defer the Close method to ensure the server is shut down after the test completes.</li><li><strong>Use Dedicated Configurations in Tests:</strong> Avoid hardcoding URLs in your application code. Instead, make the API URL configurable so you can easily switch to an httptest.Server during testing.</li><li><strong>Handle Various Status Codes:</strong> Be sure to test how your code handles different HTTP status codes and responses, as external APIs can fail in various ways.</li><li><strong>Use Response Simulation Sparingly:</strong> While it’s powerful to mock various responses, remember that over-mocking can make tests fragile and overly reliant on specific assumptions.</li><li><strong>Test Realistic Scenarios with Faker:</strong> To simulate real-world scenarios, especially in cases involving user data, consider using libraries like Faker to generate random but structured data.</li></ol><h3>Conclusion</h3><p>Testing external API interactions can be complex, but httptest.Server in Go provides a robust solution for simulating these scenarios. By implementing these strategies, you can write reliable tests for your application’s external service integrations, ensuring your application responds as expected to various outcomes.</p><p>I created a module called <a href="https://github.com/ullauri/fauxmux">fauxmux</a> that simulates various responses, errors, and more. Check it out for ideas on building a reusable solution for testing external API interactions in your services.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=68ce444cf934" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building Reliable Workflows with Temporal in Go: Essential Best Practices]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@ullauri.byron/building-reliable-workflows-with-temporal-in-go-essential-best-practices-cfa0598864d7?source=rss-b540ad628920------2"><img src="https://cdn-images-1.medium.com/max/1400/1*JcEiaa4dpb__BOXmwb9BAA.png" width="1400"></a></p><p class="medium-feed-snippet">Temporal is an open-source platform designed to manage the execution of workflows in a reliable, fault-tolerant way. With features like&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/@ullauri.byron/building-reliable-workflows-with-temporal-in-go-essential-best-practices-cfa0598864d7?source=rss-b540ad628920------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@ullauri.byron/building-reliable-workflows-with-temporal-in-go-essential-best-practices-cfa0598864d7?source=rss-b540ad628920------2</link>
            <guid isPermaLink="false">https://medium.com/p/cfa0598864d7</guid>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[temporal]]></category>
            <dc:creator><![CDATA[Byron Cabrera]]></dc:creator>
            <pubDate>Sat, 26 Oct 2024 05:04:14 GMT</pubDate>
            <atom:updated>2024-10-26T05:04:14.236Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Optimizing Database Connections in Go: Improving Throughput by Managing Open Connections…]]></title>
            <link>https://medium.com/@ullauri.byron/optimizing-database-connections-in-go-improving-throughput-by-managing-open-connections-7d90b2eb9169?source=rss-b540ad628920------2</link>
            <guid isPermaLink="false">https://medium.com/p/7d90b2eb9169</guid>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[database-connection]]></category>
            <category><![CDATA[connection-pool]]></category>
            <category><![CDATA[database-pooling]]></category>
            <dc:creator><![CDATA[Byron Cabrera]]></dc:creator>
            <pubDate>Thu, 17 Oct 2024 23:20:01 GMT</pubDate>
            <atom:updated>2024-11-03T13:38:51.841Z</atom:updated>
            <content:encoded><![CDATA[<h3>Optimizing Database Connections in Go: Improving Throughput by Managing Open Connections Efficiently</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ow3OP5soO4aDUoxyMShs9A.png" /></figure><p>Go’s <a href="https://pkg.go.dev/database/sql">database/sql</a> package provides automatic database connection pooling allowing developers to efficiently manage connections. Typically, as a developer, you&#39;d request an open connection, perform your query, and close the connection to ensure that it’s returned to the pool.</p><p>One common mistake developers make is holding a database connection open for too long which can lead to bottlenecks, where new requests are forced to wait for an available connection, hindering the effectiveness of the connection pool.</p><p>In this article, we’ll explore how to avoid this issue and optimize Go applications for better throughput by identifying a common problem area and learning how to resolve it.</p><h3>Basic Example</h3><p>To start, Let’s take a look at a basic HTTP handler that returns employee records:</p><pre>func GetEmployeesHandler(w http.ResponseWriter, r *http.Request) {<br>    rows, err := db.Query(`SELECT id, name, email FROM employee`)<br>    if err != nil {<br>        http.Error(w, fmt.Sprintf(&quot;error querying database: %v&quot;, err), http.StatusInternalServerError)<br>        return<br>    }<br>    defer rows.Close()<br><br>    var employees []Employee<br>    for rows.Next() {<br>        var e Employee<br>        if err := rows.Scan(&amp;e.ID, &amp;e.Name, &amp;e.Email); err != nil {<br>            http.Error(w, fmt.Sprintf(&quot;Error scanning row: %v&quot;, err), http.StatusInternalServerError)<br>            return<br>        }<br>        decorateEmployee(&amp;e)<br>        employees = append(employees, e)<br>    }<br><br>    if err = rows.Err(); err != nil {<br>        http.Error(w, fmt.Sprintf(&quot;error during row iteration: %v&quot;, err), http.StatusInternalServerError)<br>        return<br>    }<br><br>    w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)<br>    if err := json.NewEncoder(w).Encode(employees); err != nil {<br>        http.Error(w, &quot;Error encoding response&quot;, http.StatusInternalServerError)<br>        return<br>    }<br>}</pre><p>In this handler we:</p><ol><li>query the database for employee records.</li><li>use defer rows.Close() to ensure that the connection is closed once we&#39;re done processing the result set.</li><li>scan each row and decorate it with data obtained from an external source.</li><li>append the final struct to the result array.</li><li>check for any errors during iteration and return the results as JSON.</li></ol><p>At first glance, nothing seems out of the ordinary; in fact, you’d expect the above to perform relatively well under stress.…</p><h3>Initial Performance Results</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*S-50LoTcMwIcCgH_9il89A.png" /></figure><p>Using a stress-testing tool like <a href="https://github.com/tsenart/vegeta">Vegeta</a>, we can simulate load on this endpoint. At an initial rate of 10 requests per second (RPS), the application performs relatively well during a 30 second test run:</p><pre>$ echo &quot;GET http://localhost:8080/employees&quot; | vegeta attack -duration=30s -rate=10 | tee results.bin | vegeta report<br>Requests      [total, rate, throughput]         300, 10.03, 5.45<br>Duration      [total, attack, wait]             52.095s, 29.9s, 22.196s<br>Latencies     [min, mean, 50, 90, 95, 99, max]  2.318s, 11.971s, 8.512s, 26.222s, 30.001s, 30.001s, 30.001s<br>Bytes In      [total, mean]                     2290991, 7636.64<br>Bytes Out     [total, mean]                     0, 0.00<br>Success       [ratio]                           94.67%<br>Status Codes  [code:count]                      0:16  200:284</pre><p>However, when we increase the load to 50 RPS, we see a significant drop in throughput and a sharp rise in request failures:</p><pre>$ echo &quot;GET http://localhost:8080/employees&quot; | vegeta attack -duration=30s -rate=50 | tee results.bin | vegeta report<br>Requests      [total, rate, throughput]         1500, 50.03, 4.20<br>Duration      [total, attack, wait]             59.981s, 29.981s, 30s<br>Latencies     [min, mean, 50, 90, 95, 99, max]  2.208s, 27.175s, 30.001s, 30.001s, 30.001s, 30.002s, 30.002s<br>Bytes In      [total, mean]                     2032879, 1355.25<br>Bytes Out     [total, mean]                     0, 0.00<br>Success       [ratio]                           16.80%<br>Status Codes  [code:count]                      0:1248  200:252</pre><p>( The Status Codes of 0 above signify client timeouts that occurred during the test run )</p><h3>Identifying the Bottleneck</h3><p>At 50 RPS, the success rate drops dramatically, and the throughput falls to just 4.2 requests per second. Why? One reason could be that 50 RPS is just an unreasonable target given our current resources. To confirm whether the code <em>could</em> perform better with a change, we can look into gathering some metrics. One source of metrics is the decorating process, but for the purpose of this article, we will focus on database connection pool statistics.</p><p>Go’s <a href="https://pkg.go.dev/database/sql">database/sql</a> package offers a view into how an application’s DB pooling is performing via its <a href="https://pkg.go.dev/database/sql#DB.Stats">DBStats</a> function. It returns the following set of stats that we’ll be interested in:</p><ol><li>InUse: The number of connections currently in use.</li><li>Idle: The number of idle connections.</li><li>WaitCount: The total number of connections waited for.</li></ol><p>We can expose these values by adding another endpoint handler:</p><pre>func GetInfoHandler(w http.ResponseWriter, r *http.Request) {<br>    w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)<br>    if err := json.NewEncoder(w).Encode(db.Stats()); err != nil {<br>        http.Error(w, &quot;Error encoding response&quot;, http.StatusInternalServerError)<br>        return<br>    }<br>}</pre><p>Monitoring the /info endpoint during a rerun of the above stress test shows:</p><pre>$ while true; do curl -s http://localhost:8080/info; sleep 2; done<br>...<br>{&quot;MaxOpenConnections&quot;:15,&quot;OpenConnections&quot;:15,&quot;InUse&quot;:15,&quot;Idle&quot;:0,&quot;WaitCount&quot;:1434,&quot;WaitDuration&quot;:1389188829869,&quot;MaxIdleClosed&quot;:0,&quot;MaxIdleTimeClosed&quot;:0,&quot;MaxLifetimeClosed&quot;:0}<br>{&quot;MaxOpenConnections&quot;:15,&quot;OpenConnections&quot;:15,&quot;InUse&quot;:15,&quot;Idle&quot;:0,&quot;WaitCount&quot;:1485,&quot;WaitDuration&quot;:1582086078604,&quot;MaxIdleClosed&quot;:0,&quot;MaxIdleTimeClosed&quot;:0,&quot;MaxLifetimeClosed&quot;:0}<br>{&quot;MaxOpenConnections&quot;:15,&quot;OpenConnections&quot;:15,&quot;InUse&quot;:15,&quot;Idle&quot;:0,&quot;WaitCount&quot;:1485,&quot;WaitDuration&quot;:1772844971842,&quot;MaxIdleClosed&quot;:0,&quot;MaxIdleTimeClosed&quot;:0,&quot;MaxLifetimeClosed&quot;:0}<br>...</pre><p>This reveals that the connection pool is maxed out (InUse: 15, Idle: 0), and every new request is being forced to wait (WaitCount keeps increasing). In other words, the connection pool is essentially stalled, causing the latency and timeout issues observed earlier!</p><h3>Optimizing Connection Usage</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RNcG4Q_xlaXF77DocGIymQ.png" /></figure><p>Looking at our original code above, we see that the problem is either the query itself is performing poorly or the decorating function is taking long to return each time its called while we iterate through the result set. We can explore the latter by attempting to decorate the record outside of the rows.Next() loop and moving it below our database connection usage.</p><p>Here’s the updated code:</p><pre>func GetEmployeesHandler(w http.ResponseWriter, r *http.Request) {<br>    rows, err := db.Query(`SELECT id, name, email FROM employee`)<br>    if err != nil {<br>        http.Error(w, fmt.Sprintf(&quot;error querying database: %v&quot;, err), http.StatusInternalServerError)<br>        return<br>    }<br><br>    var employees []Employee<br>    for rows.Next() {<br>        var e Employee<br>        if err := rows.Scan(&amp;e.ID, &amp;e.Name, &amp;e.Email); err != nil {<br>            if closeErr := rows.Close(); closeErr != nil {<br>                err = fmt.Errorf(&quot;%w; failed to close rows: %v&quot;, err, closeErr)<br>            }<br>            http.Error(w, fmt.Sprintf(&quot;error scanning row: %v&quot;, err), http.StatusInternalServerError)<br>            return<br>        }<br><br>        employees = append(employees, e)<br>    }<br><br>    if err = rows.Err(); err != nil {<br>        if closeErr := rows.Close(); closeErr != nil {<br>            err = fmt.Errorf(&quot;%w; failed to close rows: %v&quot;, err, closeErr)<br>        }<br>        http.Error(w, fmt.Sprintf(&quot;error during row iteration: %v&quot;, err), http.StatusInternalServerError)<br>        return<br>    }<br><br>    for i := range employees {<br>        decorateEmployee(&amp;employees[i])<br>    }<br><br>    w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)<br>    if err := json.NewEncoder(w).Encode(employees); err != nil {<br>        http.Error(w, &quot;Error encoding response&quot;, http.StatusInternalServerError)<br>        return<br>    }<br>}</pre><p>In this refactored handler, we:</p><ol><li>Scan all the rows into memory.</li><li>Close the connection immediately after scanning, freeing it back to the pool (Don’t forget to handle errors related to closing connections!).</li><li>Decorate the employee records in memory, without holding the connection open.</li></ol><h3>Performance After Optimization</h3><p>Running the same Vegeta test at 50 RPS after the optimization yields the following results:</p><pre>$ echo &quot;GET http://localhost:8080/employees&quot; | vegeta attack -duration=30s -rate=50 | tee results.bin | vegeta report<br>Requests      [total, rate, throughput]         1500, 50.03, 45.78<br>Duration      [total, attack, wait]             32.768s, 29.98s, 2.788s<br>Latencies     [min, mean, 50, 90, 95, 99, max]  2.045s, 2.502s, 2.499s, 2.692s, 2.741s, 2.856s, 2.995s<br>Bytes In      [total, mean]                     11817000, 7878.00<br>Bytes Out     [total, mean]                     0, 0.00<br>Success       [ratio]                           100.00%<br>Status Codes  [code:count]                      200:1500</pre><pre>...<br>{&quot;MaxOpenConnections&quot;:15,&quot;OpenConnections&quot;:1,&quot;InUse&quot;:0,&quot;Idle&quot;:1,&quot;WaitCount&quot;:0,&quot;WaitDuration&quot;:0,&quot;MaxIdleClosed&quot;:0,&quot;MaxIdleTimeClosed&quot;:0,&quot;MaxLifetimeClosed&quot;:0}<br>{&quot;MaxOpenConnections&quot;:15,&quot;OpenConnections&quot;:1,&quot;InUse&quot;:0,&quot;Idle&quot;:1,&quot;WaitCount&quot;:0,&quot;WaitDuration&quot;:0,&quot;MaxIdleClosed&quot;:0,&quot;MaxIdleTimeClosed&quot;:0,&quot;MaxLifetimeClosed&quot;:0}<br>{&quot;MaxOpenConnections&quot;:15,&quot;OpenConnections&quot;:1,&quot;InUse&quot;:0,&quot;Idle&quot;:1,&quot;WaitCount&quot;:0,&quot;WaitDuration&quot;:0,&quot;MaxIdleClosed&quot;:0,&quot;MaxIdleTimeClosed&quot;:0,&quot;MaxLifetimeClosed&quot;:0}<br>...</pre><p>As we can see, not only was there huge improvement in throughput and latency with 100%, we also see that the total OpenConnections doesn’t make it past 1 and we even have Idle connections on standby thereby keeping the WaitCount consistently at zero!</p><h3>Summary</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*X4WKqlrn0zFxFqGeRwV1ow.png" /></figure><p>Instead of holding the connections open while performing additional I/O-bound operations like decorating records, we can optimize the handling of connections by fetching all rows into memory first, then closing the connection immediately. This allows the database connection to be returned to the pool sooner, freeing up resources for other incoming requests allowing for better throughput and concurrency.</p><h3>Using the Repository Pattern</h3><p>Applying the repository pattern can further improve code structure by separating storage actions from business logic. The repository pattern allows you to abstract away the data access layer (database interactions) from the rest of the application. This approach offers several benefits:</p><ol><li><strong>Better Code Separation and Readability</strong>: By separating database logic from the application’s core business logic, each part becomes easier to read, understand, and maintain.</li><li><strong>Easier Testing with Mocked Repositories</strong>: The repository pattern allows you to create mock implementations of the database layer, which can simulate database responses for testing. For instance, instead of querying the database, the handler function can rely on a mock repository, which returns predefined data. This makes it easier to isolate and test the handler’s performance without involving the database.</li><li><strong>Improved Connection Management</strong>: With the repository pattern, you can make each database interaction more modular, ensuring that resources are managed efficiently (e.g., handling rows.Close() at the repository layer). This minimizes the risk of connection pooling bottlenecks.</li></ol><p>Here’s an example of what applying the repository pattern to the GetEmployeesHandler might look like :</p><pre>type EmployeeService interface {<br>    GetEmployees() ([]Employee, error)<br>}<br><br>...<br>func (es Client) GetEmployees() ([]Employee, error) {<br>    rows, err := es.db.Query(`SELECT id, name, email FROM employee`)<br>    if err != nil {<br>        return nil, err<br>    }<br>    defer func() {<br>        if closeErr := rows.Close(); closeErr != nil {<br>            log.Printf(&quot;error closing rows: %v&quot;, closeErr)<br>        }<br>    }()<br><br>    var employees []Employee<br>    for rows.Next() {<br>        var e Employee<br>        if err := rows.Scan(&amp;e.ID, &amp;e.Name, &amp;e.Email); err != nil {<br>            return nil, err<br>        }<br>        employees = append(employees, e)<br>    }<br><br>    if err = rows.Err(); err != nil {<br>        return nil, err<br>    }<br><br>    return employees, nil<br>}<br>...<br><br>func (api API) GetEmployeesHandler(w http.ResponseWriter, r *http.Request) {<br>    employees, err := api.Employees().GetEmployees()<br>    if err != nil {<br>        http.Error(w, fmt.Sprintf(&quot;Error retrieving employees: %v&quot;, err), http.StatusInternalServerError)<br>        return<br>    }<br><br>    for i := range employees {<br>        decorateEmployee(&amp;employees[i])<br>    }<br><br>    w.Header().Set(&quot;Content-Type&quot;, &quot;application/json&quot;)<br>    if err := json.NewEncoder(w).Encode(employees); err != nil {<br>        http.Error(w, &quot;Error encoding response&quot;, http.StatusInternalServerError)<br>        return<br>    }<br>}</pre><p>Using the repository pattern in this way enables better resource management, testing, and modularity. It also means you can use defer again to close the connection because the operation itself is kept atomic!</p><p>For the full code used above please click <a href="https://github.com/Ullauri/storycodesamples/tree/main/go/inefficientConnectionPooling">here</a>.</p><p>Cheers!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7d90b2eb9169" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>