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:

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

Initialize the Go module:

go mod init go-contacts-api

2. Install dependencies

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

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:

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:

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:

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:

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:

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:

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:

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):

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.

Categories:

Tags:

Comments are closed