go-basic-server-structure


tags:

  • go
  • ready
  • golang
  • online

go-basic-server-structure

Project Structure

  • Internal Packages: Encapsulate the logic and data specific to your module, keeping it private and modular.
  • Utils Package: Provides a centralized place for shared utility functions that multiple internal packages can use.
  • Public Package: Exposes a clean interface for starting the application, while keeping the internal details hidden.
myapp/
│
├── main.go # Entry point of the application. It starts the server by calling the `StartServer` function from the `public` package.
├── go.mod
├── internal/
│   ├── controller/ # Contains HTTP handlers for user-related routes. It uses utility functions from the `utils` package.
│   │   └── user_controller.go
│   ├── service/ # Contains business logic related to users.
│   │   └── user_service.go
│   ├── model/ # Contains the data model for users.
│   │   └── user.go
│   └── utils/ # Contains shared utility functions. In this case, a function to mask email addresses.
│       └── string_utils.go
└── public/ # Sets up and starts the Gin server, exposing the necessary public API to run the application.
└── api.go

1. Internal Packages

internal/model/user.go

Define the data model for users.

package model

// User represents a user in the system.
type User struct {
ID    int    `json:"id"`
Name  string `json:"name"`
Email string `json:"email"`
}

internal/service/user_service.go

Handle the business logic related to users.

package service

import "myapp/internal/model"

// UserService provides operations related to users.
type UserService struct {
users []model.User
}

// NewUserService creates a new UserService instance.
func NewUserService() *UserService {
return &UserService{
users: []model.User{
{ID: 1, Name: "John Doe", Email: "john@example.com"},
{ID: 2, Name: "Jane Smith", Email: "jane@example.com"},
},
}
}

// GetAllUsers returns a list of users.
func (s *UserService) GetAllUsers() []model.User {
return s.users
}

internal/controller/user_controller.go

Define the HTTP handlers for user-related routes.

package controller

import (
"net/http"
"myapp/internal/service"
"myapp/internal/utils"
"github.com/gin-gonic/gin"
)

// UserController handles user-related HTTP requests.
type UserController struct {
userService *service.UserService
}

// NewUserController creates a new UserController instance.
func NewUserController(userService *service.UserService) *UserController {
return &UserController{userService: userService}
}

// GetUsers handles the GET /users request.
func (uc *UserController) GetUsers(c *gin.Context) {
users := uc.userService.GetAllUsers()
for i := range users {
users[i].Email = utils.MaskEmail(users[i].Email) // Example usage of utility function
}
c.JSON(http.StatusOK, users)
}

internal/utils/string_utils.go

Define shared utility functions.

package utils

// MaskEmail masks the domain part of the email address.
func MaskEmail(email string) string {
// Simple example of masking the email domain
parts := strings.Split(email, "@")
if len(parts) != 2 {
return email
}
return parts[0] + "@.com"
}

2. Public Package

public/api.go

Set up the Gin server and route handlers.

package public

import (
"github.com/gin-gonic/gin"
"myapp/internal/controller"
"myapp/internal/service"
)

// StartServer initializes and starts the Gin server.
func StartServer() {
router := gin.Default()

userService := service.NewUserService()
userController := controller.NewUserController(userService)

// Define routes
router.GET("/users", userController.GetUsers)

// Start the server
router.Run(":8080")
}

3. Main Application File

main.go

Start the server by calling the public API.

package main

import "myapp/public"

func main() {
// Start the server
public.StartServer()
}