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, eg,
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
, eg,
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:
server
package only works for data types in ticket
. 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. main.go
which only creates the database tables and build it into executable such that I can run it on the server just once? I think making 2 packages is a bad decision based on what you've described. If you're making a "small web app", there's nothing to gain but extra complexity in having more than one package. If you're not sure, always choose the simpler solution.
I don't think having 2 packages is cleaner or that it mixes less. You can have your package stuff on several different files, and functions as methods of different structs.
How about this? Define your db initialisation in an idempotent way (eg CREATE SCHEMA IF NOT EXISTS, CREATE TABLE IF NOT EXISTS) and run it every single time at the beginning of your main.go
, right after you db.Ping()
. Should be milliseconds most of the time, and you ensure that the db always has the structure you expect.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.