2
\$\begingroup\$

This app loads application specific global configs and starts http server so that it is ready to serve API requests.

While structuring and coding, I've followed some "best" practises either from the official docs, widely followed resources and some others. Given that the app below works, I have a feeling that it could be improved hence reason I am asking questions below. My aim is to make it more of a Go-like app than my own invention with bad practises. Just a side note, I've cut things sorter to keep the post short but if you want to see full picture this is the GitHub page.

  1. Is the way I am bootstraping the app correct? The main.go prepares things and passes to api.go who starts the server so main.go is responsible for bootstraping things and api.go starts things.

  2. The config.go has global vars but I am not directly accessing them in where they are needed. Instead, I am injecting them to functions that depend on them. Am I currently over engineering it or is it ok?

  3. Shall I create/bootstrap http.handler with New() in main.go and inject into app.go as I do for the config? Or is it fine to keep it as is just because both server.go and handler.go files are under same directory?

.
├── bin
│   └── api
├── cmd
│   └── api
│       └── main.go
└── internal
    ├── app
    │   └── api.go
    ├── config
    │   └── config.go
    ├── controller
    │   └── index
    └── http
        ├── handler.go
        └── server.go

cmd/api/main.go

# This is also boots logger but removed to keep it short for now
package main

import (
    "github.com/myself/api/internal/app"
    "github.com/myself/api/internal/config"
)

func main() {
    config.Load()

    app.Run(config.Srv.Address)
}

internal/config/config.go

# This has more stuff in it
package config

import "sync"

var (
    App application
    Srv server
    o sync.Once
)

type application struct {
    Env string
}

type server struct {
    Address string
}

func Load() {
    o.Do(func() {
        App = application{Env:"dev"}
        Srv = server{Address:"0.0.0.0:8080"}
    })
}

internal/app/api.go

# This is as simple as this
package app

import "github.com/myself/api/internal/http"

func Run(addr string) {
    http.Start(addr)
}

internal/http/server.go

# This actually handles signals and shutdown
package http

import (
    "log"
    "net/http"
)

func Start(addr string) {
    if err := http.ListenAndServe(addr, handler()); err != nil {
        log.Fatalf("couldn't start http server")
    }
}

internal/http/handler.go

# This has little bit stuff in it
package http

import (
    "github.com/myself/api/internal/controller/index"
    "github.com/julienschmidt/httprouter"
)

func handler() *httprouter.Router {
    rtr := httprouter.New()
    rtr.GET("/", index.Index)

    return rtr
}

internal/controller/index/index.go

package index

import (
    "github.com/julienschmidt/httprouter"
    "net/http"
)

func Index(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
}
\$\endgroup\$
  • \$\begingroup\$ At least the title should contain what the code does, what is the function of the program. It might be good if there was a paragraph of text about what the code does as well. Currently the question can be closed as off-topic due to Lack of Concrete Context. \$\endgroup\$ – pacmaninbw Sep 21 at 12:16
  • 2
    \$\begingroup\$ @pacmaninbw Updated as per your request. I hope it is much clearer now. \$\endgroup\$ – BentCoder Sep 21 at 12:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.