Working with Data in Go

by Solomon Eseme

.

Updated Sat Oct 07 2023

Working with Data in Go

Data manipulation is a fundamental aspect of software development, and Go provides powerful tools and libraries to work with various types of data.

In this section, we will explore several essential data-related topics in Go:

File I/O in Go

Working with files is a common requirement in many applications.

Go makes file input and output straightforward with its standard library.

Using the standard library's os and io packages, you can easily create, read, write, and manipulate files. Here's a basic example of reading a text file using os:

package main

import (
	"log"
	"os"
)

func main() {
	content, err := os.ReadFile("README.md")
	if err != nil {
		log.Println("Error reading file: ", err)
		return
	}
	log.Println("File content: ", string(content))
}

JSON and XML Data Processing

JSON and XML are widely used data interchange formats. Whenever you want to model a data entity (like user details for a database), you should use JSON.

Go's standard library supports encoding and decoding JSON and XML data. You can easily marshal and unmarshal data between Go data structures and these formats. Here's an example of decoding JSON data:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name    string
    Age     int
    Address string
}

func main() {
    jsonStr := `{"Name":"Alice","Age":30,"Address":"123 Main St"}`
    var person Person
    err := json.Unmarshal([]byte(jsonStr), &person)
    if err != nil {
        fmt.Println("Error decoding JSON:", err)
        return
    }
    fmt.Printf("Decoded Person: %+v\\\\n", person)
}

While this works, another way to represent a data entity using JSON format is to use tagging:

type CustomerAccount struct {
	LeadAccount
	ID         int       `json:"id"`
	BankNumber BankID    `json:"bank_number"`
	Balance    float64   `json:"balance"`
	CreatedAt  time.Time `json:"created_at"`
}

func main() {
	account := new(CustomerAccount)
	err := rows.Scan(
		&account.ID,
		&account.FirstName,
		&account.LastName,
		&account.Email,
		&account.BankNumber,
		&account.Balance,
		&account.CreatedAt,
	)
	return account, err
}

Working with Databases in Go

Go provides robust support for database access. You can connect to various databases, such as SQL databases (e.g., PostgreSQL, MySQL) and NoSQL databases (e.g., MongoDB). The database/sql package is a powerful and flexible tool for database interactions. Here's a simple example of querying a SQLite database:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/mattn/go-sqlite3" // SQLite driver
)

func main() {
    db, err := sql.Open("sqlite3", "example.db")
    if err != nil {
        fmt.Println("Error opening database:", err)
        return
    }
    defer db.Close()

    rows, err := db.Query("SELECT name, age FROM people WHERE age > ?", 25)
    if err != nil {
        fmt.Println("Error querying database:", err)
        return
    }
    defer rows.Close()

    for rows.Next() {
        var name string
        var age int
        err := rows.Scan(&name, &age)
        if err != nil {
            fmt.Println("Error scanning row:", err)
            return
        }
        fmt.Printf("Name: %s, Age: %d\\\\n", name, age)
    }
}

In this example, we wrote raw SQL queries. Sometimes, doing this inside Go code can be a hassle, and you must use an ORM such as GORM. You will learn more about it next.

Introduction to ORM (Object-Relational Mapping)

ORM libraries like GORM provide an abstraction layer for working with databases, allowing you to interact using Go structs and methods. This simplifies database operations and reduces the need to write raw SQL queries.

Here's a basic example using GORM:

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/sqlite" // SQLite driver
)

type Person struct {
    gorm.Model
    Name string
    Age  int
}

func main() {
    db, err := gorm.Open("sqlite3", "example.db")
    if err != nil {
        fmt.Println("Error opening database:", err)
        return
    }
    defer db.Close()

    db.AutoMigrate(&Person{})

    // Create a new person
    person := Person{Name: "Bob", Age: 35}
    db.Create(&person)

    // Query all people over 30
    var people []Person
    db.Where("age > ?", 30).Find(&people)
    fmt.Println("People over 30:", people)
}

You have seen how to interact with different data sources with Go. Next, we will explore some advanced data structures and how to create custom types in Go.

Exercise

  • Set up a properly working SQL database mapped after a User struct. Query the database to have 2 users.

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board

Topic:

Backend Tips, Every week

Backend Tips, Every week