Чистая и общая структура проекта для приложений GO и mongodb
Я хочу создать приложение на основе API, используя GO и MongoDB. Я из Asp.net фон MVC. Вероятно, если я создам архитектуру с веб-приложением MVC, то следует учитывать
-
разделение проблем (SoC)
- DataModel
- BusinessEntities
- BusinessServices
- контроллеры
Dependeny инъекции и единство работы
- единица Тестирование
- MoQ или nUnit
- интеграция с UI framework
- Angularjs или другие
- RESTful urls, который позволяет SEO
ниже архитектура может быть решением для моей потребности в приложениях на основе MVC
есть ресурсы по всему интернету, чтобы построить Asp.Net или приложения на основе Java, но я не нашел решения для Golang архитектура приложения.
Yes GO отличается от C# или Java, но все же есть структуры, интерфейсы для создания многоразового кода и общей архитектуры приложения. Рассмотрите выше моменты в виду, как мы можем сделать чистую и многоразовую структуру проекта в приложениях GO и общих репозиториях для транзакций DB(Mongodb). Любые веб-ресурсы также отличная точка для начала.
5 ответов
это зависит от вашего собственного стиля и правила, в моей компании, мы разрабатываем наши проекты таким образом:
- конфигурация определяется переменными среды, поэтому у нас есть
company/envs/project.sh
файл, который должен быть оценен до сервис (вне проекта на изображении). - добавляем
zscripts
папка, содержащая все дополнительные скрипты, такие как добавление пользователей или публикация сообщения. Предназначен для использования только для отладки предложений. - модели данных (сущности) находятся в пакете с именем
project/models
. - все контроллеры и представления (шаблоны HTML) подразделяются на "приложения" или "модули". Мы используем путь REST в качестве основного разделителя группы, поэтому path
/dogs
идет в пакетproject/apps/dogs
и/cats
toproject/apps/cats
. - менеджеры находятся в отдельном пакете в корне проекта
project/manager
. - статические файлы (.стиль CSS. ,формат PNG. ,js, etc.) находятся в
project/static/[app/]
. Иногда требуется иметь необязательный , но это происходит, только когда два приложения имеют панели мониторинга или конфликтующие имена файлов. В большинстве случаев вам не нужно использовать[app/]
для статических ресурсов.
менеджеры
мы вызываем менеджер, пакет, который содержит чистые функции, которые помогают приложениям выполнять свою задачу,например, базы данных, кэш, хранилище S3 и т. д. Мы инициализируем каждый вызов менеджера package.Startup()
прежде чем мы начнем слушать, и завершить вызов package.Finalize()
когда программа прерванный.
примером менеджера может быть project/cache/cache.go
:
type Config struct {
RedisURL string `envconfig:"redis_url"`
}
var config Config
var client *redis.Client
func Startup(c Config) error {
config = c
client, err := redis.Dial(c.RedisURL)
return err
}
func Set(k,v string) error {
return client.Set(k, v)
}
в Main.go (или your_thing_test.go):
var spec cache.Config
envconfig.Process("project", &spec)
cache.Startup(spec)
и в приложении (или модуле):
func SetCacheHandler(_ http.ResponseWriter, _ *http.Request){
cache.Set("this", "rocks")
}
модули
модуль-это контейнер представлений и контроллеров, изолированных от других модулей, используя нашу конфигурацию, я бы рекомендовал не создавать зависимости между модулями. Модули также называются приложениями.
каждый модуль настраивает свои маршруты с помощью маршрутизатора, суб-маршрутизатора или того, что предоставляет ваша платформа, например (file project/apps/dogs/configure.go
):
func Configure(e *echo.Echo) {
e.Get("/dogs", List)
}
тогда все обработчики живут в project/apps/dogs/handlers.go
:
// List outputs a dog list of all stored specimen.
func List(c *echo.Context) error {
// Note the use of models.Xyz
var res := make([]models.Dog, 0) // A little trick to not return nil.
err := store.FindAll("dogs", nil, &res) // Call manager to find all dogs.
// handle error ...
return c.JSON(200, res) // Output the dogs.
}
наконец, вы настраиваете приложение в main (или в тесте):
e := echo.New()
dogs.Configure(e)
// more apps
e.Run(":8080")
Примечание: Для видов, вы можете добавить их в project/apps/<name>/views
папка и настроить их с помощью той же функции.
другое
иногда мы также добавляем project/constants
и project/utils
пакета.
вот как это выглядит:
обратите внимание, что в приведенном выше примере, templates
отделены от приложений, это потому, что его прототип, каталог пуст.
надеюсь, это было полезно. Привет из Мексики :Д.
Я также боролся о том, как структурировать мой Go Web APIs в прошлом и не знаю никаких веб-ресурсов, которые говорят вам точно, как написать Go web API.
то, что я сделал, это просто проверить другие проекты на Github и попробовать, как они структурировали свой код, например,настройки РЕПО имеет очень idomatic код перейти на его API.
и похожа на любой - это RESTful framework, который генерирует структуру проекта для вас способом MVC и согласно их docs, Он также может использоваться для API.
Я построение веб-интерфейсов в golang для некоторое время теперь.
вам придется провести некоторые исследования, но я могу дать вам некоторые отправные точки:
- создание веб-приложений с Go -- книги
- github.com/julienschmidt/httprouter -- для маршрутизации адресов
- github.com/unrolled/render/ -- для рендеринга различных форм ответов(JSON, HTML и т. д..)
- github.com/dgrijalva/jwt-go -- JSON Web Жетоны
- www.gorillatoolkit.org/pkg/sessions -- управление сеансами
и для справки о том, как некоторые вещи работать вместе в конце:
Go Web API Repo -- личный проект
на мой взгляд, папка проекта webapp на рабочем сервере может выглядеть на вашей картинке намного проще. Ничего особенного в структуре активов-статика, Шаблоны, контент, стили, Img, JSlibs, DBscripts и т. д. обычные папки. Ничего особенного в WebAPI - как обычно, вы разрабатываете, какой URI будет отвечать требуемым функциям и маршрутизировать запросы обработчикам соответственно. Некоторые особенности-многие суслики не верят в архитектуру MVC,это зависит от вас. И вы развернуть один staticaly связаны исполняемый файл без зависимостей. В вашей среде разработки вы структурируете свои и импортированные / вендорные файлы sorce в $GOPATH, как в stdlib, но развертываете только один исполняемый файл в производственной среде, конечно, со статическими активами. Вы можете увидеть, как организовать исходные пакеты Go только в stdlib. Имея только один исполняемый файл, что бы вы структурировали на производстве?
1. Разделение забот (SoC)
я не работал с SoC напрямую, но у меня есть свой шаблон. Вы можете адаптироваться к любому шаблону (MVC, вашему собственному и т. д.).
в моем коде я разделяю свой код на разные пакеты:
myprojectname (package main) — Holds the very basic setup and configuration/project consts
* handlers (package handlers) — Holds the code that does the raw HTTP work
* models (package models) — Holds the models
* apis (NOT a package)
- redis (package redis) — Holds the code that wraps a `sync.Pool`
- twilio (package twilio) — Example of layer to deal with external API
Примечания:
- в каждом пакете, кроме основного, у меня есть
Setup()
функция (с соответствующими аргументами), вызываемая основным пакетом. - для пакетов под
apis
папка, они часто просто инициализируют внешние библиотеки Go. Вы также можете напрямую импортировать существующие библиотеки в обработчики/модели безapis
пакета. -
я настраиваю свой mux как экспортированный глобальный в
handlers
пакет такой...Router := mux.NewRouter()
...а затем создайте файл для каждого URL-адреса (разные методы с одним и тем же URL-адресом находятся в одном файле). В каждом файле, я использую гоу
init()
функция, которая выполняется после глобальных переменных инициализируются (поэтому безопасно использовать маршрутизатор), но доmain()
выполняется (поэтому для main безопасно предположить, что все было настроено). Самое замечательное вinit()
это то, что вы можете иметь столько этих методов, сколько хотите в одном пакете, поэтому они автоматически запускаются при импорте пакета.Main затем импортирует
myprojectname/handlers
а затем служитhandlers.Router
в Main.
2. Инъекция зависимости и единство работы
I не работал с Unity of Work, поэтому я понятия не имею о возможных реализациях Go.
для DI я создаю интерфейс, который будет реализован как реальный объект, так и макетные объекты.
в пакете я добавляю это в корень:
var DatabaseController DatabaseControllerInterface = DefaultController
тогда первую строку каждого теста я могу изменить DatabaseController
что этот тест должен. Когда не тестируется, модульные тесты не должны выполняться, и по умолчанию это DefaultController
.
3. Блок Тестирование
Go обеспечивает встроенное тестирование с помощью . Вы можете использовать go test --cover
также излучать процент покрытия. Вы можете даже покрытие отображается в вашем браузере, выделяя части, которые / не покрыты.
я использую показания/утверждать пакет, чтобы помочь мне с тестированием, где стандартная библиотека не хватает:
// something_test.go
//
// The _test signifies it should only be compiled into a test
// Name the file whatever you want, but if it's testing code
// in a single file, I like to do filename_test.go.
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestMath(t *testing.T) {
assert.Equal(t, 3+1, 4)
}
4. Интеграция с UI рамки
я не видел ни одного углового. Хотя я не использовал его, Go имеет хороший шаблонный движок, встроенный в стандартный lib.
5. RESTful url, что позволяет SEO
опять же, я не могу помочь вам здесь. Это зависит от вас: отправьте правильные коды состояния (не отправляйте 200 со страницей 404, так как вы будете закреплены за дубликатами страниц), не дублируйте страницы (обратите внимание на google.com/something
vs google.com/something/
; надеюсь, ваша структура будет не испортите это), не пытайтесь обмануть поисковую систему и так далее.