Saya baru-baru ini mempelajari bahasa pemrograman Go khususnya dalam kasus pengembangan aplikasi web. Tidak perlu ditanyakan sebabnya, karena sebagai orang yang terjun di dunia teknologi, pasti harus selalu memperbarui ilmu setiap saat agar tidak tertinggal dengan yang lain, begitu juga saya. Prinsip belajar saya adalah mencoba dan mengulang kembali agar tidak lupa. Oleh karena itu, dalam waktu kedepan, akan banyak tulisan saya mengenai penerapan bahasa Go dalam berbagai kasus sederhana. Selain bisa untuk belajar saya pribadi, juga bisa dibaca oleh siapa saja yang berkunjung ke web ini.
Dalam artikel ini, kita akan belajar bagaimana membuat CRUD REST API menggunakan bahasa Go. Saya tidak memakai full framework seperti GIN , Echo atau Fiber, akan tetapi saya coba menggunakan libary Gorilla Mux untuk routing dan GORM untuk pengaksesan database. Untuk manajemen konfigurasi saya menggunakan Viper, dan database menggunakan MySQL. Saya akan coba pendekatan yang menurut saya paling mudah dipahami oleh pemula seperti saya, termasuk pembuatan struktur direktori dalam aplikasi ini.
Read more: Membuat CRUD Rest API di Golang menggunakan GORM dan Mux : Edisi PemulaSetup Project
Dengan menggunakan terminal / konsole saya membuat direktori untuk project ini sebagai berikut
mkdir golang-crud-api
cd golang-crud-api
Setelah masuk kedalam direktori project, buat go.mod dengan perintah sebagai berikut
go mod init go-crud-api
Lakukan instalasi pada library yang dibutuhkan, perintahnya adalah sebagai berikut (jalankan satu persatu, tunggu hingga selesai)
go get -u github.com/gorilla/mux
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
go get -u github.com/spf13/viper
Penjelasan dari perintah di atas adalah
- Gorilla/Mux digunakan untuk mengatur routing dari aplikasi nantinya. Misalnya GET /users akan diarahkan ke fungsi getUser, POST /user akan diarahkan ke fungsi postUser dan sebagainya.
- Gorm adalah sebuah ORM untuk mempermudah manajemen query ke dalam database. Alih-alih menuliskan script SQL, dengan GORM dapat diubah menjadi fungsi yang lebih mudah dipahami.
- Driver Mysql, karena kita menggunakan database MySQL maka diperlukan libray ini
- viper digunakan untuk manajemen konfigurasi yang membantu kita memuat file dan nilai yang akan digunakan dalam aplikasi
Buat main.go dan buka dengan editor kalian
touch main.go
code . //untuk membuka dengan visual studio code
vim . //untuk membuka dengan vim editor
nvim . //untuk membuka dengan neovim editor
dan buat function main seperti berikut
package main
func main() {
}
Mengatur konfigurasi dengan Viper
Buat file dengan nama config.go Isikan dengan kode berikut
package main
import (
"log"
"github.com/spf13/viper"
)
type Config struct {
Port string `mapstructure:"port"`
ConnectionString string `mapstructure:"connection_string"`
}
var AppConfig *Config
func LoadAppConfig() {
log.Println("Loading server configuration")
viper.AddConfigPath(".")
viper.SetConfigName("config")
viper.SetConfigType("json")
err := viper.ReadInConfig()
if err != nil {
log.Println(err)
}
err = viper.Unmarshal(&AppConfig)
if err != nil {
log.Println(err)
}
}
Kita analisa bersama, dimulai dari baris 9-12 adalah untuk mendefiniskan struct yang nantinya akan digunakan dalam konfigurasi aplikasi. Saat ini kita atur isinya dengan port aplikasi dan koneksi database yang akan digunakan.
Baris 14 digunakan untuk membuat variabel dengan type data struct Config
Baris 16-30 adalah fungsi dimana tempat Viper akan memuat konfigurasi dari config.json. Nantinya fungsi ini dipanggil di main program untuk menerapkan konfigurasinya.
Selanjutnya buat file config.json dan isi sebagai berikut
{
"connection_string": "root:secret@tcp(127.0.0.1:3306)/go_crud_api",
"port": 8080
}
Model Entity
Sekarang saatnya membuat model, layaknya di platform / frameworks lain, models digunakan untuk mockuop data dari table di database. Buat sebuah folder dengan nama entities dan buat file dengan nama product.go sebagai entitas model untuk table products yang akan kita buat nanti. Isi file product.go adalah sebagai berikut,
package entities
type Product struct {
ID uint `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
Dscription string `json:"description"`
}
Penjelasan sederhananya adalah, struct product berisikan atribut table product dan format datanya serta format jsonnya.
Menghubungkan dengan database
Langkah berikut adalah membuat koneksi dengan database. Oleh karena itu buat folder dengan nama database dan buat file dengan nama client.go isi dengan code berikut
package database
import (
"go-crud-api/entities"
"log"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var Instance *gorm.DB
var err error
func Connect(ConnectionString string) {
Instance, err = gorm.Open(mysql.Open(ConnectionString), &gorm.Config{})
if err != nil {
log.Fatal(err)
panic("Cannot connect to database")
}
log.Println("Connecting to database")
}
func Migrate() {
Instance.AutoMigrate(&entities.Product{})
log.Println("Database migration completed")
}
Baris 11-12 adalah membuat instansiasi variable DB dan variable error
Baris 14-21 adalah fungsi untuk menghubungkan ke database, disertakan error handling jika koneksi tidak berhasil
Baris 23-25 adalah fungsi untuk membuat migrasi sesuai entitas yang sudah dibuat.
Mulai membuat routing
Seperti disebutkan sebelumnya, kita akan menggunakan MUX untuk penanganan routing pada aplikasi ini. Untuk itu, buka kembali file main.go dan tambahkan fungsi berikut
func ProductHandlers(router *mux.Router) {
router.HandleFunc("/api/products", controllers.GetProducts).Methods(http.MethodGet)
router.HandleFunc("/api/products/{id}", controllers.GetProductById).Methods(http.MethodGet)
router.HandleFunc("/api/products", controllers.CreateProduct).Methods(http.MethodPost)
router.HandleFunc("/api/products/{id}", controllers.UpdateProduct).Methods(http.MethodPut)
router.HandleFunc("/api/products/{id}", controllers.DeleteProduct).Methods(http.MethodDelete)
}
Perhatikan format perintah dalam fungsi tersebut, jika kita sudah terbiasa menggunakan framework web lain, akan tampak familiar dengan kode diatas, terutama bagian parameter pada method HandleFunc. Parameter pertama adalah path, parameter selanjutnya adalah function. Jadi sederhanya adalah path “/api/products” akan diproses pada fungsi GetProducts. Sedangkan bagian terakhir adalah Methods menunjukan methoh HTTP yang digunakan untuk memanggil path tersebut, ada GET,POST,PUT dan DELETE
Saat ini akan muncul error karena package controllers belum dibuat.
Membuat Controller
File controllers akan kita letakkan di folder controllers, oleh karena itu buat terlebih dahulu folder controllers, dan buat file product_controller.go di dalamnya. Sekarang seluruh struktur direktori dan file pada aplikasi sudah selesai dibuat semua, dengan gambaran seperti berikut
Get Products
Fungsi ini digunakan dalam path /products (perhatikan fungsi router pada main.go) Isinya adalah mendapatkan keseluruhan data dari table di database. Isinya sebagai berikut
func GetProducts(w http.ResponseWriter, r *http.Request) {
var products []entities.Product
database.Instance.Find(&products)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(products)
}
Get Product By Id
Fungsi ini digunakan dalam path /product/{id}. Isinya adalah mendapatkan data sesuai ID dari url. Isinya sebagai berikut
func GetProductById(w http.ResponseWriter, r *http.Request) {
productID := mux.Vars(r)["id"]
var product entities.Product
w.Header().Set("Content-Type", "application/json")
database.Instance.First(&product, productID)
if product.ID == 0 {
json.NewEncoder(w).Encode("Product not found")
} else {
json.NewEncoder(w).Encode(product)
}
}
Create Product
Fungsi ini digunakan dalam path Post /product. Berfungsi untuk menyimpan data dari request ke dalam table
func CreateProduct(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var product entities.Product
json.NewDecoder(r.Body).Decode(&product)
database.Instance.Create(&product)
json.NewEncoder(w).Encode(product)
}
Update Product By Id
Fungsi ini dipanggil dalam path PUT /product/{id}. Digunakan untuk mengupdate product dengan ID sesuai parameter yang ditentukan
func UpdateProduct(w http.ResponseWriter, r *http.Request) {
productID := mux.Vars(r)["id"]
var product entities.Product
w.Header().Set("Content-Type", "application/json")
database.Instance.First(&product, productID)
if product.ID == 0 {
json.NewEncoder(w).Encode("Product not found")
} else {
json.NewDecoder(r.Body).Decode(&product)
database.Instance.Save(&product)
json.NewEncoder(w).Encode(product)
}
}
Delete Product By Id
Fungsi ini dipanggil dalam path DELETE /product/{id}. Digunakan untuk menghapus product dengan ID sesuai parameter yang ditentukan
func DeleteProduct(w http.ResponseWriter, r *http.Request) {
productID := mux.Vars(r)["id"]
var product entities.Product
w.Header().Set("Content-Type", "application/json")
database.Instance.First(&product, productID)
if product.ID == 0 {
json.NewEncoder(w).Encode("Product not found")
} else {
json.NewDecoder(r.Body).Decode(&product)
database.Instance.Delete(&product, productID)
json.NewEncoder(w).Encode("Product deleted")
}
}
Wrap Up the code
Saatnya menghubungkan semua fungsi yang sudah dibuat di fungsi main. Buka main.go dan ubah pada fungsi main menjadi sebagai berikut
func main() {
LoadAppConfig()
database.Connect(AppConfig.ConnectionString)
database.Migrate()
router := mux.NewRouter().StrictSlash(true)
ProductHandlers(router)
log.Println(fmt.Sprintf("starting server on port %s", AppConfig.Port))
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", AppConfig.Port), router))
}
Uji Coba
jalankan program dengan perintah
go run *.go
Lakukan request ke server dengan Postman atau CURL sesuai dengan path yang sudah ditentukan. Misalkan untuk path /products seperti berikut
curl -X GET 'http://localhost:8080/api/products'
Untuk membuat product dengan method POST, gunakan kode berikut
curl -X POST \
'http://localhost:8080/api/products' \
--header 'Content-Type: application/json' \
--data-raw '{
"name":"New Barang ",
"price":20000,
"description":"Barang pribadi yang sering digunakan"
}'
Mengambil product dengan Id tertentu
curl -X GET 'http://localhost:8080/api/products/2'
Mengupdate product
curl -X PUT \
'http://localhost:8080/api/products/3' \
--data-raw '{
"name":"New Barang Update "
}'
Menghapus product
curl -X DELETE 'http://localhost:8080/api/products/2'
Seluruh file kode sudah saya upload di https://github.com/dwijonarko/go-crud-api. Semoga bermanfaat
Pingback: Membuat REST API dengan Golang Framework Echo | dudu.WEB.ID