Skip to content
dante robles

Tutorial API REST (Go Lang)

Requirements • Go installed (version 1.16 or higher). • MySQL server set up. • Basic knowledge of Go, SQL, and module handling. • An API tool like Postman or cURL for testing. 1. Create the project Create a directory for your project and navigate to it: Initialize the Go module: 2. Install dependenc...

2 min read

Requirements

• Go installed (version 1.16 or higher).

• MySQL server set up.

• Basic knowledge of Go, SQL, and module handling.

• An API tool like Postman or cURL for testing.

1. Create the project

Create a directory for your project and navigate to it:

text
mkdir go-contacts-api
cd go-contacts-api

Initialize the Go module:

text
go mod init go-contacts-api

2. Install dependencies

We will install the necessary dependencies to handle MySQL and routing:

text
go get -u github.com/gorilla/mux
go get -u github.com/go-sql-driver/mysql

3. MySQL configuration

1. Create the database and table in MySQL:

Connect to your MySQL server and run the following:

text
CREATE DATABASE contacts_db;

USE contacts_db;

CREATE TABLE contacts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL,
    phone VARCHAR(15) NOT NULL
);

2. Set up a user with appropriate permissions for the database.

4. Project structure

Inside your directory, create the following files:

• main.go

• database.go

• handlers.go

• models.go

5. Source code

main.go

This file contains the application’s entry point:

text
package main

import (
	"log"
	"net/http"
	"github.com/gorilla/mux"
)

func main() {
	// Initialize the database connection
	InitDB()

	// Create the router
	r := mux.NewRouter()

	// Define API routes
	r.HandleFunc("/contacts", CreateContact).Methods("POST")
	r.HandleFunc("/contacts", GetContacts).Methods("GET")

	// Start the server on port 8080
	log.Println("API running at http://localhost:8080")
	log.Fatal(http.ListenAndServe(":8080", r))
}

database.go

This file will handle the connection to MySQL:

text
package main

import (
	"database/sql"
	"fmt"
	"log"

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

var db *sql.DB

// InitDB initializes the database connection
func InitDB() {
	var err error
	// Replace with your MySQL credentials
	dsn := "user:password@tcp(127.0.0.1:3306)/contacts_db"
	db, err = sql.Open("mysql", dsn)
	if err != nil {
		log.Fatal("Error connecting to the database:", err)
	}

	if err = db.Ping(); err != nil {
		log.Fatal("Error pinging the database:", err)
	}

	fmt.Println("Successfully connected to the database")
}

models.go

Define the contact model:

text
package main

type Contact struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
	Phone string `json:"phone"`
}

handlers.go

This file will contain the handlers to create and list contacts:

text
package main

import (
	"encoding/json"
	"net/http"
	"strconv"
)

// Create a new contact
func CreateContact(w http.ResponseWriter, r *http.Request) {
	var contact Contact
	if err := json.NewDecoder(r.Body).Decode(&contact); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Insert the contact into the database
	query := "INSERT INTO contacts (name, email, phone) VALUES (?, ?, ?)"
	result, err := db.Exec(query, contact.Name, contact.Email, contact.Phone)
	if err != nil {
		http.Error(w, "Error inserting contact", http.StatusInternalServerError)
		return
	}

	id, _ := result.LastInsertId()
	contact.ID = int(id)

	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(contact)
}

// Get contacts with pagination
func GetContacts(w http.ResponseWriter, r *http.Request) {
	page, _ := strconv.Atoi(r.URL.Query().Get("page"))
	if page < 1 {
		page = 1
	}

	limit := 10
	offset := (page - 1) * limit

	query := "SELECT id, name, email, phone FROM contacts LIMIT ? OFFSET ?"
	rows, err := db.Query(query, limit, offset)
	if err != nil {
		http.Error(w, "Error retrieving contacts", http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	var contacts []Contact
	for rows.Next() {
		var contact Contact
		if err := rows.Scan(&contact.ID, &contact.Name, &contact.Email, &contact.Phone); err != nil {
			http.Error(w, "Error scanning contacts", http.StatusInternalServerError)
			return
		}
		contacts = append(contacts, contact)
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(contacts)
}

6. Run the application

Compile and run the application:

text
go run main.go

The API will be available at http://localhost:8080.

7. API testing

Create a contact

You can use cURL or Postman to test creating a contact:

text
curl -X POST http://localhost:8080/contacts \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com", "phone": "+1234567890"}'

List contacts with pagination

To list contacts (10 per page):

text
curl -X GET "http://localhost:8080/contacts?page=1"

Conclusion

This tutorial covers the creation of a basic REST API in Go with MySQL as the backend. You can expand it by adding authentication, data validation, more robust error handling, and additional CRUD operations to enhance its functionality.