Using global variables without any strong reason in any programming language is not a good idea.
Why should we not use global variables in Golang?
Global variables have no access control. We can access and change these variables in any part of the code. As the project grows, it becomes difficult to remember the actual reason for every possible use. Any function can access global variables. Hence, it is difficult to debug and understand the existing business logic.
The following tutorial will show us how to avoid using global variables in golang.
Take an example of database configuration using sqlx in golang.
package database
import (
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
var Db *sqlx.DB
func SqlConfig() *sqlx.DB {
host := "localhost"
port := "3306"
username := "root"
password := "secret"
dbName := "db_name"
Db = sqlx.MustConnect("mysql", username+":"+password+"@tcp("+host+":"+port+")/"+dbName)
return Db
}
Here we have declared Db as a global variable and we can access it anywhere in the project.
type User struct {
id int
name string
}
func GetUser(id int) (*User, error) {
var user User
err := database.Db.Get(&user, "SELECT id, name FROM user WHERE id = ? ", id )
if err != nil {
return nil, err
}
return &user, nil
}
The function uses a package of global sqlx.DB, to make a query against some database. This operation has side effects that are completely invisible from an inspection of the function signature.
The caller can not predict what database configuration is used for it, except by inspecting the function and digging the definition of the globals.
There are many solutions to avoid this like passing the Db variable in the function signature like this.
func GetUser(Db *sqlx.DB, id int)
I guess for large projects, it’s not a feasible solution. I have found one possible solution and that is making use of repositories.
Now we will see how to implement repositories to effectively use variables in the project without making it global.
Let’s declare the Db variable inside the function definition.
package database
import (
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
func SqlConfig() *sqlx.DB {
var Db *sqlx.DB
host := "localhost"
port := "3306"
username := "root"
password := "secret"
dbName := "db_name"
Db = sqlx.MustConnect("mysql", username+":"+password+"@tcp("+host+":"+port+")/"+dbName)
return Db
}
Now the question is, How to access Db in the entire project?
Here we go...
We will create a struct and repository interface in user/user.go, that will hold the the database dependency for us.
type Repo struct{
Db *sqlx.DB
}
func RepoInterface(db *sqlx.DB) *Repo {
return &Repo{Db: db}
}
Let’s add the GetUser() method to this repository
func (repo *Repo) GetUser(id int) (*User, error) {
var user User
err := repo.Db.Get(&user, "SELECT id, name FROM user WHERE id = ? ", id )
if err != nil {
return nil, err
}
return &user, nil
}
As GetUser
function is part of the repository, it will have DB variable access that it can use to execute queries.
Now let’s see how we can initialize the repository from the app entry point.
Add a function SqlConfig() in main.go that can provide us database connection like this.
func InitDb() *sqlx.DB {
db := database.SqlConfig()
return db
}
In the main function, we will initialize the repo by passing db.
func main() {
db := InitDb()
userRepo := users.RepoInterface(db)
user, err := userRepo.GetUser(<userId>)
if err != nil {
log.Println(err)
}
fmt.Println(user)
}
That’s it, we are done!!
I took the SQL database just for example purposes. You can map any other database or dependencies like Redis, MongoDB, struct(if required), etc. in repositories depending on your use cases.
We’re Grateful to have you with us on this journey!
Suggestions and feedback are more than welcome!
Please reach us at Canopas Twitter handle @canopas_eng with your content or feedback. Your input enriches our content and fuels our motivation to create more valuable and informative articles for you.
Get started today
Let's build the next
big thing!
Let's improve your business's digital strategy and implement robust mobile apps to achieve your business objectives. Schedule Your Free Consultation Now.
Get Free ConsultationGet started today
Let's build the next big thing!
Let's improve your business's digital strategy and implement robust mobile apps to achieve your business objectives. Schedule Your Free Consultation Now.
Get Free Consultation