简体   繁体   English

去休息api服务器设计好的做法

[英]go rest api server design good practice

I am new to golang and would like to make a small web app of to-do list to polish my go skills. 我是Golang的新手,想制作一个待办事项列表的小型网络应用程序,以提高我的技能。 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 . 现在,我为这个项目定义了两个包: ticketserver ticket is about database and server is about http handlers. ticket是关于数据库, server是关于http处理程序。

My data has two types: Ticket and Todo. 我的数据有两种类型:Ticket和Todo。 One Ticket can have multiple Todo in it. 一张票可以有多个Todo。 They are defined in the ticket package. 它们在ticket包中定义。

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 ticket包中,我也定义了

type AppDB struct {                                                                
    db *sqlx.DB                                                                    
}   

This wrapping around *sqlx.DB allows me to put all the database access functions inside ticket package, eg, 这包围*sqlx.DB允许我将所有数据库访问功能放在ticket包中,例如,

func (adb *AppDB) MustInit() 
func (adb *AppDB) AddTicket(i *Ticket) (int64, error)

In the server package, I define server包中,我定义

type Application struct {                                                          
    db ticket.AppDB                                                                
}   

And the http handler functions are defined as methods of Application , eg, 并且http处理程序函数被定义为Application方法,例如,

func (app *Application) CreateTicket(w http.ResponseWriter, req *http.Request)

In the main.go , I register the handle functions. main.go ,我注册了句柄功能。

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: 我有以下问题:

  1. Is this design a good practice? 这种设计是一种很好的做法吗? If not, what is the right way? 如果没有,那么正确的方法是什么?
  2. 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. 在Donovan和Kernighan的Go编程书第194页中,他们给出了一个示例,其中http处理程序直接定义为数据库的方法。 Would that be a better design? 这会是一个更好的设计吗? It makes sense because my server package only works for data types in ticket . 这是有道理的,因为我的server包仅适用于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. 另一方面,它混合了http和数据库,我不确定它是否是一件好事。
  3. 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? 我应该创建另一个main.go ,它只创建数据库表并将其构建为可执行文件,这样我只能在服务器上运行一次吗?
  1. I think making 2 packages is a bad decision based on what you've described. 我认为根据你所描述的内容制作2个包是一个糟糕的决定。 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. 如果您不确定,请始终选择更简单的解决方案。

  2. I don't think having 2 packages is cleaner or that it mixes less. 我不认为有2个包装更清洁或混合更少。 You can have your package stuff on several different files, and functions as methods of different structs. 您可以将包中的东西放在几个不同的文件中,并作为不同结构的方法。

  3. 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() . 以幂等方式定义数据库初始化(例如,CREATE SCHEMA IF NOT NOT EXISTS,CREATE TABLE IF NOT NOT EXISTS)并在main.go开头每次运行它,就在db.Ping() Should be milliseconds most of the time, and you ensure that the db always has the structure you expect. 大多数情况下应该是毫秒,并确保db始终具有您期望的结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM