我一直在研究Golang以构建一个Web应用程序,我喜欢语言和所有内容,但是我无法在golang中围绕结构概念进行思考。它似乎迫使我没有文件结构,没有文件夹,没有分区,没有关注点分离。有没有办法以我看不到的方式组织.go文件?到目前为止,文件结构一直很令人头痛,这是我用这种语言唯一的糟糕体验。谢谢!
答案 0 :(得分:2)
你是部分正确的。 Go不强制执行有关文件和包结构的任何内容,除非它禁止循环依赖。恕我直言,这是一件好事,因为你有自由选择最适合你的套房。
然而,它决定什么是最好的,这给你带来了负担。我尝试了很少的方法,取决于我在做什么(例如库,命令行工具,服务),我相信不同的方法是最好的。
如果您只创建命令行工具,请让root软件包(存储库的根目录)为main
。如果它是小工具,那就是你所需要的。您可能会发生命令行工具增长,因此您可能希望将某些内容分离到自己的内容中,但可以在同一个存储库中进行分配。
如果您要创建库,请执行相同的操作,但包名称将是您的库的名称,而不是main
。
如果你需要组合(这对于库和命令行工具都很有用),我会在VCS根目录中放入库代码(库的所有内容),以及潜在的子包和{{1}为你的二进制文件。
对于网络服务,我发现遵循these指南是最实际的。最好阅读整篇博文,但简而言之 - 在VCS root中定义您的域,创建cmd/toolname
(或多个)作为命令行入口点,并为每个依赖项创建一个包(例如memcache,database,http等) )。您的子包从不明确地相互依赖,它们只共享来自root的域定义。它需要一些习惯,我仍然适应我的用例,但到目前为止看起来很有希望。
答案 1 :(得分:1)
正如@ del-boy所说,这取决于你想做什么,我多次讨论这个问题,但是在开发golang web应用程序时,更适合我的是按照依赖项划分你的包
- myproject
-- cmd
--- main.go
-- http
--- http.go
-- postgres
--- postgres.go
-- mongodb
--- mongodb.go
myproject.go
myproject.go 将包含接口和 Structs ,其中包含主域名或商业模式
例如,你可以在 myproject.go
里面type User struct {
MongoID bson.ObjectId `bson:"_id,omitempty"`
PostgresID string
Username string
}
和这样的界面
type UserService interface {
GetUser(username string) (*User, error)
}
现在,在 http 包中,您将处理公开api端点
//Handler represents an HTTP API interface for our app.
type Handler struct {
Router *chi.Mux // you can use whatever router you like
UserService myproject.UserService
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *Request){
//this just a wrapper for the Router ServeHTTP
h.Router.ServeHTTP(w,r)
}
func (h *Handler) someHandler(w http.ResponseWriter, r *Request){
//get the username from the request
//
user := h.UserService.GetUser(username)
}
在postgres.go中,您可以使用结构来实现 UserService
type PostgresUserService struct {
DB *sql.DB
}
然后实现服务
func (s *PostgresUserService) GetUser(username string) {
//implement the method
}
和mongodb可以做同样的事情
type MongoUserService struct {
Session *mgo.Session
}
func (s *MongoUserService) GetUser(username string) {
//implement the method
}
现在你的cmd / main.go中你可以有类似的东西
func main(){
postgresDB, err := postgres.Connect()
mongoSession, err := mongo.Connect()
postgresService := postgres.PostgresUserService{DB: postgresDB}
mongoService := mongo.MongoUserService{Session: mongoSession}
//then pass your services to your http handler
// based on the underlying service your api will act based on the underlying service you passed
myHandler := http.Handler{}
myHandler.UserService = postgresService
}
假设你更改了底层商店,你只需要在这里更改它,你就不会改变任何东西
这个设计受到了blog的启发,我希望你觉得它很有用