2014-12-24 4 views
0

TLDR Здесь есть детская площадка, которая демонстрирует проблемы, если вы попытаетесь запустить его: https://play.golang.org/p/myQtUVg1iqОпределение метода интерфейса с типом возвращаемого интерфейса

Я делаю REST API и имеют много видов ресурсов, которые могут быть получены через запрос GET

GET http://localhost/api/users 
GET http://localhost/api/groups 

у меня есть пакет моделей, которые абстрагируют как реализуются различные ресурсы:

func(m *UserManager) Get() []Users { 
    // Internal logic, assume returns correct results 
} 

func(m *GroupManager) Get() []Groups { 
    // Internal logic, assume returns correct results 
} 

A маршруты файлы расстановки всех маршрутов и обработчики:

users := models.UserManager{} 
groups := models.GroupManager{} 

func GetUsersHandler (w http.ResponseWriter, r *http.Request) { 
    users := users.Get() 
    // Implementation details, writing to w as JSON 
} 

func GetGroupsHandler (w http.ResponseWriter, r *http.Request) { 
    groups := groups.Get() 
    // Implementation details, writing to w as JSON 
} 

func registerRoutes(r *mux.Router) { 
    r.handleFunc("/api/users", GetUsersHandler).Method("GET") 
    r.handleFunc("/api/groups", GetGroupsHandler).Method("GET") 
} 

Я пытаюсь сделать это более общим путем создания интерфейса, а затем только нуждаясь один GetHandler. Что-то вроде этого:

type Getter interface { 
    Get() []interface{} 
} 

func GetHandler(g Getter) { 
    return func(w http.ResponseWriter, r *http.Request) { 
     results := g.Get() 
     // Implementation details, writing to w as JSON 
    } 
} 

func registerRoutes(r *mux.Router) { 
    r.handleFunc("/api/users", GetHandler(&users)).Method("GET") 
    r.handleFunc("/api/groups", GetHandler(&groups)).Method("GET") 
} 

Это очень близко к работе, единственной проблемой является тип возвращаемого из моделей представляет собой особый тип объекта, но интерфейс просто использует тип возвращаемого интерфейса. Есть ли способ решить эту проблему, не возвращая модели []interface{}?

https://play.golang.org/p/myQtUVg1iq

+0

Не полный ответ, но этот вопрос может быть полезным: http://stackoverflow.com/questions/3839335/any-sensible-solution-to-the-lack-of-array-slice-covariance-in-go – Boushley

+0

В частности, этот ответ: http://stackoverflow.com/a/3844983/86018 может быть полезным. – Boushley

ответ

0

Я полностью избегал этой проблемы, и вместо того, чтобы пытаться уменьшить количество кода, я использую новую функцию go generate в Go 1.4 для создания кода, необходимого для каждого ресурса.

0

Старайтесь не подходить к проблеме, как вы бы другие языки объектно-ориентированного программирования. У вас нет ковариантных контейнеров в Go, поэтому вам нужно либо использовать пустой interface{}, либо вам придется структурировать свою программу по-разному.

Если Get методы различны, и вы хотите типов групп в интерфейсе, используйте другой метод (иногда даже Nööp методы только для интерфейсов), или просто передать в users или groups как interface{}. В любом случае вам понадобится сделать переключатель типа или утверждение в какой-то момент в цепочке вызовов, и как только вы поймете, какой тип это вы можете обработать соответствующим образом.

Трудно сказать без кода, но в этом случае самый простой путь может состоять только в том, чтобы каждый тип был сам http.Handler, и он может отправляться соответствующим образом.

Смежные вопросы