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.