<?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>DEV Community: Rodney Otieno</title>
    <description>The latest articles on DEV Community by Rodney Otieno (@rodneyo1).</description>
    <link>https://dev.to/rodneyo1</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%2F1616500%2F44a4af53-5519-47bd-b995-60de952a3c8a.png</url>
      <title>DEV Community: Rodney Otieno</title>
      <link>https://dev.to/rodneyo1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rodneyo1"/>
    <language>en</language>
    <item>
      <title>Stop Writing Old Go: How modernize Transforms Your Development</title>
      <dc:creator>Rodney Otieno</dc:creator>
      <pubDate>Sat, 24 May 2025 21:31:00 +0000</pubDate>
      <link>https://dev.to/rodneyo1/stop-writing-old-go-how-modernize-transforms-your-development-1e3g</link>
      <guid>https://dev.to/rodneyo1/stop-writing-old-go-how-modernize-transforms-your-development-1e3g</guid>
      <description>&lt;p&gt;Go, with its legendary simplicity and efficiency, continues to evolve. While the language prides itself on stability, subtle yet powerful additions are consistently introduced to make Go development even more productive, readable, and performant. Enter &lt;strong&gt;&lt;code&gt;modernize&lt;/code&gt;&lt;/strong&gt;, a powerful analyzer that acts as your personal guide to these contemporary Go constructs. If you're still writing Go 1.17 code in a Go 1.24 world, it's time to talk.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;modernize&lt;/code&gt; analyzer, part of &lt;code&gt;golang.org/x/tools/gopls&lt;/code&gt;, is all about leveraging the latest advancements in the Go ecosystem to write cleaner, more idiomatic, and often more efficient code. Think of it as a quality-of-life upgrade for your codebase, gently nudging you towards a more modern and robust Go development experience. In the context of the Go ecosystem, an analyzer is a specialized tool that performs static analysis on Go source code. This means it examines your code without actually running it, identifying patterns, potential issues, or, in the case of modernize, opportunities for improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go's Evolution, Not Its Dictation: Why You Should Still Modernize
&lt;/h2&gt;

&lt;p&gt;Go's design philosophy champions stability and backward compatibility. Unlike some languages that might introduce breaking changes or force rapid adoption of new paradigms, Go's approach is deliberate and incremental. The &lt;code&gt;modernize&lt;/code&gt; analyzer, therefore, isn't a mandate from the Go core team; it's a helpful guide to &lt;strong&gt;optional, yet powerfully beneficial&lt;/strong&gt;, enhancements.&lt;/p&gt;

&lt;p&gt;So, if Go isn't forcing these changes, why should you actively choose to modernize your codebase? The reasons extend beyond mere novelty:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Elevated Readability and Conciseness:&lt;/strong&gt; Many of the suggested modernizations replace verbose, multi-line constructs with single, expressive function calls. This isn't just about saving lines of code; it's about reducing cognitive load. Code that is easier to read at a glance is inherently more maintainable and less prone to misinterpretation, allowing engineers to focus on business logic rather than parsing intricate syntax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adherence to Evolving Idiomatic Go:&lt;/strong&gt; As the language matures, certain patterns emerge as the established "Go way" of solving common problems. By adopting constructs like &lt;code&gt;slices.Sort&lt;/code&gt; or &lt;code&gt;maps.Clone&lt;/code&gt;, your code aligns with these contemporary idioms. This makes your codebase more familiar and approachable to the broader Go community, easing onboarding for new team members and facilitating collaboration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Performance and Efficiency:&lt;/strong&gt; In numerous cases, the new constructs leverage highly optimized Go internals that are more efficient than their older, manually implemented counterparts. For instance, &lt;code&gt;slices.Sort&lt;/code&gt; is often more performant than a custom &lt;code&gt;sort.Slice&lt;/code&gt; implementation due to underlying optimizations. Similarly, &lt;code&gt;fmt.Appendf&lt;/code&gt; can significantly reduce intermediate allocations compared to &lt;code&gt;[]byte(fmt.Sprintf...)&lt;/code&gt;, leading to measurable performance gains in critical paths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Error Surface:&lt;/strong&gt; Utilizing purpose-built, standard library functions like &lt;code&gt;slices.Delete&lt;/code&gt; instead of manual slice index manipulation drastically reduces the likelihood of subtle off-by-one errors or other common pitfalls that can plague complex hand-rolled logic. These functions are rigorously tested and battle-hardened within the Go ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leveraging a Robust Standard Library:&lt;/strong&gt; Go's standard library is a cornerstone of its strength – a treasure trove of well-tested, high-quality, and performant code. &lt;code&gt;modernize&lt;/code&gt; encourages you to lean on these robust building blocks, rather than expending effort reinventing the wheel or maintaining custom implementations that the standard library now provides out-of-the-box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future-Proofing and Developer Experience:&lt;/strong&gt; While backward compatibility is paramount, embracing modern Go constructs positions your codebase to more easily integrate with future advancements and tools. It also signals a commitment to staying current with the language, attracting talent, and fostering a development environment that values continuous improvement and efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In essence, modernizing your Go code isn't about complying with a strict mandate, but about a proactive choice to enhance code quality, improve developer productivity, and leverage the very best the Go language has to offer.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Glimpse into the Modern Go Landscape
&lt;/h2&gt;

&lt;p&gt;Let's dive into some of the compelling transformations &lt;code&gt;modernize&lt;/code&gt; suggests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Goodbye &lt;code&gt;if/else&lt;/code&gt; for &lt;code&gt;min&lt;/code&gt;/&lt;code&gt;max&lt;/code&gt; (Go 1.21+):&lt;/strong&gt; No more verbose conditional assignments for finding the minimum or maximum of two numbers. &lt;code&gt;min(a, b)&lt;/code&gt; and &lt;code&gt;max(a, b)&lt;/code&gt; are your new best friends, offering elegant conciseness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlined Sorting with &lt;code&gt;slices.Sort&lt;/code&gt; (Go 1.21+):&lt;/strong&gt; Tired of writing boilerplate &lt;code&gt;sort.Slice&lt;/code&gt; with an anonymous function? &lt;code&gt;slices.Sort(s)&lt;/code&gt; is a game-changer for common sorting needs, making your sorting code dramatically simpler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Power of &lt;code&gt;any&lt;/code&gt; (Go 1.18+):&lt;/strong&gt; While &lt;code&gt;interface{}&lt;/code&gt; served its purpose, &lt;code&gt;any&lt;/code&gt; is a more semantic and clearer alias, instantly communicating your intent for a value of any type.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Slicing with &lt;code&gt;slices.Clone&lt;/code&gt; and &lt;code&gt;slices.Concat&lt;/code&gt; (Go 1.21+):&lt;/strong&gt; Say goodbye to &lt;code&gt;append([]T(nil), s...)&lt;/code&gt; for cloning or concatenating slices. &lt;code&gt;slices.Clone(s)&lt;/code&gt; and &lt;code&gt;slices.Concat(s1, s2)&lt;/code&gt; offer direct, readable, and often more performant alternatives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern Map Operations (Go 1.21+):&lt;/strong&gt; Manual loops for map updates are often a thing of the past. The &lt;code&gt;maps&lt;/code&gt; package introduces &lt;code&gt;Collect&lt;/code&gt;, &lt;code&gt;Copy&lt;/code&gt;, &lt;code&gt;Clone&lt;/code&gt;, and &lt;code&gt;Insert&lt;/code&gt; functions, simplifying common map manipulations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better String Formatting with &lt;code&gt;fmt.Appendf&lt;/code&gt; (Go 1.19+):&lt;/strong&gt; For efficient byte-based formatting, &lt;code&gt;fmt.Appendf(nil, ...)&lt;/code&gt; is the way to go, potentially reducing allocations compared to &lt;code&gt;[]byte(fmt.Sprintf...)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Contexts with &lt;code&gt;t.Context&lt;/code&gt; (Go 1.24+):&lt;/strong&gt; Testing just got easier. For tests requiring a context, &lt;code&gt;t.Context()&lt;/code&gt; provides a built-in, cancellable context, eliminating the need for manual &lt;code&gt;context.WithCancel&lt;/code&gt; setups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;omitzero&lt;/code&gt; for Structs (Go 1.24+):&lt;/strong&gt; More precise JSON marshaling! &lt;code&gt;omitzero&lt;/code&gt; allows you to omit fields from the JSON output if their value is the zero value for their type, providing finer control than &lt;code&gt;omitempty&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Slice Deletion with &lt;code&gt;slices.Delete&lt;/code&gt; (Go 1.21+):&lt;/strong&gt; Manually manipulating slice indices for deletion can be error-prone. &lt;code&gt;slices.Delete(s, i, i+1)&lt;/code&gt; offers a clear and concise way to remove elements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elegant &lt;code&gt;for range n&lt;/code&gt; Loops (Go 1.22+):&lt;/strong&gt; Iterating a fixed number of times? &lt;code&gt;for i := range n {}&lt;/code&gt; is a more idiomatic and often cleaner alternative to the traditional &lt;code&gt;for i := 0; i &amp;lt; n; i++ {}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient String Splitting with &lt;code&gt;strings.SplitSeq&lt;/code&gt; (Go 1.24+):&lt;/strong&gt; For scenarios where you iterate over parts of a string after splitting, &lt;code&gt;strings.SplitSeq&lt;/code&gt; offers a more efficient approach than creating an entire slice with &lt;code&gt;strings.Split&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to Embrace the Modern Go Era
&lt;/h2&gt;

&lt;p&gt;The best part? Adopting these modernizations is surprisingly easy. The &lt;code&gt;modernize&lt;/code&gt; analyzer comes with a powerful auto-fix capability. You can run it on your codebase with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest &lt;span class="nt"&gt;-test&lt;/span&gt; ./...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will apply all the suggested fixes. Be aware that for complex cases with conflicting fixes, you might need to run it a few times until all changes are cleanly applied. While this command is not an officially supported interface and may change, it provides an invaluable tool for mass modernization.&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Stop DDoS Attacks in in Go with Rate Limiting</title>
      <dc:creator>Rodney Otieno</dc:creator>
      <pubDate>Thu, 28 Nov 2024 06:00:08 +0000</pubDate>
      <link>https://dev.to/rodneyo1/how-to-stop-ddos-attacks-in-go-with-rate-limiting-52m3</link>
      <guid>https://dev.to/rodneyo1/how-to-stop-ddos-attacks-in-go-with-rate-limiting-52m3</guid>
      <description>&lt;p&gt;Rate limiting is one of the most effective techniques to mitigate DDoS attacks. Among its variations, &lt;strong&gt;per-IP rate limiting&lt;/strong&gt; stands out for its targeted approach: it enforces request limits individually for each client, based on their IP address. This prevents any single user from overwhelming the server while maintaining a fair level of access for legitimate users.&lt;/p&gt;

&lt;p&gt;In this article, we’ll cover how per-IP rate limiting works, why it is one of the best strategies to stop DDoS attacks, and how to implement it in Go using the rate package.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Rate Limiting&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Rate limiting is widely used because it balances security and usability. Here’s why it’s a preferred approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Efficient Resource Management:&lt;/strong&gt;
By limiting the number of requests from each client, servers can avoid being overwhelmed, even during an attack.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fairness:&lt;/strong&gt;
Legitimate users can continue to access the server while malicious clients are throttled.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable:&lt;/strong&gt;
Rate limits can be adjusted based on use cases, such as different limits for public APIs versus private services.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt;
Rate limiting mechanisms scale well with modern infrastructure, especially when combined with load balancers or reverse proxies.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How it Compares to Other Techniques&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Firewall Rules:&lt;/strong&gt;
Block traffic at the network level based on predefined rules. While effective for large-scale filtering, it’s less flexible and can block legitimate users during false positives.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Delivery Networks (CDNs):&lt;/strong&gt;
Distribute traffic across multiple servers. While great for reducing the impact of DDoS, CDNs don’t address abusive traffic at the application level.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proof of Work (PoW):&lt;/strong&gt;
Requires clients to solve computational puzzles before accessing the server. Effective but adds latency for legitimate users and can be resource-intensive for clients.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting:&lt;/strong&gt;
Offers fine-grained control, scales well, and doesn’t add significant overhead. It’s often the best choice for protecting application-level endpoints.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Implementation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In per-IP rate limiting, a separate limiter is maintained for each client IP. Here’s how to implement it using the &lt;code&gt;golang.org/x/time/rate&lt;/code&gt; package.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Install the Required Package&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;rate&lt;/code&gt; package is part of Go’s extended modules. Install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get golang.org/x/time/rate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Code the Per-IP Rate Limiter&lt;/strong&gt;
&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;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="s"&gt;"golang.org/x/time/rate"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;       &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mutex&lt;/span&gt;
    &lt;span class="n"&gt;visitors&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;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Limiter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// getVisitor retrieves the rate limiter for a given IP, creating one if it doesn't exist.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getVisitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Limiter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&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;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;visitors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// 1 request/second, burst of 5&lt;/span&gt;
        &lt;span class="n"&gt;visitors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;limiter&lt;/span&gt;

        &lt;span class="c"&gt;// Clean up limiter after 1 minute of inactivity&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="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;Minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;mu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Unlock&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;return&lt;/span&gt; &lt;span class="n"&gt;limiter&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// rateLimitedHandler applies the per-IP rate limit&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;rateLimitedHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&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="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoteAddr&lt;/span&gt;
    &lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getVisitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Too many requests. Please try again later."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusTooManyRequests&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="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Request successful."&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&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;rateLimitedHandler&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;"Starting server on :8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&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;h3&gt;
  
  
  &lt;strong&gt;Explanation&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Visitors Map:&lt;/strong&gt;
Maintains a &lt;code&gt;rate.Limiter&lt;/code&gt; for each IP address. The &lt;code&gt;visitors&lt;/code&gt; map holds these limiters, keyed by IP addresses (&lt;code&gt;r.RemoteAddr&lt;/code&gt;). When a request comes in, the &lt;code&gt;getVisitor&lt;/code&gt; function checks if a limiter already exists for the IP.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limiter Creation:&lt;/strong&gt;
Each limiter allows 1 request per second with a burst of 5.  A a new limiter is created with specific rules (1 request per second with a burst capacity of 5) if one doesn’t exist. The limiter allows some initial burst of requests but enforces a steady rate thereafter.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Cleanup:&lt;/strong&gt;
A goroutine cleans up idle limiters after 1 minute to save memory.To prevent memory growth, the code includes a cleanup mechanism. A goroutine is started whenever a new limiter is created, and it waits for 1 minute of inactivity before removing the corresponding entry from the &lt;code&gt;visitors&lt;/code&gt; map. This ensures that limiters are only kept for active clients.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting Logic:&lt;/strong&gt;
The handler checks if the limiter allows the request.  If the request exceeds the defined limit, it responds with a &lt;code&gt;429 Too Many Requests&lt;/code&gt; error; otherwise, it processes the request. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Per-IP rate limiting in Go is an excellent way to mitigate DDoS attacks at the application level. It provides precise control over traffic, ensuring that legitimate users can access your service while malicious users are effectively throttled.&lt;/p&gt;

&lt;p&gt;This approach efficiently throttles abusive IPs without impacting legitimate users, offering a scalable and memory-efficient solution for mitigating DDoS attacks.&lt;/p&gt;

</description>
      <category>go</category>
      <category>ddos</category>
      <category>cybersecurity</category>
    </item>
  </channel>
</rss>
