I am new to golang and would like to make a small web app of to-do list to polish my go skills. I would like to know what is a good practice to organize the code.
Right now, I define two packages for this project: ticket
and server
. ticket
is about database and server
is about http handlers.
My data has two types: Ticket and Todo. One Ticket can have multiple Todo in it. They are defined in the ticket
package.
type Ticket struct {
Id int64 `db:"id" json:"id"`
Label string `db:"label" json:"label"`
Description string `db:"description" json:"description"`
StartTime time.Time `db:"start_time" json:"start_time"`
EndTime *time.Time `db:"end_time" json:"end_time"`
Priority bool `db:"priority" json:"priority"`
}
type Todo struct {
Id int64 `db:"id" json:"id"`
Item int64 `db:"item" json:"item"`
TicketId int64 `db:"ticket_id" json:"ticket_id"`
Active bool `db:"active" json:"active"`
}
In the ticket
package, I also define
type AppDB struct {
db *sqlx.DB
}
This wrapping around *sqlx.DB
allows me to put all the database access functions inside ticket
package, e.g.,
func (adb *AppDB) MustInit()
func (adb *AppDB) AddTicket(i *Ticket) (int64, error)
In the server
package, I define
type Application struct {
db ticket.AppDB
}
And the http handler functions are defined as methods of Application
, e.g.,
func (app *Application) CreateTicket(w http.ResponseWriter, req *http.Request)
In the main.go
, I register the handle functions.
func main() {
app := server.NewApplication()
fmt.Println("now listening...")
router := mux.NewRouter()
router.HandleFunc("/", app.Hello).Methods("GET")
router.HandleFunc("/get", app.Get).Methods("GET")
log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), router))
}
I have the following questions:
- Is this design a good practice? If not, what is the right way?
- In Donovan and Kernighan's Go programming book p.194, they give an example where the http handlers are defined as the database's method directly. Would that be a better design? It makes sense because my
server
package only works for data types inticket
. It also makes the code a little cleaner to write. On the other hand it mixes http and database, which I am not sure if it is a good thing. - How to deal with database table creation? Shall I create another
main.go
which only creates the database tables and build it into executable such that I can run it on the server just once?