Golang — With MySql

Ranjeet Kaur
3 min readJul 5, 2018

In the Previous Article, we discussed about basics of Go Programming. In this article, we will make a simple Go Application, to do CRUD operations on a Student object with a mysql database.

Before we start to code, we need to import go-sql-driver library.

go get -u github.com/go-sql-driver/mysql

Next, we add the required imports for creating database connector.

import (
_ "github.com/go-sql-driver/mysql"
"database/sql"
)

Now we create a connection object to open a MySQL connection.

var db *sql.DB
db, err:= sql.Open("mysql","root:password@(localhost:3306)/student")

Once the connector is initialised, we call Ping function to test the connection.

err = db.Ping()

In sql.DB object, we have some in-built functions to set connection properties.

db.SetMaxOpenConns(10)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(time.Second * 10)

Following is the complete function to connect to mysql database.

var db *sql.DB

func InitializeMySQL() {
dBConnection, err := sql.Open("mysql", "root:password@(localhost:3306)/student")
if err != nil {
fmt.Println("Connection Failed!!")
}
err = dBConnection.Ping()
if err != nil {
fmt.Println("Ping Failed!!")
}
db = dBConnection
dBConnection.SetMaxOpenConns(10)
dBConnection.SetMaxIdleConns(5)
dBConnection.SetConnMaxLifetime(time.Second * 10)
}

func GetMySQLConnection() *sql.DB {
return db
}

Once we have database connector in place, we can start adding functions to perform read and write operations.

We create a statement object, by calling Prepare method on the query.

sqlQuery := "INSERT student SET name = ?, age = ?"
stmt, err := db.Prepare(sqlQuery)

For Insert/Update/Delete operations, queries can be run using Exec command and passing parameters in function call.

res, err := stmt.Exec(student.Name, student.Age)

For Read operations, queries can be run using Query command and passing parameters in function call,

sqlQuery := "SELECT id, name, age FROM student WHERE id = ?"
stmt, err := db.Prepare(sqlQuery)
res, err := stmt.Query(studentID)

And returned values can be parsed through scan function.

for res.Next() {
res.Scan(&student.StudentID, &student.Name, &student.Age)
}

It is important to close statement and result objects(returned from Query function), to avoid leaks and to reuse connections.

res.Close()
stmt.Close()

Following are the sample functions to perform CRUD operations on a Student object.

func AddStudent(student model.Student) (int64, int64, error) {
sqlQuery := "INSERT student SET name = ?, age = ?"
stmt, err := db.Prepare(sqlQuery)
defer closeStmt(stmt)
if err != nil {
return 0, 0, err
}
res, err := stmt.Exec(student.Name, student.Age)
if err != nil {
return 0, 0, err
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return 0, 0, err
}
lastInsertedId, err := res.LastInsertId()
return rowsAffected, lastInsertedId, err
}

func UpdateStudent(student model.Student) (int64, error) {
sqlQuery := "UPDATE student SET name = ?, age = ? WHERE id = ?"
stmt, err := db.Prepare(sqlQuery)
defer closeStmt(stmt)
if err != nil {
return 0, err
}
res, err := stmt.Exec(student.Name, student.Age, student.StudentID)
if err != nil {
return 0, err
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return 0, err
}
return rowsAffected, err
}

func DeleteStudent(studentID int64) (int64, error) {
sqlQuery := "DELETE FROM student WHERE id = ?"
stmt, err := db.Prepare(sqlQuery)
defer closeStmt(stmt)
if err != nil {
return 0, err
}
res, err := stmt.Exec(studentID)
if err != nil {
return 0, err
}
rowsAffected, err := res.RowsAffected()
if err != nil {
return 0, err
}
return rowsAffected, err
}

func GetStudent(studentID int64) (model.Student, error) {
sqlQuery := "SELECT id, name, age FROM student WHERE id = ?"
stmt, err := db.Prepare(sqlQuery)
defer closeStmt(stmt)
var student model.Student
if err != nil {
return student, err
}
res, err := stmt.Query(studentID)
defer closeRows(res)
if err != nil {
return student, err
}
if res.Next() {
res.Scan(&student.StudentID, &student.Name, &student.Age)
}
return student, err
}

func closeRows(rows *sql.Rows) {
if rows != nil {
rows.Close()
}
}

func closeStmt(stmt *sql.Stmt) {
if stmt != nil {
stmt.Close()
}
}

Complete Code for this tutorial can be accessed through the GitHub Repo.

I hope you find it helpful. If you have any suggestions, please feel free to drop a comment.

In the Next Article, we will discuss how to setup file logging for a Go Application.

--

--