<?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[Reading input in Go]]></title><description><![CDATA[Reading input in Go]]></description><link>https://bufiopackage.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 02 Sep 2026 06:26:00 GMT</lastBuildDate><atom:link href="https://bufiopackage.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Reading input in Go; using bufio.NewScanner and bufio.NewReader effectively]]></title><description><![CDATA[Reading input is a fundamental concept in backend development. In Node.js, developers often rely on the readline module or fs.createReadStream() to handle it. Similarly, Go provides bufio.NewScanner and bufio.NewReader for this same purpose, and I’ll...]]></description><link>https://bufiopackage.hashnode.dev/reading-input-in-go-using-bufionewscanner-and-bufionewreader-effectively</link><guid isPermaLink="true">https://bufiopackage.hashnode.dev/reading-input-in-go-using-bufionewscanner-and-bufionewreader-effectively</guid><dc:creator><![CDATA[Peter Aluya]]></dc:creator><pubDate>Fri, 09 May 2025 20:45:51 GMT</pubDate><content:encoded><![CDATA[<p>Reading input is a fundamental concept in backend development. In Node.js, developers often rely on the <strong>readline</strong> module or <strong>fs.createReadStream()</strong> to handle it. Similarly, Go provides <strong>bufio.NewScanner</strong> and <strong>bufio.NewReader</strong> for this same purpose, and I’ll show you how to use these tools effectively in your Go projects.</p>
<h2 id="heading-what-is-input-handling-and-why-does-it-matter-in-backend-development">What is input handling? And why does it matter in backend development?</h2>
<p>Input handling in backend development refers to receiving, validating, and processing data sent by users to a server. Hence, user input is central to backend development. From form submissions and API requests to file uploads and command-line tools, poor input handling can lead to issues like broken features, injection attacks, or even system crashes.</p>
<h3 id="heading-overview-of-the-bufio-package-in-go">Overview of the bufio package in Go</h3>
<p>The <strong><em>bufio</em></strong> <em>package in Go helps with</em> <strong><em>buffered I/O</em></strong>.</p>
<p>I know some of these terms might not make sense, but I’ll try to always break down complex terms using very simple words throughout this article.</p>
<p><strong>buffered I/O</strong> is the technique of temporarily storing the results of an I/O (input/output) operation before transmitting it to the kernel (when it’s writing) or before providing it to your process (when it’s reading).</p>
<blockquote>
<p>The kernel is the core part of an operating system. It’s like a manager that handles the communication between your program and your computer hardware.</p>
</blockquote>
<p>A quick example on how to use the <strong>bufio</strong> package in your Go program</p>
<pre><code class="lang-plaintext">package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Enter text: ")
    input, _ := reader.ReadString('\n')
    fmt.Println("You entered:", input)
}
</code></pre>
<p>In this code, we’re using <strong>bufio.NewReader</strong> to create a buffered reader that reads from standard input.<br />Here, <strong>os.Stdin</strong> just refers to your keyboard input. You don’t need to worry too much about the <strong>os</strong> package for now, it’s only helping us capture input from the user.</p>
<h3 id="heading-using-bufionewscanner">Using bufio.NewScanner</h3>
<p>The <strong>bufio.NewScanner</strong> function in Go is used to read input <strong>line-by-line</strong> or <strong>word-by-word</strong>, depending on how you configure it. It’s perfect for cases where you want to process input in small chunks, like reading lines from a user or parsing a file line by line.</p>
<p><strong>Here’s how to read user input from the terminal using</strong> <strong>bufio.NewScanner</strong>:</p>
<pre><code class="lang-plaintext">package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    fmt.Println("Enter some text:")
// this line creates a new scanner that read input from your keyboard and also prints a message to the terminal asking the user to write something


    for scanner.Scan() {
        line := scanner.Text()
        fmt.Println("You typed:", line)
    }
// this is a loop that runs each time the user enters a new line and scanner.Text() gets the current line of text the user just typed
// fmt.Println() returns the result of the user input back to the terminal

    if err := scanner.Err(); err != nil {
        fmt.Println("Error reading input:", err)
    }
// this line of code checks if there is an error while reading the user input and then prints it out
}
</code></pre>
<p><strong>Here’s how you can use the bufio.NewScanner to read a file line by line:</strong></p>
<pre><code class="lang-plaintext">package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("example.txt") // this line opens the file named "example.txt" if it already exists
    if err != nil {                    
        fmt.Println("Error opening file:", err)
        return                          
    }
    // this block tells the program to stop runing if there is an error

    defer file.Close() // this makes sure the opened file is closed when the function ends

    scanner := bufio.NewScanner(file) // this line creates a scanner to read the file line by line
    for scanner.Scan() {              
        fmt.Println(scanner.Text())
    }
    // this block of code loops through the opened file line by line and prints each line to the terminal


    if err := scanner.Err(); err != nil {           
        fmt.Println("Error reading file:", err)   
    }
    // this block of code checks if there was an error while reading the file and prints it to the terminal

}
</code></pre>
<h3 id="heading-using-bufionewreader">Using bufio.NewReader</h3>
<p>Although using <strong>bufio.NewScanner</strong> is efficient for reading input line by line, <strong>bufio.NewReader</strong> can be utilized when you need full control of the input, like reading until it gets to a specific character or reading raw bytes.</p>
<blockquote>
<p>Reading raw bytes simply means reading data exactly the way it is — in its binary or byte level form — without trying to interpret it as characters, strings or lines. This can be useful when dealing with binary files, custom formats or any data that isn’t plain text.</p>
</blockquote>
<p>Use NewReader when:</p>
<ul>
<li><p>You want to read input until a specific character, like a comma or a hash symbol, instead of just stopping at a new line.</p>
</li>
<li><p>You want more control — like checking the next part of the input without reading it yet, or reading a fixed number of characters or bytes.</p>
</li>
</ul>
<p><strong>Here’s an example of how to use NewReader to read input until a newline:</strong></p>
<pre><code class="lang-plaintext">package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Type something and press Enter: ")
    input, _ := reader.ReadString('\n')
    fmt.Println("You typed:", input)
}

//reader.ReadString('\n') reads input from the user until they press Enter (\n is the newline character).
</code></pre>
<blockquote>
<p>Incase you didn’t already know, the _ is just saying “I know the ReadString() function returns a value there (an error in this case) but I’m just choosing to ignore it”</p>
</blockquote>
<p><strong>Here’s another example on how to use NewReader to read input until it gets to a specific character. In this case, we’ll go with the ‘&amp;’ character:</strong></p>
<pre><code class="lang-plaintext">package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    input := "Go is awesome&amp;But this part won’t show"
    reader := bufio.NewReader(strings.NewReader(input))

    result, _ := reader.ReadString('&amp;') // remember what I told you about the _
    fmt.Println("Read until &amp;: ", result)
}
</code></pre>
<p>I hope these code blocks will be able to guide you through on getting started with the <strong>bufio</strong> package in Go.</p>
<h2 id="heading-key-differences-between-bufionewscanner-and-bufionewreader">Key differences between bufio.NewScanner and bufio.NewReader</h2>
<p>Here’s a quick comparison table to help you decide the right one for your Go projects:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>bufio.NewScanner</strong></td><td><strong>bufio.NewReader</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Ease of use</strong></td><td>Simpler code and requires fewer steps</td><td>More flexibility, but requires more code</td></tr>
<tr>
<td><strong>Size limits</strong></td><td>Can't handle lines bigger than 64KB by default</td><td>There are no size restrictions</td></tr>
<tr>
<td><strong>Common use cases</strong></td><td>Perfect for text files, logs, CSVs</td><td>Better for mixed data, protocols, or when you need precise control</td></tr>
</tbody>
</table>
</div><h3 id="heading-edge-case-newscanners-64kb-limit">Edge case: NewScanner’s 64KB limit</h3>
<p>By default, <strong>bufio.NewScanner</strong> can only read one line if it’s <strong>64KB or smaller</strong>. If your line is longer (like a big chunk of text or a long JSON string), it will fail and give an error.</p>
<p>You can fix this by telling the scanner to use a bigger buffer with the <strong>scanner.Buffer()</strong> function, but if your input is often that large, it’s easier to just use <strong>bufio.NewReader</strong> instead.</p>
<h3 id="heading-here-are-common-pitfalls-you-might-come-across-when-using-the-bufio-package-in-your-go-projects">Here are common pitfalls you might come across when using the bufio package in your Go projects:</h3>
<ul>
<li><p><strong>Scanner not reading the last line</strong></p>
<p>  If the last line of your input doesn't end with a newline (\n), <strong>Scanner</strong> might skip it. Always make sure your input ends with a newline, especially when reading from files.</p>
</li>
<li><p><strong>Reader hanging due to heavy delimiter</strong></p>
<p>  If you're using <strong>reader.ReadString(delimiter)</strong> and the delimiter (like ‘\n’ or ‘&amp;’) never shows up, the program will wait forever. Always be sure that the input contains the character you're waiting for.</p>
</li>
<li><p><strong>Best practices when handling error from the bufio package</strong></p>
<p>  Both <strong>Scanner</strong> and <strong>Reader</strong> can fail quietly. Always check for errors using by checking the err returned from <strong>ReadString()</strong>. It helps catch problems like missing files or bad input.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>To wrap it up, use <strong>bufio.NewScanner</strong> when you just want to read things line by line — like simple user input or text files. It’s easy to use but can’t handle very big lines. Use <strong>bufio.NewReader</strong> when you need more control, like reading until a special character or working with large or complex input. It takes more code, but it’s more flexible. Just pick the one that fits what you're trying to do, and always check for errors so your program doesn’t crash or behave in strange ways.</p>
]]></content:encoded></item></channel></rss>