<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Faiyaj Zaman</title>
    <description>The latest articles on DEV Community by Muhammad Faiyaj Zaman (@faiyajz).</description>
    <link>https://dev.to/faiyajz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F283186%2F07a01390-54fa-480f-8172-123c6b63c48a.png</url>
      <title>DEV Community: Muhammad Faiyaj Zaman</title>
      <link>https://dev.to/faiyajz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/faiyajz"/>
    <language>en</language>
    <item>
      <title>Rest Full API - Golang (Best Practices)</title>
      <dc:creator>Muhammad Faiyaj Zaman</dc:creator>
      <pubDate>Sat, 27 Jul 2024 17:21:33 +0000</pubDate>
      <link>https://dev.to/faiyajz/rest-full-api-golang-best-practices-g0n</link>
      <guid>https://dev.to/faiyajz/rest-full-api-golang-best-practices-g0n</guid>
      <description>&lt;h2&gt;
  
  
  1. Project Structure
&lt;/h2&gt;

&lt;p&gt;Organize your code in a way that makes it easy to understand and extend. A common structure includes separating your code into folders such as models, handlers, routes, middlewares, utils, and config.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example structure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go-rest-api/
|-- main.go
|-- config/
|   |-- config.go
|-- handlers/
|   |-- user.go
|-- models/
|   |-- user.go
|-- routes/
|   |-- routes.go
|-- middlewares/
|   |-- logging.go
|-- utils/
|   |-- helpers.go

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Environment Configuration
&lt;/h2&gt;

&lt;p&gt;Store configuration settings (like database credentials, port numbers, etc.) in environment variables or configuration files. Use a package like viper to manage configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;config/config.go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package config

import (
    "github.com/spf13/viper"
    "log"
)

type Config struct {
    Port string
    DB   struct {
        Host     string
        Port     string
        User     string
        Password string
        Name     string
    }
}

var AppConfig Config

func LoadConfig() {
    viper.SetConfigName("config")
    viper.AddConfigPath(".")
    viper.AutomaticEnv()

    if err := viper.ReadInConfig(); err != nil {
        log.Fatalf("Error reading config file, %s", err)
    }

    err := viper.Unmarshal(&amp;amp;AppConfig)
    if err != nil {
        log.Fatalf("Unable to decode into struct, %v", err)
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Error Handling
&lt;/h2&gt;

&lt;p&gt;Always handle errors appropriately. Return meaningful error messages and HTTP status codes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;handlers/user.go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func GetUserHandler(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    id, err := strconv.Atoi(params["id"])
    if err != nil {
        http.Error(w, "Invalid user ID", http.StatusBadRequest)
        return
    }

    user, err := findUserByID(id)
    if err != nil {
        http.Error(w, "User not found", http.StatusNotFound)
        return
    }

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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Middlewares
&lt;/h2&gt;

&lt;p&gt;Use middlewares for logging, authentication, and other cross-cutting concerns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;middlewares/logging.go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package middlewares

import (
    "log"
    "net/http"
    "time"
)

func LoggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        log.Printf("%s %s %s", r.Method, r.RequestURI, time.Since(start))
    })
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In main.go or routes/routes.go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;r.Use(middlewares.LoggingMiddleware)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. JSON Handling
&lt;/h2&gt;

&lt;p&gt;Use proper JSON encoding and decoding. Validate incoming JSON data to ensure it meets the expected structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;handlers/user.go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
    var user models.User
    if err := json.NewDecoder(r.Body).Decode(&amp;amp;user); err != nil {
        http.Error(w, "Invalid input", http.StatusBadRequest)
        return
    }

    // Validate user data...

    users = append(users, user)

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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Database Access
&lt;/h2&gt;

&lt;p&gt;Use a database to store your data. Use a package like gorm for ORM or sqlx for raw SQL queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;models/user.go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package models

import "gorm.io/gorm"

type User struct {
    gorm.Model
    Name  string `json:"name"`
    Email string `json:"email"`
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;main.go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "github.com/yourusername/go-rest-api/config"
    "github.com/yourusername/go-rest-api/routes"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
    "log"
    "net/http"
)

func main() {
    config.LoadConfig()

    dsn := "host=" + config.AppConfig.DB.Host +
        " user=" + config.AppConfig.DB.User +
        " password=" + config.AppConfig.DB.Password +
        " dbname=" + config.AppConfig.DB.Name +
        " port=" + config.AppConfig.DB.Port +
        " sslmode=disable"
    db, err := gorm.Open(postgres.Open(dsn), &amp;amp;gorm.Config{})
    if err != nil {
        log.Fatalf("Could not connect to the database: %v", err)
    }

    r := routes.NewRouter(db)

    log.Println("Starting server on port", config.AppConfig.Port)
    log.Fatal(http.ListenAndServe(":"+config.AppConfig.Port, r))
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Logging
&lt;/h2&gt;

&lt;p&gt;Use a structured logging library like logrus or zap for better logging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;middlewares/logging.go:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package middlewares

import (
    "github.com/sirupsen/logrus"
    "net/http"
    "time"
)

func LoggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        logrus.WithFields(logrus.Fields{
            "method": r.Method,
            "url":    r.URL.Path,
            "time":   time.Since(start),
        }).Info("handled request")
    })
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Security
&lt;/h2&gt;

&lt;p&gt;Ensure your API is secure by using HTTPS, validating and sanitizing inputs, and implementing proper authentication and authorization.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Versioning
&lt;/h2&gt;

&lt;p&gt;Version your API to handle changes without breaking existing clients. This can be done by including the version in the URL, such as /api/v1/users.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Documentation
&lt;/h2&gt;

&lt;p&gt;Document your API using tools like Swagger or Postman to provide clear usage instructions for developers.&lt;/p&gt;

&lt;p&gt;By following these best practices, you can create a robust, maintainable, and scalable RESTful API in Go.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>go</category>
      <category>backend</category>
      <category>restapi</category>
    </item>
  </channel>
</rss>
