<?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"><channel><title><![CDATA[Hossein Margani's Blog]]></title><description><![CDATA[Hossein Margani's Blog]]></description><link>https://margani.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 10:10:55 GMT</lastBuildDate><atom:link href="https://margani.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How I Deployed CoreDNS in My Home Lab Using Podman, Ansible, and systemd]]></title><description><![CDATA[Setting up a proper internal DNS had been on my to-do list for a long time, but I always assumed it would be heavier than it was worth—probably a full VM, lots of manual config, and something I’d be scared to touch once it was “working.” Eventually I...]]></description><link>https://margani.dev/home-lab-coredns-using-podman-ansible</link><guid isPermaLink="true">https://margani.dev/home-lab-coredns-using-podman-ansible</guid><category><![CDATA[Homelab]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 24 Nov 2025 08:00:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763622212974/fa711105-201d-45dd-8423-cdb192cfcb7e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Setting up a proper internal DNS had been on my to-do list for a long time, but I always assumed it would be heavier than it was worth—probably a full VM, lots of manual config, and something I’d be scared to touch once it was “working.” Eventually I decided to try a lighter, more modern approach using Podman and Ansible, and it completely changed how I think about home lab services. CoreDNS turned out to be a perfect fit: small, fast, easy to configure, and ideal for handling a custom internal domain like <code>whosane.local</code> without burning through CPU and RAM on my laptop.</p>
<p>I started by creating a small Ansible project with a simple layout: an inventory, a CoreDNS config (<code>Corefile</code>), a <code>hosts</code> file for local records, and a playbook to glue everything together. The folder looked like this:</p>
<pre><code class="lang-text">infra/
  coredns/
    files/
      Corefile
      hosts
    coredns.yml
    inventory.ini
</code></pre>
<p>My <code>Corefile</code> defines a basic forwarding resolver plus an internal zone:</p>
<pre><code class="lang-text">. {
    forward . 1.1.1.1
    cache 30
}

whosane.local {
    file /etc/coredns/hosts
    reload
}
</code></pre>
<p>The Ansible playbook handles both configuration and the Podman container. First it copies the CoreDNS files to the host, then it runs CoreDNS as a Podman container:</p>
<pre><code class="lang-yaml"><span class="hljs-bullet">-</span> <span class="hljs-attr">hosts:</span> <span class="hljs-string">homelab</span>
  <span class="hljs-attr">gather_facts:</span> <span class="hljs-literal">false</span>
  <span class="hljs-attr">become:</span> <span class="hljs-literal">true</span>

  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Copy</span> <span class="hljs-string">CoreDNS</span> <span class="hljs-string">config</span>
      <span class="hljs-attr">copy:</span>
        <span class="hljs-attr">src:</span> <span class="hljs-string">files/</span>
        <span class="hljs-attr">dest:</span> <span class="hljs-string">/opt/coredns/</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">CoreDNS</span> <span class="hljs-string">container</span>
      <span class="hljs-attr">containers.podman.podman_container:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">coredns</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">coredns/coredns:latest</span>
        <span class="hljs-attr">state:</span> <span class="hljs-string">started</span>
        <span class="hljs-attr">restart_policy:</span> <span class="hljs-string">always</span>
        <span class="hljs-attr">ports:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"53:53/tcp"</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"53:53/udp"</span>
        <span class="hljs-attr">volumes:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">"/opt/coredns:/etc/coredns:Z"</span>
        <span class="hljs-attr">command:</span> [<span class="hljs-string">"-conf"</span>, <span class="hljs-string">"/etc/coredns/Corefile"</span>]
</code></pre>
<p>One thing I really wanted was for the DNS service to survive reboots and behave like a “real” system service. Instead of manually writing unit files, I used Ansible’s Podman integration to generate a systemd unit for the container and enable it automatically:</p>
<pre><code class="lang-yaml">    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Generate</span> <span class="hljs-string">systemd</span> <span class="hljs-string">unit</span> <span class="hljs-string">for</span> <span class="hljs-string">CoreDNS</span>
      <span class="hljs-attr">containers.podman.podman_generate_systemd:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">coredns</span>
        <span class="hljs-attr">dest:</span> <span class="hljs-string">/etc/systemd/system</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Enable</span> <span class="hljs-string">and</span> <span class="hljs-string">start</span> <span class="hljs-string">CoreDNS</span> <span class="hljs-string">systemd</span> <span class="hljs-string">service</span>
      <span class="hljs-attr">systemd:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">container-coredns.service</span>
        <span class="hljs-attr">enabled:</span> <span class="hljs-literal">yes</span>
        <span class="hljs-attr">state:</span> <span class="hljs-string">started</span>
</code></pre>
<p>After running the playbook, CoreDNS comes up as a container, is managed by systemd, and persists across reboots without me having to think about it. Adding new internal services is as simple as editing the <code>hosts</code> file and rerunning the playbook. For a home lab, this combination of Podman, Ansible, CoreDNS, and systemd feels surprisingly close to how modern production infrastructure is built—but compact enough to live happily on a single laptop.</p>
]]></content:encoded></item><item><title><![CDATA[Go Error Handling]]></title><description><![CDATA[Go's error handling is unique and efficient. Errors aren't exceptions that halt execution; instead, functions return an error value alongside their result. This allows for fine-grained control over how errors are handled. Here's a simple example:
fun...]]></description><link>https://margani.dev/go-error-handling</link><guid isPermaLink="true">https://margani.dev/go-error-handling</guid><category><![CDATA[Go Language]]></category><category><![CDATA[error handling]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 24 Mar 2025 07:00:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735278469428/9912a5dd-7a1d-4709-9ad1-e3fa8f503561.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://go.dev/">Go</a>'s error handling is unique and efficient. Errors aren't exceptions that halt execution; instead, functions return an error value alongside their result. This allows for fine-grained control over how errors are handled. Here's a simple example:</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">divide</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">int</span>, error)</span></span> {
    <span class="hljs-keyword">if</span> b == <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>, fmt.Errorf(<span class="hljs-string">"division by zero"</span>)
    }
    <span class="hljs-keyword">return</span> a / b, <span class="hljs-literal">nil</span>
}
</code></pre>
<p>This <code>divide</code> function returns an <code>error</code> if <code>b</code> is zero. The caller must explicitly check for this error. This explicit error checking enhances code clarity and prevents unexpected crashes.</p>
<pre><code class="lang-go">result, err := divide(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>)
<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
    fmt.Println(<span class="hljs-string">"Error:"</span>, err)
} <span class="hljs-keyword">else</span> {
    fmt.Println(<span class="hljs-string">"Result:"</span>, result)
}
</code></pre>
<p>Go's <code>error</code> type is an interface, allowing for flexibility in error representation. <a target="_blank" href="https://gobyexample.com/custom-errors">Custom error types</a> can be created to provide more context or detail. This example demonstrates the use of a custom error:</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> MyError <span class="hljs-keyword">struct</span> {
    Message <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(e *MyError)</span> <span class="hljs-title">Error</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> { <span class="hljs-keyword">return</span> e.Message }

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">myFunction</span><span class="hljs-params">()</span> <span class="hljs-title">error</span></span> {
    <span class="hljs-keyword">return</span> &amp;MyError{Message: <span class="hljs-string">"Something went wrong!"</span>} 
}
</code></pre>
<p>This <code>MyError</code> type provides a structured way of representing specific errors. The <code>Error()</code> method satisfies the <code>error</code> interface requirement, allowing it to be used just like any other error value. The practice of returning errors as function parameters encourages mindful and robust error management practices.</p>
<p>The <code>errors</code> package provides useful functions for working with errors, such as <a target="_blank" href="https://pkg.go.dev/errors#Is"><code>errors.Is</code></a> and <a target="_blank" href="https://pkg.go.dev/errors#As"><code>errors.As</code></a>, facilitating complex error checks without writing verbose conditional statements. A good understanding of error handling enables building secure, robust, and maintainable applications in Go.</p>
]]></content:encoded></item><item><title><![CDATA[Organizing Your Go Applications: A Simple Folder Structure]]></title><description><![CDATA[When building Go applications, especially those with multiple services and models, a well-structured folder organization is crucial for maintainability and scalability. A haphazard arrangement can quickly lead to confusion and difficulty in managing ...]]></description><link>https://margani.dev/organizing-your-go-applications-a-simple-folder-structure</link><guid isPermaLink="true">https://margani.dev/organizing-your-go-applications-a-simple-folder-structure</guid><category><![CDATA[Go Language]]></category><category><![CDATA[Folder Structure]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 17 Mar 2025 07:00:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735290282310/8d6058fe-584d-43b9-a269-d3a94758faf5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When building Go applications, especially those with multiple services and models, a <a target="_blank" href="https://github.com/golang-standards/project-layout">well-structured folder organization</a> is crucial for maintainability and scalability. A haphazard arrangement can quickly lead to confusion and difficulty in managing your codebase as it grows. This post outlines a simple yet effective approach.</p>
<p>The foundation of our structure centers around separating concerns. We'll group related files based on their function, creating distinct folders for services, models, and any other necessary components. This allows for easier navigation and understanding of the code's purpose. Let's assume we're building a simple e-commerce application.</p>
<pre><code class="lang-plaintext">├── cmd
│ └── main.go
├── internal
│ ├── models
│ │ └── product.go
│ ├── services
│ │ └── product_service.go
│ └── utils
│   └── database.go
└── go.mod
</code></pre>
<p>The <code>cmd</code> folder holds the main application entry point (<code>main.go</code>). The <code>internal</code> folder encloses our application's internal packages, ensuring they are not accessible externally. <code>models</code> contains data structures representing our application's domain (e.g., <code>product.go</code>), <code>services</code> contains business logic related to those models (e.g., <code>product_service.go</code>), and <code>utils</code> includes common utility functions (e.g., database interaction in <code>database.go</code>).</p>
<p>This structure promotes modularity. Each service can clearly access and operate on its corresponding models. The <code>utils</code> folder helps to centralize reusable functionality, preventing code duplication and improving consistency. For instance, database interactions can be encapsulated in <code>utils/database.go</code> to ensure all services use the same access methods.</p>
<p>In this e-commerce example, the <code>product_service.go</code> might handle adding, updating, retrieving, and deleting products. It would directly utilize the <code>Product</code> struct defined in <code>models/product.go</code> and the database functions from <code>utils/database.go</code>. This clear separation makes code easier to read, understand, and maintain, fostering collaborative development and seamless scaling of your Go application.</p>
<p>For more advanced scenarios, consider exploring packages like <a target="_blank" href="https://cs.opensource.google/go/x/tools"><code>https://cs.opensource.google/go/x/tools</code></a> for improved code formatting, and further delve into dependency injection patterns for cleaner separation of concerns and better testability. Remember that a consistent and well-defined folder structure is a cornerstone of successful software development.</p>
]]></content:encoded></item><item><title><![CDATA[Bash Loops and Conditionals]]></title><description><![CDATA[Bash, the default shell in many Linux distributions, offers powerful constructs for controlling program flow. This post focuses on two fundamental elements: if statements for conditional execution and for loops for iterative processing. Mastering the...]]></description><link>https://margani.dev/bash-loops-and-conditionals</link><guid isPermaLink="true">https://margani.dev/bash-loops-and-conditionals</guid><category><![CDATA[Bash]]></category><category><![CDATA[for loop]]></category><category><![CDATA[if-else]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 10 Mar 2025 07:00:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735288624279/e9a738cb-bc2f-4bd6-af2b-2a559d021908.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://www.gnu.org/software/bash/">Bash</a>, the default shell in many Linux distributions, offers powerful constructs for controlling program flow. This post focuses on two fundamental elements: <code>if</code> statements for conditional execution and <code>for</code> loops for iterative processing. Mastering these will significantly enhance your shell scripting abilities.</p>
<h2 id="heading-the-if-statement">The <code>if</code> Statement</h2>
<p>The <a target="_blank" href="https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html"><code>if</code></a> statement allows you to execute commands conditionally. Its basic structure involves a test condition followed by one or more commands that are executed if the condition evaluates to true. A simple example might look like this:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

number=10

<span class="hljs-keyword">if</span> [ <span class="hljs-variable">$number</span> -gt 5 ]; <span class="hljs-keyword">then</span>
    <span class="hljs-built_in">echo</span> <span class="hljs-string">"The number is greater than 5"</span>
<span class="hljs-keyword">fi</span>
</code></pre>
<p>This script checks if the variable <code>number</code> is greater than 5. The <code>-gt</code> operator performs the numerical comparison. If true, the message is printed. The <code>fi</code> keyword marks the end of the <code>if</code> block. More complex conditions can be created using <code>elif</code> (else if) and <code>else</code> clauses.</p>
<h2 id="heading-the-for-loop">The <code>for</code> Loop</h2>
<p><a target="_blank" href="https://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html"><code>for</code></a> loops are ideal when you need to execute a block of code multiple times. Bash offers several ways to use <code>for</code> loops, including iterating over a sequence of numbers or a list of words. A common pattern iterates over a set of files:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> *.txt; <span class="hljs-keyword">do</span>
    <span class="hljs-built_in">echo</span> <span class="hljs-string">"Processing file: <span class="hljs-variable">$file</span>"</span>
<span class="hljs-keyword">done</span>
</code></pre>
<p>This script processes all files ending in <code>.txt</code> in the current directory. Each filename is assigned to the variable <code>file</code> in each iteration, and the <code>done</code> keyword marks the end of the loop. Another way to use the for loop is by using an array:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

myArray=(
    <span class="hljs-string">"apple"</span>
    <span class="hljs-string">"banana"</span>
    <span class="hljs-string">"cherry"</span>
)

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-string">"<span class="hljs-variable">${myArray[@]}</span>"</span>; <span class="hljs-keyword">do</span> 
    <span class="hljs-built_in">echo</span> <span class="hljs-string">"item is: <span class="hljs-variable">$i</span>"</span>
<span class="hljs-keyword">done</span>
</code></pre>
<p>Output:</p>
<pre><code class="lang-plaintext">
item is: apple
item is: banana
item is: cherry
</code></pre>
<h2 id="heading-further-reading">Further Reading</h2>
<p>To delve deeper, explore Bash's <a target="_blank" href="https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_03.html"><code>case</code></a> statement for multiple-condition decision-making and the <a target="_blank" href="https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_02.html"><code>while</code></a> and <a target="_blank" href="https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_03.html"><code>until</code></a> loops for conditions that are checked before and after each iteration, respectively. The Bash manual provides comprehensive documentation on these and other control flow structures.</p>
]]></content:encoded></item><item><title><![CDATA[Compiling a Go App with SQLite for Linux on Windows Using Docker]]></title><description><![CDATA[If you're developing a Go application on Windows that uses SQLite and need to compile it for Linux, Docker can be a lifesaver. By leveraging Docker, you can create a consistent build environment that mimics a Linux system, ensuring your application r...]]></description><link>https://margani.dev/compiling-go-app-with-sqlite-for-linux-on-windows-using-docker</link><guid isPermaLink="true">https://margani.dev/compiling-go-app-with-sqlite-for-linux-on-windows-using-docker</guid><category><![CDATA[Go Language]]></category><category><![CDATA[SQLite]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Windows]]></category><category><![CDATA[Cgo]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 03 Mar 2025 07:00:52 GMT</pubDate><content:encoded><![CDATA[<p>If you're developing a Go application on Windows that uses SQLite and need to compile it for Linux, Docker can be a lifesaver. By leveraging Docker, you can create a consistent build environment that mimics a Linux system, ensuring your application runs smoothly on the target platform. Here's how you can do it using a simple <code>docker run</code> command.</p>
<p>The key to this process is the <code>docker run</code> command, which allows you to execute commands inside a Docker container. In this case, we're using the official Go image (<code>golang:latest</code>) to compile our application. The command mounts your current working directory into the container, sets the working directory, and then runs the necessary Go build command. Here's the command in action:</p>
<pre><code class="lang-bash">docker run --rm -v <span class="hljs-variable">${pwd}</span>:/app -w /app golang:latest sh -c <span class="hljs-string">"GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -o dist/myapp_linux"</span>
</code></pre>
<p>Let's break this down. The <code>--rm</code> flag ensures the container is removed after the build process, keeping your system clean. The <code>-v ${pwd}:/app</code> flag mounts your current directory (retrieved using <code>${pwd}</code>) to the <code>/app</code> directory inside the container. The <code>-w /app</code> flag sets the working directory inside the container to <code>/app</code>, so the build command runs in the correct location.</p>
<p>The <code>sh -c</code> part allows you to pass a shell command to the container. Here, we're setting a few environment variables: <code>GOOS=linux</code> tells Go to compile for Linux, <code>GOARCH=amd64</code> specifies the architecture, and <code>CGO_ENABLED=1</code> enables CGO, which is necessary for SQLite. Finally, <code>go build -o dist/myapp_linux</code> compiles the application and outputs it to the <code>dist</code> directory with the name <code>myapp_linux</code>.</p>
<p>Why is <code>CGO_ENABLED=1</code> important? SQLite is a C library, and the <code>go-sqlite3</code> package <a target="_blank" href="https://github.com/mattn/go-sqlite3#installation">relies</a> on CGO to interact with it. Without enabling CGO, the build process would fail because the Go compiler wouldn't be able to link the SQLite library. This is a crucial step when working with SQLite in Go, especially when cross-compiling for different platforms.</p>
<p>By using this Docker command, you can easily compile your Go application for Linux on a Windows machine without worrying about setting up a cross-compilation environment. It's a clean, efficient way to ensure your application is ready for deployment on Linux servers.</p>
]]></content:encoded></item><item><title><![CDATA[Bicep Templates: Advantages Over Azure ARM Templates]]></title><description><![CDATA[Azure Resource Manager (ARM) templates have long been the standard for infrastructure as code (IaC) in Azure. However, Bicep, a newer domain-specific language (DSL), offers several key advantages that simplify the process of deploying and managing Az...]]></description><link>https://margani.dev/azure-bicep-vs-arm-templates</link><guid isPermaLink="true">https://margani.dev/azure-bicep-vs-arm-templates</guid><category><![CDATA[Azure]]></category><category><![CDATA[azure-bicep]]></category><category><![CDATA[arm template]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 24 Feb 2025 07:00:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735285496198/e418d3fd-c173-431e-8f96-3fa254fdc960.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Azure Resource Manager (ARM) templates have long been the standard for infrastructure as code (IaC) in Azure. However, Bicep, a newer domain-specific language (DSL), offers several key advantages that simplify the process of deploying and managing Azure resources.</p>
<p>One major advantage of Bicep is its improved readability and writability. Unlike ARM templates, which use a JSON structure that can become complex and difficult to read, Bicep utilizes a more concise and intuitive syntax. This makes Bicep templates easier to write, understand, and maintain, particularly for large deployments.</p>
<p>Another key benefit is the improved developer experience. Bicep offers features like auto-completion, linting, and built-in functions that streamline the development process and reduce the risk of errors. This increased developer productivity leads to faster and more reliable deployments.</p>
<p>Consider the following example: deploying a virtual network and subnet. In ARM, this would require a nested JSON structure, while in Bicep, the same task can be accomplished with less verbose code. This difference becomes even more significant when deploying complex deployments involving multiple dependent resources.</p>
<p>Let's illustrate with a simple example. Deploying a simple storage account in ARM requires extensive JSON nesting, whereas in Bicep, the structure is much cleaner:</p>
<pre><code class="lang-plaintext">param location string = resourceGroup().location
param storageAccountName string

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = {
  name: storageAccountName
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}
</code></pre>
<p>Bicep's improved syntax and enhanced developer experience make it a compelling alternative to ARM templates for infrastructure-as-code deployments in Azure. Its conciseness and readability improve maintainability and reduce the likelihood of errors, ultimately leading to more efficient and reliable deployments.</p>
<p>For further reading and more advanced Bicep examples, refer to the official Microsoft documentation on Bicep: <a target="_blank" href="https://learn.microsoft.com/en-us/azure/bicep/">https://learn.microsoft.com/en-us/azure/bicep/</a></p>
]]></content:encoded></item><item><title><![CDATA[Sending Telegram Messages/Photos in NodeJS using Fetch]]></title><description><![CDATA[This blog post provides a basic guide on how to send Telegram messages and photos from a Node.js application using the node-fetch library. We'll focus on a simple, straightforward approach, perfect for beginners getting started with Telegram bot deve...]]></description><link>https://margani.dev/sending-telegram-messages-using-nodejs-fetch</link><guid isPermaLink="true">https://margani.dev/sending-telegram-messages-using-nodejs-fetch</guid><category><![CDATA[telegram]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[fetch API]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 17 Feb 2025 07:00:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735284489386/032e48db-aae4-4965-a3ab-8aab0dc0e3a0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post provides a basic guide on how to send <a target="_blank" href="https://telegram.org">Telegram</a> messages and photos from a Node.js application using the <code>node-fetch</code> library. We'll focus on a simple, straightforward approach, perfect for beginners getting started with <a target="_blank" href="https://core.telegram.org/bots/api#available-methods">Telegram bot development</a>.</p>
<p>First, you'll need to install the <code>node-fetch</code> library: <code>npm install node-fetch</code>. Then, you will need a Telegram Bot token, which you can obtain from <a target="_blank" href="https://telegram.me/BotFather">BotFather</a> on Telegram. This token will be used to authenticate your bot's requests to the Telegram API.</p>
<p>Here's an example of sending a simple text message:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fetch = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node-fetch'</span>);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params">chatId, text, botToken</span>) </span>{
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`https://api.telegram.org/bot<span class="hljs-subst">${botToken}</span>/sendMessage`</span>, {
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
        },
        <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">chat_id</span>: chatId, <span class="hljs-attr">text</span>: text })
    });
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
    <span class="hljs-built_in">console</span>.log(data);
}

<span class="hljs-comment">// Example usage:</span>
<span class="hljs-keyword">const</span> chatId = <span class="hljs-string">'-123456789'</span>; <span class="hljs-comment">// Replace with your chat ID</span>
<span class="hljs-keyword">const</span> botToken = <span class="hljs-string">'YOUR_BOT_TOKEN'</span>; <span class="hljs-comment">// Replace with your bot token</span>
<span class="hljs-keyword">const</span> message = <span class="hljs-string">'Hello from Node.js!'</span>;
sendMessage(chatId, message, botToken);
</code></pre>
<p>Sending photos requires a slightly different approach. You'll need to send a multipart/form-data request containing the photo's data:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ... other code ...</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendPhoto</span>(<span class="hljs-params">chatId, photoPath, botToken</span>) </span>{
    <span class="hljs-keyword">const</span> formData = <span class="hljs-keyword">new</span> FormData();
    formData.append(<span class="hljs-string">'chat_id'</span>, chatId);
    formData.append(<span class="hljs-string">'photo'</span>, fs.createReadStream(photoPath));
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`https://api.telegram.org/bot<span class="hljs-subst">${botToken}</span>/sendPhoto`</span>, {
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">body</span>: formData
    });
<span class="hljs-comment">// ... handling the response ...</span>
}
</code></pre>
<p>This functionality can be used in various applications, such as creating chatbots for customer service, automated alerts, or personal task management systems.</p>
<p>For more advanced features and detailed information about the Telegram Bot API, refer to the <a target="_blank" href="https://core.telegram.org/bots/api#available-methods">official Telegram Bot API documentation</a>. You may also want to consider using libraries built on top of the fetch API for more robust error handling and other advanced features.</p>
]]></content:encoded></item><item><title><![CDATA[Using chromedp in Go]]></title><description><![CDATA[chromedp is a powerful and lightweight library for controlling headless Chrome or Chromium instances using the CDP (Chrome DevTools Protocol) from within Go applications. It offers a clean, idiomatic Go API for automating browser interactions, making...]]></description><link>https://margani.dev/using-chromedp-in-go</link><guid isPermaLink="true">https://margani.dev/using-chromedp-in-go</guid><category><![CDATA[chromedp]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[browser automation]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 10 Feb 2025 07:00:50 GMT</pubDate><content:encoded><![CDATA[<p><a target="_blank" href="https://github.com/chromedp/chromedp">chromedp</a> is a powerful and lightweight library for controlling headless Chrome or Chromium instances using the CDP (Chrome DevTools Protocol) from within Go applications. It offers a clean, idiomatic Go API for automating browser interactions, making it ideal for tasks like web scraping, testing, and generating screenshots.</p>
<h2 id="heading-getting-started">Getting Started</h2>
<p>To begin, you'll need to install the chromedp package. You can use Go modules for this:</p>
<pre><code class="lang-bash">go get github.com/chromedp/chromedp
</code></pre>
<p>Next, let's explore a basic example to demonstrate the core functionality. The following code snippet demonstrates how to navigate to a URL and get the page title:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"context"</span>
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"log"</span>

    <span class="hljs-string">"github.com/chromedp/chromedp"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    opts := <span class="hljs-built_in">append</span>(chromedp.DefaultOptions(), chromedp.DisableGPU)
    ctx, cancel := chromedp.NewContext(context.Background(), opts...)
    <span class="hljs-keyword">defer</span> cancel()

    <span class="hljs-keyword">var</span> title <span class="hljs-keyword">string</span>
    err := chromedp.Run(ctx, 
        chromedp.Navigate(<span class="hljs-string">`https://www.example.com`</span>),
        chromedp.Text(<span class="hljs-string">`body &gt; title`</span>, &amp;title, chromedp.ByQuery),
    )

    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        log.Fatal(err)
    }

    fmt.Printf(<span class="hljs-string">"Title: %s\n"</span>, title)
}
</code></pre>
<p>This is a simple example of opening a new browser, navigating to a page, selecting an element, and extracting text from the page. chromedp offers advanced features such as handling user interactions, managing cookies, and taking screenshots. Further exploration of this example shows a more complex scenario.</p>
<h2 id="heading-practical-application">Practical Application</h2>
<p>A common use case for chromedp is web scraping. By automating browser actions, you can efficiently extract data from websites that are difficult or impossible to scrape using simple HTTP requests. For instance, websites with JavaScript-rendered content or those using dynamic loading techniques are ideal candidates for chromedp.</p>
<h2 id="heading-further-reading">Further Reading</h2>
<p>The <a target="_blank" href="https://pkg.go.dev/github.com/chromedp/chromedp">official chromedp repository on GitHub</a> provides comprehensive documentation, tutorials, and examples to help you master this powerful library. The <a target="_blank" href="https://github.com/chromedp/chromedp#about-chromedp">project's README</a> contains a wealth of information to enhance your understanding and allow you to tackle more advanced use cases.</p>
]]></content:encoded></item><item><title><![CDATA[Using GORM with SQLite]]></title><description><![CDATA[When it comes to working with databases in Go, GORM is one of the most popular ORM (Object-Relational Mapping) libraries. It simplifies database interactions by allowing you to work with Go structs instead of writing raw SQL queries. SQLite, on the o...]]></description><link>https://margani.dev/using-gorm-with-sqlite</link><guid isPermaLink="true">https://margani.dev/using-gorm-with-sqlite</guid><category><![CDATA[Go Language]]></category><category><![CDATA[gorm]]></category><category><![CDATA[SQLite]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 03 Feb 2025 07:00:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735283259689/78834334-638f-442e-9073-92ca4d1e882e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When it comes to working with databases in <a target="_blank" href="https://go.dev/">Go</a>, <a target="_blank" href="https://gorm.io/">GORM</a> is one of the most popular ORM (Object-Relational Mapping) libraries. It simplifies database interactions by allowing you to work with Go structs instead of writing raw SQL queries. <a target="_blank" href="https://www.sqlite.org/">SQLite</a>, on the other hand, is a lightweight, file-based database that’s perfect for small projects or prototyping. Combining GORM with SQLite can make your development process smoother and faster.</p>
<p>To get started, you’ll need to install GORM and the SQLite driver. You can do this using Go modules. Run the following command in your terminal:</p>
<pre><code class="lang-bash">go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
</code></pre>
<p>Once the packages are installed, you can start using GORM with SQLite. First, import the necessary packages and define a model. A model in GORM is a Go struct that represents a table in the database. Here’s an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"gorm.io/driver/sqlite"</span>
    <span class="hljs-string">"gorm.io/gorm"</span>
)

<span class="hljs-keyword">type</span> User <span class="hljs-keyword">struct</span> {
    ID   <span class="hljs-keyword">uint</span>
    Name <span class="hljs-keyword">string</span>
    Age  <span class="hljs-keyword">int</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    db, err := gorm.Open(sqlite.Open(<span class="hljs-string">"test.db"</span>), &amp;gorm.Config{})
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        <span class="hljs-built_in">panic</span>(<span class="hljs-string">"failed to connect database"</span>)
    }

    db.AutoMigrate(&amp;User{})
}
</code></pre>
<p>In this example, we define a <code>User</code> struct and use <code>db.AutoMigrate</code> to automatically create the corresponding table in the SQLite database. The database file, <code>test.db</code>, will be created in the same directory as your Go program.</p>
<p>Once your database and table are set up, you can start performing CRUD (Create, Read, Update, Delete) operations. Here’s how you can insert a new record:</p>
<pre><code class="lang-go">user := User{Name: <span class="hljs-string">"John"</span>, Age: <span class="hljs-number">30</span>}
db.Create(&amp;user)
</code></pre>
<p>To query the database, you can use GORM’s methods like <code>First</code>, <code>Find</code>, and <code>Where</code>. For example, to retrieve the first user with the name "John":</p>
<pre><code class="lang-go"><span class="hljs-keyword">var</span> result User
db.First(&amp;result, <span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"John"</span>)
</code></pre>
<p>Updating and deleting records is just as straightforward. To update a user’s age:</p>
<pre><code class="lang-go">db.Model(&amp;User{}).Where(<span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"John"</span>).Update(<span class="hljs-string">"age"</span>, <span class="hljs-number">31</span>)
</code></pre>
<p>And to delete a user:</p>
<pre><code class="lang-go">db.Delete(&amp;User{}, <span class="hljs-string">"name = ?"</span>, <span class="hljs-string">"John"</span>)
</code></pre>
<p>To fetch a user by their ID using GORM, you can use the <code>First</code> method. This method allows you to query the database and retrieve the first record that matches the given conditions. Here’s how you can get a user by their ID:</p>
<pre><code class="lang-go"><span class="hljs-comment">// Define a variable to hold the user record</span>
record := &amp;User{ID: <span class="hljs-number">10</span>}

<span class="hljs-comment">// Query the database for the user with ID 10</span>
db.First(record)

<span class="hljs-comment">// Check if the record was found</span>
<span class="hljs-keyword">if</span> record.ID != <span class="hljs-number">0</span> {
    fmt.Printf(<span class="hljs-string">"User found: %+v\n"</span>, record)
} <span class="hljs-keyword">else</span> {
    fmt.Println(<span class="hljs-string">"User not found"</span>)
}
</code></pre>
<p>In this example, <code>record</code> is initialized with the ID of the user you want to retrieve. When <code>db.First(record)</code> is called, GORM will query the database for a user with the specified ID. If the user is found, the <code>record</code> variable will be populated with the user’s data. If no user is found, the <code>ID</code> field will remain <code>0</code>, which you can use to check if the record exists.</p>
<p>This approach is clean and concise, leveraging GORM’s ability to work directly with structs. It’s a great way to fetch specific records without writing complex queries.</p>
<p>GORM’s simplicity and SQLite’s lightweight nature make them a great combination for small-scale applications or when you need a quick and easy database solution. With just a few lines of code, you can set up your database, define models, and perform CRUD operations without worrying about the underlying SQL.</p>
]]></content:encoded></item><item><title><![CDATA[Git Rebase vs. Git Merge: A Concise Guide]]></title><description><![CDATA[Git, the ubiquitous version control system, offers two primary ways to integrate changes from different branches: git merge and git rebase. Both achieve the same outcome—combining code—but through different processes. Understanding these differences ...]]></description><link>https://margani.dev/git-rebase-vs-git-merge-a-concise-guide</link><guid isPermaLink="true">https://margani.dev/git-rebase-vs-git-merge-a-concise-guide</guid><category><![CDATA[Git]]></category><category><![CDATA[git rebase]]></category><category><![CDATA[git merge]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 27 Jan 2025 07:00:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735282600825/cc5901ce-858a-44c4-9a23-d8086a242ca7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Git, the ubiquitous version control system, offers two primary ways to integrate changes from different branches: <code>git merge</code> and <code>git rebase</code>. Both achieve the same outcome—combining code—but through different processes. Understanding these differences is key to effective collaboration.</p>
<p><a target="_blank" href="https://git-scm.com/docs/git-merge"><code>git merge</code></a> creates a new merge commit that combines the histories of two branches. This preserves the complete history of both branches, providing a comprehensive view of development. While simple, the resulting history can become complex in projects with frequent merging. Here's an example:</p>
<pre><code class="lang-bash">git checkout main
git merge feature-branch
</code></pre>
<p><a target="_blank" href="https://git-scm.com/docs/git-rebase"><code>git rebase</code></a>, on the other hand, rewrites the project history by applying the commits from one branch onto another linearly. This results in a cleaner, more streamlined history, making it easier to follow the progression of changes. However, rewriting history is powerful but potentially disruptive, especially in collaborative settings; it's essential to use it with caution on shared branches.</p>
<pre><code class="lang-bash">git checkout feature-branch
git rebase main
git checkout main
git merge feature-branch
</code></pre>
<p>Consider a scenario where two developers work on separate features concurrently. <code>git merge</code> maintains both individual feature branches, demonstrating how these features developed independently, while <code>git rebase</code> integrates changes chronologically. The choice depends on prioritization; merging for clarity of changes or rebasing for a cleaner, linear history.</p>
<p>For more detailed information on rebasing and merging, use the <a target="_blank" href="https://git-scm.com/docs">official Git documentation</a>. Understanding the nuances of these commands is critical for every software developer.</p>
]]></content:encoded></item><item><title><![CDATA[Asynchronous Reduce in JavaScript]]></title><description><![CDATA[The reduce function is a powerful tool for processing arrays, but it can become tricky when dealing with asynchronous operations. In JavaScript, we can leverage async/await and promises to handle these operations gracefully. Let's imagine we're fetch...]]></description><link>https://margani.dev/asynchronous-reduce-in-javascript</link><guid isPermaLink="true">https://margani.dev/asynchronous-reduce-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[reduce method]]></category><category><![CDATA[asynchronous]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 20 Jan 2025 07:00:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735279364771/f722b3f7-7993-4e83-975e-88c7a68428af.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The reduce function is a powerful tool for processing arrays, but it can become tricky when dealing with asynchronous operations. In JavaScript, we can leverage async/await and promises to handle these operations gracefully. Let's imagine we're fetching data from multiple endpoints, each represented as a promise. To process them all using reduce, we'll need to handle each promise within the reduce callback:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">asyncReduceExample</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> promises = [
        fetch(<span class="hljs-string">'https://api.example.com/data1'</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json()),
        fetch(<span class="hljs-string">'https://api.example.com/data2'</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json()),
        fetch(<span class="hljs-string">'https://api.example.com/data3'</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json()),
    ];

    <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> promises.reduce(<span class="hljs-keyword">async</span> (accumulator, currentPromise) =&gt; {
        <span class="hljs-keyword">const</span> acc = <span class="hljs-keyword">await</span> accumulator;
        <span class="hljs-keyword">const</span> currentValue = <span class="hljs-keyword">await</span> currentPromise;
        <span class="hljs-keyword">return</span> [...acc, currentValue];
    }, <span class="hljs-built_in">Promise</span>.resolve([]));

    <span class="hljs-built_in">console</span>.log(result);
}
</code></pre>
<p>Notice the use of async in the reduce callback, allowing us to use await to resolve each Promise before proceeding. The initial value of the accumulator is set using Promise.resolve([]) to ensure it's a promise that resolves to an empty array. This ensures that the reduce function handles the asynchronous operations correctly by resolving the accumulator before it is used in subsequent iterations. Each Promise is fetched in sequence, and the results are aggregated in the result array which is logged to the console.</p>
<p>For more complex scenarios, error handling is crucial. Here's a revised example that handles potential errors during the asynchronous operations:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">asyncReduceWithErrorHandling</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> promises = [
        fetch(<span class="hljs-string">'https://api.example.com/data1'</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json()),
        fetch(<span class="hljs-string">'https://api.example.com/data2'</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json()),
        fetch(<span class="hljs-string">'https://api.example.com/data3'</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json()),
    ];

    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> promises.reduce(<span class="hljs-keyword">async</span> (accumulator, currentPromise) =&gt; {
            <span class="hljs-keyword">const</span> acc = <span class="hljs-keyword">await</span> accumulator;
            <span class="hljs-keyword">const</span> currentValue = <span class="hljs-keyword">await</span> currentPromise;
            <span class="hljs-keyword">return</span> [...acc, currentValue];
        }, <span class="hljs-built_in">Promise</span>.resolve([]));
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Success:'</span>, result);
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error:'</span>, error);
    }
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Using reduce in JavaScript]]></title><description><![CDATA[The reduce function is a powerful tool for processing arrays in JavaScript and TypeScript. It allows you to iterate over an array and accumulate a single value from the elements. Let's explore how it works with some examples.
const numbers = [1, 2, 3...]]></description><link>https://margani.dev/using-reduce-in-javascript</link><guid isPermaLink="true">https://margani.dev/using-reduce-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[reduce method]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 13 Jan 2025 07:00:28 GMT</pubDate><content:encoded><![CDATA[<p>The <code>reduce</code> function is a powerful tool for processing arrays in JavaScript and TypeScript. It allows you to iterate over an array and accumulate a single value from the elements. Let's explore how it works with some examples.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];
<span class="hljs-keyword">const</span> sum = numbers.reduce(<span class="hljs-function">(<span class="hljs-params">accumulator, currentValue</span>) =&gt;</span> accumulator + currentValue, <span class="hljs-number">0</span>);
<span class="hljs-built_in">console</span>.log(sum); <span class="hljs-comment">// Output: 15</span>
</code></pre>
<p>In this example, <code>reduce</code> takes two arguments: a callback function and an initial value (0 in this case). The callback function takes two parameters: <code>accumulator</code> (which starts at 0) and <code>currentValue</code> (each number in the array). The callback function's return value is assigned to the <code>accumulator</code> for the next iteration, building up the final sum.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> Person {
    name: <span class="hljs-built_in">string</span>;
    age: <span class="hljs-built_in">number</span>;
}

<span class="hljs-keyword">const</span> people: Person[] = [
    { name: <span class="hljs-string">'Alice'</span>, age: <span class="hljs-number">30</span> },
    { name: <span class="hljs-string">'Bob'</span>, age: <span class="hljs-number">25</span> },
    { name: <span class="hljs-string">'Charlie'</span>, age: <span class="hljs-number">35</span> },
];

<span class="hljs-keyword">const</span> totalAge = people.reduce(<span class="hljs-function">(<span class="hljs-params">acc, person</span>) =&gt;</span> acc + person.age, <span class="hljs-number">0</span>);
<span class="hljs-built_in">console</span>.log(totalAge); <span class="hljs-comment">// Output: 90</span>
</code></pre>
<p>Here, we're using <code>reduce</code> to calculate the total age of all people in the array. The <code>accumulator</code> starts at 0 and each person's age is added to it in each iteration.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> words = [<span class="hljs-string">'hello'</span>, <span class="hljs-string">'world'</span>, <span class="hljs-string">'typescript'</span>];
<span class="hljs-keyword">const</span> concatenatedString = words.reduce(<span class="hljs-function">(<span class="hljs-params">acc, word</span>) =&gt;</span> acc + <span class="hljs-string">' '</span> + word, <span class="hljs-string">''</span>);
<span class="hljs-built_in">console</span>.log(concatenatedString); <span class="hljs-comment">// Output: 'hello world typescript'</span>
</code></pre>
<p>This shows how <code>reduce</code> can be used to concatenate strings. The initial value is an empty string, and each word is appended to it during the iterations.</p>
]]></content:encoded></item><item><title><![CDATA[Modular Infrastructure with Pulumi and C#]]></title><description><![CDATA[In the ever-evolving world of cloud infrastructure, designing modular and reusable components is key to building scalable and maintainable solutions. Pulumi, a modern Infrastructure as Code (IaC) tool, supports multiple languages, but this post will ...]]></description><link>https://margani.dev/modular-infrastructure-with-pulumi-and-csharp</link><guid isPermaLink="true">https://margani.dev/modular-infrastructure-with-pulumi-and-csharp</guid><category><![CDATA[Pulumi]]></category><category><![CDATA[C#]]></category><category><![CDATA[#IaC]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 06 Jan 2025 07:00:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735926307228/10513a25-39a1-4b7d-b1e2-7595941ae9ea.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the ever-evolving world of cloud infrastructure, designing modular and reusable components is key to building scalable and maintainable solutions. <a target="_blank" href="https://www.pulumi.com/">Pulumi</a>, a modern Infrastructure as Code (IaC) tool, supports multiple languages, but this post will focus on using Pulumi with C#. By leveraging the flexibility of NuGet libraries, you can create, share, and reuse common infrastructure modules across projects, dramatically improving development speed and consistency.</p>
<h4 id="heading-why-modular-infrastructure-matters">Why Modular Infrastructure Matters</h4>
<p>Modular infrastructure design focuses on breaking down large, monolithic configurations into smaller, reusable units. This approach simplifies maintenance and enables teams to rapidly adapt to changing requirements. With Pulumi and C#, you can encapsulate common patterns—such as VNet configurations, Kubernetes clusters, or storage setups—into self-contained modules. These modules can then be packaged as NuGet libraries, making them easily shareable across teams or projects. For instance, a team might create a "StandardVNet" NuGet package that provisions a virtual network with predefined subnets and security rules, allowing other teams to consume it without reinventing the wheel.</p>
<h4 id="heading-building-a-pulumi-module-in-c">Building a Pulumi Module in C</h4>
<p>Creating a reusable module in Pulumi involves defining infrastructure components in a structured manner. Consider the example below, where we encapsulate the provisioning of an Azure Storage Account as a reusable component:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Pulumi;
<span class="hljs-keyword">using</span> Pulumi.AzureNative.Storage;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">StorageAccountModule</span> : <span class="hljs-title">ComponentResource</span>
{
    <span class="hljs-keyword">public</span> Output&lt;<span class="hljs-keyword">string</span>&gt; StorageAccountName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">private</span> <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">StorageAccountModule</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> name, ComponentResourceOptions? options = <span class="hljs-literal">null</span></span>) : <span class="hljs-title">base</span>(<span class="hljs-params"><span class="hljs-string">"custom:module:StorageAccountModule"</span>, name, options</span>)</span>
    {
        <span class="hljs-keyword">var</span> storageAccount = <span class="hljs-keyword">new</span> StorageAccount(<span class="hljs-string">$"<span class="hljs-subst">{name}</span>-sa"</span>, <span class="hljs-keyword">new</span> StorageAccountArgs
        {
            ResourceGroupName = <span class="hljs-string">"my-resource-group"</span>,
            Location = <span class="hljs-string">"WestEurope"</span>,
            Sku = <span class="hljs-keyword">new</span> SkuArgs { Name = SkuName.Standard_LRS },
            Kind = Kind.StorageV2
        });

        StorageAccountName = storageAccount.Name;
        <span class="hljs-keyword">this</span>.RegisterOutputs(<span class="hljs-keyword">new</span> { StorageAccountName });
    }
}
</code></pre>
<p>This module can then be used in any Pulumi stack by simply referencing it:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> storageAccount = <span class="hljs-keyword">new</span> StorageAccountModule(<span class="hljs-string">"appstorage"</span>);
</code></pre>
<h4 id="heading-publishing-as-a-nuget-library">Publishing as a NuGet Library</h4>
<p>Once you’ve created a module, you can package it as a NuGet library for reuse. Begin by structuring your project with appropriate metadata in the <code>.csproj</code> file. Then, use the <code>dotnet pack</code> command to create the NuGet package. Hosting the package on a private NuGet feed or a public repository like <a target="_blank" href="http://nuget.org">nuget.org</a> allows other teams to integrate it into their projects with minimal effort. Here’s an example of how to add the NuGet package:</p>
<pre><code class="lang-bash">&gt; dotnet add package CustomPulumiModules.StorageAccount --version 1.0.0
</code></pre>
<p>By adopting this approach, organizations can build a repository of standardized modules, ensuring consistency and reducing duplication.</p>
<h4 id="heading-best-practices-for-modular-design">Best Practices for Modular Design</h4>
<p>While modularization simplifies infrastructure management, following best practices is crucial to maximize its benefits. First, maintain clear documentation for each module, outlining inputs, outputs, and intended use cases. Second, implement rigorous versioning to ensure backward compatibility and minimize disruptions. Third, adopt automated testing pipelines to validate modules against predefined scenarios. Finally, encourage collaboration across teams to contribute to and improve shared libraries, fostering a culture of reusability and innovation.</p>
<p>With Pulumi and C#, coupled with NuGet’s distribution model, the possibilities for modular infrastructure design are vast. By investing in reusable modules, organizations can enhance productivity, ensure consistency, and position themselves for long-term success in cloud operations.</p>
]]></content:encoded></item><item><title><![CDATA[Using Pulumi’s Apply Method]]></title><description><![CDATA[This blog post provides a concise guide on leveraging Pulumi's Apply method within the context of Azure infrastructure and C#. Pulumi's Apply method is a powerful tool for performing actions after a resource has been provisioned, allowing for dynamic...]]></description><link>https://margani.dev/pulumi-apply</link><guid isPermaLink="true">https://margani.dev/pulumi-apply</guid><category><![CDATA[pulumi apply]]></category><category><![CDATA[Pulumi]]></category><category><![CDATA[Azure]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Mon, 30 Dec 2024 07:00:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735282127178/1b5fb3fd-1397-469c-bf54-909f6a59bee2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This blog post provides a concise guide on leveraging <a target="_blank" href="https://www.pulumi.com/">Pulumi</a>'s <code>Apply</code> method within the context of Azure infrastructure and C#. Pulumi's <code>Apply</code> method is a powerful tool for performing actions after a resource has been provisioned, allowing for dynamic configuration and post-deployment tasks. We'll illustrate this with clear examples.</p>
<p>The <code>Apply</code> method allows you to interact with resources after Pulumi has created them. This enables you to execute custom logic based on the resource's properties. A common use case is to retrieve resource IDs or connection strings, which are usually available only after deployment completes. To make use of <code>Apply</code>, ensure you have the necessary Azure and Pulumi packages installed in your project. You might need to set up an Azure service principal to authenticate.</p>
<p>Let's consider a scenario where we deploy a storage account and then retrieve its connection string using <code>Apply</code>. Here's a snippet of C# code that demonstrates this:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> Pulumi;
<span class="hljs-keyword">using</span> Pulumi.AzureNative.Resources;
<span class="hljs-keyword">using</span> Pulumi.AzureNative.Storage;
<span class="hljs-keyword">using</span> Pulumi.AzureNative.Storage.Inputs;
<span class="hljs-keyword">using</span> System.Threading.Tasks;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyStack</span> : <span class="hljs-title">Stack</span>
{
    [<span class="hljs-meta">Output</span>]
    <span class="hljs-keyword">public</span> Output&lt;<span class="hljs-keyword">string</span>&gt; ConnectionString { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">private</span> <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyStack</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">var</span> resourceGroup = CreateResourceGroup();
        <span class="hljs-keyword">var</span> storageAccount = CreateStorageAccount(resourceGroup);
        <span class="hljs-keyword">this</span>.ConnectionString = GetStorageAccountConnectionString(resourceGroup.Name, storageAccount.Name);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> ResourceGroup <span class="hljs-title">CreateResourceGroup</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ResourceGroup(<span class="hljs-string">"resourceGroup"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> StorageAccount <span class="hljs-title">CreateStorageAccount</span>(<span class="hljs-params">ResourceGroup resourceGroup</span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> StorageAccount(<span class="hljs-string">"mystorage"</span>, <span class="hljs-keyword">new</span> StorageAccountArgs
        {
            ResourceGroupName = resourceGroup.Name,
            AccountName = <span class="hljs-string">"myaccount"</span>,
            Sku = <span class="hljs-keyword">new</span> SkuArgs { Name = SkuName.Premium_LRS }
        });
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Output&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">GetStorageAccountConnectionString</span>(<span class="hljs-params">Output&lt;<span class="hljs-keyword">string</span>&gt; resourceGroupName, Output&lt;<span class="hljs-keyword">string</span>&gt; accountName</span>)</span>
    {
        <span class="hljs-keyword">return</span> Output.Tuple(resourceGroupName, accountName).Apply(names =&gt;
        {
            <span class="hljs-keyword">var</span> (rgName, accName) = names;
            <span class="hljs-keyword">return</span> GetStorageAccountPrimaryKey(rgName, accName).Apply(key =&gt;
                <span class="hljs-string">$"DefaultEndpointsProtocol=https;AccountName=<span class="hljs-subst">{accName}</span>;AccountKey=<span class="hljs-subst">{key}</span>;EndpointSuffix=core.windows.net"</span>);
        });
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task&lt;<span class="hljs-keyword">string</span>&gt; <span class="hljs-title">GetStorageAccountPrimaryKey</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> resourceGroupName, <span class="hljs-keyword">string</span> accountName</span>)</span>
    {
        <span class="hljs-keyword">var</span> accountKeys = <span class="hljs-keyword">await</span> ListStorageAccountKeys.InvokeAsync(<span class="hljs-keyword">new</span> ListStorageAccountKeysArgs
        {
            ResourceGroupName = resourceGroupName,
            AccountName = accountName
        });
        <span class="hljs-keyword">return</span> accountKeys.Keys[<span class="hljs-number">0</span>].Value;
    }
}
</code></pre>
<p>In this example, I started by creating a Resource Group and a Storage Account using Pulumi's Azure Native provider.</p>
<p>To securely retrieve the primary key, I used the <code>ListStorageAccountKeys</code> function, which is wrapped in an asynchronous method.</p>
<p>The <code>Apply</code> method was then used to combine the Resource Group name and Storage Account name, passing them to the key retrieval function. Once the key was obtained, I constructed a connection string in the format required by Azure.</p>
<p>This approach not only ensures that sensitive information like the primary key is handled securely but also demonstrates how Pulumi's <code>Apply</code> method can elegantly manage dependencies and transform outputs in a clean, readable way. By breaking the code into smaller, single-responsibility methods, the solution becomes more maintainable and easier to extend for future use cases.</p>
<p>Practical applications extend beyond connection strings. Imagine a scenario where you need to register a custom resource provider or configure service endpoints post-deployment. The <code>Apply</code> method provides the flexibility to handle such scenarios, facilitating a more tailored and dynamic infrastructure deployment. By combining the power of <code>Apply</code> with Pulumi's infrastructure-as-code approach, you can effectively manage and automate your Azure environments efficiently.</p>
<p>To further enhance your understanding, explore <a target="_blank" href="https://www.pulumi.com/docs/iac/concepts/inputs-outputs/apply/">Pulumi's official documentation</a>, which offers in-depth examples and advanced techniques. Also I found <a target="_blank" href="https://leebriggs.co.uk/blog/2021/05/09/pulumi-apply">this blog post</a> very useful. Exploring these resources will solidify your grasp on how to make the most of this powerful tool.</p>
]]></content:encoded></item><item><title><![CDATA[PowerShell Arrays Quick Tips]]></title><description><![CDATA[You are looking for a short but useful help to use Arrays in PowerShell. Here you can find out quick examples of:

Creating arrays

Adding elements

Removing elements

Accessing an element

Iterating them

Filtering them


in PowerShell.
Creating an ...]]></description><link>https://margani.dev/powershell-arrays-quick-how-to</link><guid isPermaLink="true">https://margani.dev/powershell-arrays-quick-how-to</guid><category><![CDATA[Powershell]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Tue, 11 May 2021 11:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733907834869/f4300625-8dc0-4868-b18e-54ddd8c73382.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You are looking for a short but useful help to use Arrays in PowerShell. Here you can find out quick examples of:</p>
<ul>
<li><p>Creating arrays</p>
</li>
<li><p>Adding elements</p>
</li>
<li><p>Removing elements</p>
</li>
<li><p>Accessing an element</p>
</li>
<li><p>Iterating them</p>
</li>
<li><p>Filtering them</p>
</li>
</ul>
<p>in PowerShell.</p>
<h2 id="heading-creating-an-array"><strong>Creating an array</strong></h2>
<p>When you create an array by default it’s type is Object[], unless you specify the type.</p>
<pre><code class="lang-powershell"><span class="hljs-comment"># using @()</span>
<span class="hljs-variable">$itemsArray</span> = <span class="hljs-selector-tag">@</span>(<span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>)
<span class="hljs-comment"># or ()</span>
<span class="hljs-variable">$itemsArray</span> = (<span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>)
<span class="hljs-comment"># or just comma separated</span>
<span class="hljs-variable">$itemsArray</span> = <span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>

<span class="hljs-comment"># Using ranges</span>
<span class="hljs-variable">$genericArray</span> = <span class="hljs-number">1</span>..<span class="hljs-number">10</span>
<span class="hljs-comment"># instead of @('a', 'b', 'c', 'd', 'e')</span>
<span class="hljs-variable">$genericArray</span> = <span class="hljs-string">'a'</span>..<span class="hljs-string">'e'</span>

<span class="hljs-comment"># Int32[] array</span>
[<span class="hljs-built_in">int</span>[]]<span class="hljs-variable">$numbersArray</span> = <span class="hljs-number">1</span>..<span class="hljs-number">10</span>

<span class="hljs-comment"># ArrayList, type will be List`1, Base type: System.Object</span>
<span class="hljs-variable">$itemsList</span> = <span class="hljs-built_in">New-Object</span> System.Collections.Generic.List[<span class="hljs-type">System.Object</span>]
</code></pre>
<h2 id="heading-adding-items-to-an-array"><strong>Adding items to an array</strong></h2>
<pre><code class="lang-powershell"><span class="hljs-comment"># Add one item</span>
<span class="hljs-variable">$itemsArray</span> += <span class="hljs-string">'Item 4'</span>
<span class="hljs-comment"># Add a list to array with @()</span>
<span class="hljs-variable">$itemsArray</span> += <span class="hljs-selector-tag">@</span>(<span class="hljs-string">'Item 5'</span>, <span class="hljs-string">'Item 6'</span>)
<span class="hljs-comment"># Add a list to array with ()</span>
<span class="hljs-variable">$itemsArray</span> += (<span class="hljs-string">'Item 5'</span>, <span class="hljs-string">'Item 6'</span>)
<span class="hljs-comment"># Add a list to array with just comma separated list</span>
<span class="hljs-variable">$itemsArray</span> += <span class="hljs-string">'Item 5'</span>, <span class="hljs-string">'Item 6'</span>

<span class="hljs-variable">$genericArray</span> += (<span class="hljs-number">11</span>..<span class="hljs-number">20</span>)
<span class="hljs-variable">$genericArray</span> += <span class="hljs-string">'z'</span>..<span class="hljs-string">'a'</span>

<span class="hljs-variable">$numbersArray</span> += (<span class="hljs-number">11</span>..<span class="hljs-number">20</span>)
<span class="hljs-comment"># The following command will add ASCII codes of the characters,</span>
<span class="hljs-comment"># because $numbersArray is an array of type Int32[]</span>
<span class="hljs-variable">$numbersArray</span> += <span class="hljs-string">'a'</span>..<span class="hljs-string">'e'</span>

<span class="hljs-comment"># Add one item</span>
<span class="hljs-variable">$itemsList</span>.Add(<span class="hljs-string">'Item 1'</span>)
<span class="hljs-comment"># Add a list to the end of our list with @()</span>
<span class="hljs-variable">$itemsList</span>.AddRange(<span class="hljs-selector-tag">@</span>(<span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>))
<span class="hljs-comment"># Add a list to the end of our list with ()</span>
<span class="hljs-variable">$itemsList</span>.AddRange((<span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>))

<span class="hljs-comment"># Nope! this doesn't work</span>
<span class="hljs-variable">$itemsList</span>.AddRange(<span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>) <span class="hljs-comment">#Error</span>
</code></pre>
<h2 id="heading-remove-an-item-from-an-array"><strong>Remove an item from an array</strong></h2>
<p>Created arrays using <code>@()</code>, <code>()</code> or comma separated items, are <strong>fixed</strong> arrays. It means you can’t remove items from them, but you can create a new list with remaining items.</p>
<pre><code class="lang-powershell"><span class="hljs-variable">$itemsArray</span> = <span class="hljs-selector-tag">@</span>(<span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>)
<span class="hljs-comment"># Remove 'Item 2'</span>
<span class="hljs-variable">$newItemsArray</span> = <span class="hljs-variable">$itemsArray</span> | <span class="hljs-built_in">Where-Object</span> { <span class="hljs-variable">$_</span> –ne <span class="hljs-string">'Item 2'</span> }

<span class="hljs-comment"># Remove 'Item 2'</span>
<span class="hljs-variable">$newItemsArray</span> = <span class="hljs-variable">$itemsArray</span>[<span class="hljs-number">0</span>, <span class="hljs-number">2</span>]
</code></pre>
<p>Or you can use array lists:</p>
<pre><code class="lang-powershell"><span class="hljs-variable">$itemsList</span> = <span class="hljs-built_in">New-Object</span> System.Collections.Generic.List[<span class="hljs-type">System.Object</span>]
<span class="hljs-variable">$itemsList</span>.AddRange(<span class="hljs-selector-tag">@</span>(<span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>))
<span class="hljs-comment"># Remove 'Item 1'</span>
<span class="hljs-variable">$isRemoved</span> = <span class="hljs-variable">$itemsList</span>.Remove(<span class="hljs-string">'Item 1'</span>)
</code></pre>
<h2 id="heading-working-with-arrays"><strong>Working with Arrays</strong></h2>
<h3 id="heading-accessing-items"><strong>Accessing items</strong></h3>
<pre><code class="lang-powershell"><span class="hljs-variable">$itemsArray</span> = <span class="hljs-selector-tag">@</span>(<span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>)

<span class="hljs-variable">$itemsArray</span>[<span class="hljs-number">0</span>] <span class="hljs-comment"># =&gt; Item 1</span>
<span class="hljs-variable">$itemsArray</span>[<span class="hljs-number">2</span>] <span class="hljs-comment"># =&gt; Item 3</span>
<span class="hljs-variable">$itemsArray</span>[-<span class="hljs-number">1</span>] <span class="hljs-comment"># =&gt; Item 3</span>
<span class="hljs-variable">$itemsArray</span>[-<span class="hljs-number">3</span>] <span class="hljs-comment"># =&gt; Item 1</span>
<span class="hljs-variable">$itemsArray</span>[-<span class="hljs-number">4</span>] <span class="hljs-comment"># =&gt; $NULL, no error</span>
<span class="hljs-variable">$itemsArray</span>[<span class="hljs-number">3</span>] <span class="hljs-comment"># =&gt; $NULL, no error</span>

<span class="hljs-comment"># The following will throw an error</span>
<span class="hljs-comment"># OperationStopped: Index was outside the bounds of the array.</span>
<span class="hljs-variable">$itemsArray</span>[<span class="hljs-number">3</span>] = <span class="hljs-string">'Item 4'</span>

<span class="hljs-variable">$unknownVariable</span> <span class="hljs-comment"># =&gt; $NULL</span>
<span class="hljs-variable">$unknownVariable</span>[<span class="hljs-number">0</span>] <span class="hljs-comment"># =&gt; Error: Cannot index into a null array.</span>
</code></pre>
<h3 id="heading-iterating-arrays"><strong>Iterating Arrays</strong></h3>
<pre><code class="lang-powershell"><span class="hljs-variable">$itemsArray</span> = <span class="hljs-selector-tag">@</span>(<span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>)

<span class="hljs-comment"># ForEach-Object Pipeline</span>
<span class="hljs-variable">$itemsArray</span> | <span class="hljs-built_in">ForEach-Object</span> {<span class="hljs-string">"Item: [<span class="hljs-variable">$_</span>]"</span>}

<span class="hljs-comment"># For loop</span>
<span class="hljs-keyword">foreach</span> (<span class="hljs-variable">$item</span> <span class="hljs-keyword">in</span> <span class="hljs-variable">$itemsArray</span>) {
    <span class="hljs-string">"Item: [<span class="hljs-variable">$item</span>]"</span>
}

<span class="hljs-comment"># Foreach method</span>
<span class="hljs-variable">$itemsArray</span>.foreach({<span class="hljs-string">"Item: [<span class="hljs-variable">$_</span>]"</span>})
<span class="hljs-variable">$itemsArray</span>.foreach {<span class="hljs-string">"Item: [<span class="hljs-variable">$_</span>]"</span>}

<span class="hljs-comment"># For loop</span>
<span class="hljs-keyword">for</span> (<span class="hljs-variable">$index</span> = <span class="hljs-number">0</span>; <span class="hljs-variable">$index</span> <span class="hljs-operator">-lt</span> <span class="hljs-variable">$itemsArray</span>.count; <span class="hljs-variable">$index</span>++) {
    <span class="hljs-string">"Item: [{0}]"</span> <span class="hljs-operator">-f</span> <span class="hljs-variable">$itemsArray</span>[<span class="hljs-variable">$index</span>]
}

<span class="hljs-comment"># Switch</span>
<span class="hljs-keyword">switch</span>(<span class="hljs-variable">$itemsArray</span>)
{
    <span class="hljs-string">'Item 1'</span>
    {
        <span class="hljs-string">"Item: [<span class="hljs-variable">$_</span>]"</span>
    }
    <span class="hljs-string">'Item 3'</span>
    {
        <span class="hljs-string">"Item: [<span class="hljs-variable">$_</span>]"</span>
    }
    Default
    {
        <span class="hljs-string">"Item: [<span class="hljs-variable">$_</span>] not in the list of switch"</span>
    }
}
</code></pre>
<h3 id="heading-filtering-arrays"><strong>Filtering Arrays</strong></h3>
<pre><code class="lang-powershell"><span class="hljs-variable">$itemsArray</span> = <span class="hljs-selector-tag">@</span>(<span class="hljs-string">'Item 1'</span>, <span class="hljs-string">'Item 2'</span>, <span class="hljs-string">'Item 3'</span>)

<span class="hljs-comment"># Where-Object</span>
<span class="hljs-variable">$itemsArray</span> | <span class="hljs-built_in">Where-Object</span> { <span class="hljs-variable">$_</span> <span class="hljs-operator">-like</span> <span class="hljs-string">'*tem*'</span> }

<span class="hljs-comment"># Where method</span>
<span class="hljs-variable">$itemsArray</span>.Where({ <span class="hljs-variable">$_</span> <span class="hljs-operator">-like</span> <span class="hljs-string">'*tem*'</span> })
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This was very short and quick introduction to PowerShell Arrays. You can find more information on PowerShell commands and Arrays at <a target="_blank" href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_arrays?view=powershell-7.1">Microsoft documentations on Arrays in PowerShell</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Async/Await in C# - A quick how to]]></title><description><![CDATA[Using asynchronous programming in C#, you can improve your application’s responsiveness by avoiding the activities which are blocked in a synchronous operation. This post will explain in short so you will understand how to use Async and Await keyword...]]></description><link>https://margani.dev/async-await-csharp</link><guid isPermaLink="true">https://margani.dev/async-await-csharp</guid><category><![CDATA[C#]]></category><category><![CDATA[asynchronous]]></category><dc:creator><![CDATA[Hossein Margani]]></dc:creator><pubDate>Wed, 21 Apr 2021 11:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733908022165/a7799dd4-045d-4408-b995-bd2da6fc14d8.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Using asynchronous programming in C#, you can improve your application’s responsiveness by avoiding the activities which are blocked in a synchronous operation. This post will explain in short so you will understand how to use Async and Await keywords in C#.</p>
<p>Assume you go to a coffee shop and order coffee with cake.</p>
<p>Here are the list of thing that a worker needs to do:</p>
<ol>
<li><p>Accept the order and payment, takes <strong>3 minutes</strong></p>
</li>
<li><p>Make the coffee, and put it on a tray, takes <strong>5 minutes</strong></p>
</li>
<li><p>Put a slice of cake you have ordered and put it on the tray, takes <strong>1 minutes</strong></p>
</li>
</ol>
<h2 id="heading-synchronous"><strong>Synchronous</strong></h2>
<p>In a synchronous world, it’s like the coffee shop has only one staff and has to work on the tasks one after another. Here it takes <strong>9 minutes</strong> for the worker to complete all above three tasks.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">Demo</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">CoffeeShop</span>
    {
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">int</span> MIN = <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">AcceptPayment</span>(<span class="hljs-params"></span>)</span>         =&gt; Thread.Sleep(<span class="hljs-number">3</span> * MIN);
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">MakeCoffee</span>(<span class="hljs-params"></span>)</span>            =&gt; Thread.Sleep(<span class="hljs-number">5</span> * MIN);
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">PrepareSliceOfCake</span>(<span class="hljs-params"></span>)</span>    =&gt; Thread.Sleep(<span class="hljs-number">1</span> * MIN);
    }

    <span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">var</span> shop = <span class="hljs-keyword">new</span> CoffeeShop();
            shop.AcceptPayment();
            shop.MakeCoffee();
            shop.PrepareSliceOfCake();
        }
    }
}
</code></pre>
<h2 id="heading-asynchronous"><strong>Asynchronous</strong></h2>
<p>But if we use asynchronous programming, we can me it less.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Threading.Tasks;
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Demo</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">CoffeeShop</span>
    {
        ...
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">AcceptPayment</span>(<span class="hljs-params"></span>)</span>       =&gt; <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">3</span> * MIN);
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">MakeCoffee</span>(<span class="hljs-params"></span>)</span>          =&gt; <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">5</span> * MIN);
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">PrepareSliceOfCake</span>(<span class="hljs-params"></span>)</span>  =&gt; <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">1</span> * MIN);
        ...
    }

    <span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">var</span> shop = <span class="hljs-keyword">new</span> CoffeeShop();
            <span class="hljs-keyword">var</span> acceptPaymentTask = shop.AcceptPayment();
            <span class="hljs-keyword">var</span> makeCoffeeTask = shop.MakeCoffee();
            <span class="hljs-keyword">var</span> prepareSliceOfCake = shop.PrepareSliceOfCake();

            Task.WaitAll(acceptPaymentTask, makeCoffeeTask, prepareSliceOfCake);
        }
    }
}
</code></pre>
<p>We changed the return types of the functions from <code>void</code> to <code>async Task</code> and used <code>Task.WaitAll</code> to wait for all the task to complete so we can drink our coffee with the slice of cake.</p>
<h3 id="heading-using-await-in-main-needs-async-main"><strong>Using await in Main needs async Main</strong></h3>
<p>We may want to have the coffee even if without the cake, because we are thirsty?</p>
<pre><code class="lang-csharp">    ...
        <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Main</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">var</span> shop = <span class="hljs-keyword">new</span> CoffeeShop();
            <span class="hljs-keyword">var</span> acceptPaymentTask = shop.AcceptPayment();
            <span class="hljs-keyword">var</span> makeCoffeeTask = shop.MakeCoffee();

            Task.WaitAll(acceptPaymentTask, makeCoffeeTask);

            <span class="hljs-comment">// Drink the coffee while waiting for...</span>

            <span class="hljs-keyword">await</span> shop.PrepareSliceOfCake();

            <span class="hljs-comment">// The cake is ready :yum:</span>
        }
    ...
</code></pre>
<p>You can see we had to add <code>async Task</code> to the <code>Main</code> method as well, because we are using await keyword inside it.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This post was a quick introduction to using async/await in C# which I hope it was helpful. Parallel tasks are still tasks and needs to be done in the same time as the synchronous tasks, but running them asynchronously helps us getting the coffee sooner if we are thirsty. :)</p>
]]></content:encoded></item></channel></rss>