2017-08-05 49 views
0

我一直在尋找到golang爲了建立一個網絡應用程序,我喜歡語言和一切,但我遇到了麻煩,圍繞着golang結構的概念。看起來這幾乎迫使我沒有文件結構,沒有文件夾,沒有劃分,也沒有分離關注點。有沒有辦法以我沒有看到的方式組織.go文件?到目前爲止,文件構造一直令人頭疼,這是我對這門語言唯一不好的體驗。謝謝!golang foment沒有文件結構嗎?

+2

沒有你看看:https://golang.org/doc/code.html? –

+0

是的,我做了,從我收集如果我會使用MVC模式,我將不得不創建一個控制器和模型的包是正確的?但arent軟件包應該用於多個系統? – Amirgem

+0

https://github.com/gernest/utron可能是一個很好的例子 –

回答

2

你是部分權利。 Go不強制執行關於文件和包結構的任何內容,只是它禁止循環依賴。恕我直言,這是一件好事,因爲你有自由選擇你最好的套房。

但是,它決定什麼是最好的負擔。我嘗試了幾種方法,並根據我在做什麼(例如庫,命令行工具,服務),我認爲不同的方法是最好的。

如果您只創建命令行工具,請讓根包(您的存儲庫的根目錄)爲main。如果它是小工具,那就是你所需要的。可能會發生命令行工具不斷增長的情況,因此您可能需要將某些內容分離到自己的內容中,但可能並非必須位於同一個存儲庫中。

如果您正在創建庫,請執行相同的操作,但包名稱不是您的庫的名稱,而是main

如果您需要組合(作爲庫和命令行工具都有用),我會將庫代碼(庫中的所有內容)放入VCS根目錄,並附帶潛在的子包和cmd/toolname二進制文件。

當談到網絡服務時,我發現遵循these準則是最實際的。最好閱讀整篇博客文章,但總之 - 在VCS根目錄下定義您的域,創建cmd/app(或多個)作爲命令行入口點併爲每個依賴項(例如memcache,數據庫,http等)創建一個包。你的子包永遠不會明確地相互依賴,它們只從根共享域定義。這需要一些習慣,我仍然在適應我的用例,但到目前爲止它看起來很有希望。

+1

這就是一個有趣的方式,我正在採取另一種方法,讓我的處理程序在一個獨立的包中共享結構和數據庫服務,並將其導入我的主要 – Amirgem

1

正如@德爾男孩說,這取決於你想要做什麼,我多次去了這個問題,但什麼適合我更多的時候開發golang web應用程序是依賴於將你的包

- myproject 
-- cmd 
--- main.go 
-- http 
--- http.go 
-- postgres 
--- postgres.go 
-- mongodb 
--- mongodb.go 
myproject.go 

myproject.go將包含接口的Structs包含的主要領域或業務模式

例如,你可以有內部myproje ct.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的接口。去了你就可以有一個結構實現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啓發,我希望你覺得它有用

+0

您的結構實際上給了我一個想法,因爲現在我是對於簡單的東西有長代碼的問題,連接,查詢,故事到一個切片,併發送到模板的單個文件,也包含我的結構正在玩我的ocd,我試圖找到一個很好的方式來分開這些轉換爲結構體包(例如模型)或使用服務來調用數據庫,並將查詢和存儲處理成片 – Amirgem

+0

我建議你把這些模型在接口定義的項目根目錄中,並且對於需要提供某種服務的每個程序包,都應該實現它(滿足界面的精確性) – Ibraheam