At this stage we will create the main
function of the project that we have created. In the main
function we will add several function initializations which are used to initialize all the resources
needed by the project such as database connections, handler initialization, usecases and repositories that we have previously created.
The HTTP Router that we use in this project is
github.com/julienschmidt/httprouter
So we need to first add the package to our project using the golang module command.
go get github.com/julienschmidt/httprouter
Configuring HTTP Router and HTTP ServerA
First, we create a main.go
file in the cmd
folder then fill the file with the code below.
package cmd
import (
"database/sql"
"github.com/julienschmidt/httprouter"
httpHandler "github.com/santekno/learn-golang-restful/delivery/http"
mysqlRepository "github.com/santekno/learn-golang-restful/repository/mysql"
articleUsecase "github.com/santekno/learn-golang-restful/usecase/article"
)
func main() {
router := httprouter.New()
repository := mysqlRepository.New(&sql.DB{})
articleUsecase := articleUsecase.New(repository)
articleHandler := httpHandler.New(articleUsecase)
router.GET("/api/articles", articleHandler.GetAll)
router.GET("/api/articles/:article_id", articleHandler.GetByID)
router.POST("/api/articles/", articleHandler.Store)
router.PUT("/api/articles/:article_id", articleHandler.Update)
router.DELETE("/api/articles/:article_id", articleHandler.Delete)
server := http.Server{
Addr: "localhost:3000",
Handler: router,
}
err := server.ListenAndServe()
if err != nil {
panic(err)
}
}
We can see that the first initialization done is
router := httprouter.New()
This httprouter
initialization is done every time there is a REST API initialization if we use the package from julienschmidt/httprouter
.
Next we initialize the repository, usecase and handler layers that we have previously created.
repository := mysqlRepository.New(&sql.DB{})
articleUsecase := articleUsecase.New(repository)
articleHandler := httpHandler.New(articleUsecase)
In initializing repository we need to add a database connection to the layer which will be explained in the database connection configuration section.
Followed by creating each endpoint that we previously defined using the API Specification. Make sure the method and entrypoint are the same as in the documentation.
router.GET("/api/articles", articleHandler.GetAll)
router.GET("/api/articles/:article_id", articleHandler.GetByID)
router.POST("/api/articles/", articleHandler.Store)
router.PUT("/api/articles/:article_id", articleHandler.Update)
router.DELETE("/api/articles/:article_id", articleHandler.Delete)
And the last is the HTTP Server to make our REST API server public with a configuration like this.
server := http.Server{
Addr: "localhost:3000",
Handler: router,
}
err := server.ListenAndServe()
if err != nil {
panic(err)
}
MySQL Database Connection Configuration
In this database connection we use an additional package to support connections to the MySQL database, namely
github.com/go-sql-driver/mysql
Then we need to add the package/libary first with this command.
go get github.com/go-sql-driver/mysql
Then we create the pkg/database
folder and create the mysql.go
file then fill the file with the code below.
package database
import (
"database/sql"
"os"
"gorm.io/driver/mysql"
)
unc New() *sql.DB {
cfg := mysql.Config{
User: os.Getenv("DATABASE_USER"),
Passwd: os.Getenv("DATABASE_PASS"),
Net: "tcp",
Addr: os.Getenv("DATABASE_ADDRESS"),
DBName: os.Getenv("DATABASE_NAME"),
AllowNativePasswords: true,
ParseTime: true,
}
var err error
db, err := sql.Open("mysql", cfg.FormatDSN())
if err != nil {
log.Fatal(err)
}
pingErr := db.Ping()
if pingErr != nil {
log.Fatal(pingErr)
}
fmt.Println("Connected!")
return db
}
In this project we only do basic configuration including
Configuration | Information |
---|---|
User | user connection required to mysql database |
Passwd | the passowrd for the user required for connection to the mysql database |
Net | the protocol used to connect to the database |
Addr | the address indicating the server of the database |
DBName | the name of the destination database |
Next add the database connection to the main.go
file and change the main()
function as below.
func main() {
// initialize http router
router := httprouter.New()
// initialize database
db := database.New()
// initialize repository
repository := mysqlRepository.New(db)
// initialize usecase
articleUsecase := articleUsecase.New(repository)
// handler initialization
articleHandler := httpHandler.New(articleUsecase)
// entrypoint
router.GET("/api/articles", articleHandler.GetAll)
router.GET("/api/articles/:article_id", articleHandler.GetByID)
router.POST("/api/articles/", articleHandler.Store)
router.PUT("/api/articles/:article_id", articleHandler.Update)
router.DELETE("/api/articles/:article_id", articleHandler.Delete)
}
Create .env file
We will make all the configuration stored in one .env
file so that when we want to change all the configuration it is easier and easier to just replace it in the file. So we will try to create a .env
file and fill the file with this.
DATABASE_USER=development
DATABASE_PASS=d3v3l0pm3nt
DATABASE_ADDRESS=localhost:3306
DATABASE_NAME=article
then add this library package to read the .env
file
go get github.com/joho/godotenv
and add the code below to the main.go
file at the top of the main()
function.
err := godotenv.Load(".env")
if err != nil {
log.Fatalf("error loading .env file")
}