2016-09-25 125 views
1

从Java背景来看,我对Golang中通常做的事情有些疑问。我正在专门讨论服务和dao /仓库。在java中,我会使用依赖注入(可能作为单例/应用程序范围),并有一个服务注入我的休息端点/资源。Golang服务/ daos实现

给予更多的上下文。想象一下以下Golang代码:

func main() { 
    http.ListenAndServe("localhost:8080", nil) 
} 

func init() { 
    r := httptreemux.New() 
    api := r.NewGroup("/api/v1") 
    api.GET("/blogs", GetAllBlogs) 
    http.Handle("/", r) 
} 

直接从我的代码,主要和init被分割,因为谷歌应用程序引擎复制本。

所以现在我有一个处理程序。在该处理程序中,我希望与BlogService进行交互。

问题是,在哪里,在什么范围内应该实例化一个BlogService结构和一个类似于数据结构的dao?

我应该每次处理程序被触发,或使其为常量/全局?

为了完整起见,这里是处理器和blogService:

// GetAllBlogs Retrieves all blogs from GCloud datastore 
func GetAllBlogs(w http.ResponseWriter, req *http.Request, params map[string]string) { 
    c := appengine.NewContext(req) 
    // need a reference to Blog Service at this point, where to instantiate? 
} 

type blogService struct{} 

// Blog contains the content and meta data for a blog post. 
type Blog struct {...} 

// newBlogService constructs a new service to operate on Blogs. 
func newBlogService() *blogService { 
    return &blogService{} 
} 

func (s *blogService) ListBlogs(ctx context.Context) ([]*Blog, error) { 
    // Do some dao-ey/repository things, where to instantiate BlogDao? 
} 

回答

2

可以请求过程中使用context.Context传递请求范围(在Go 1.7提供)值到您的处理程序,如果你建立你的所有需要​​的依赖/响应周期(您应该避免竞争条件,除了自己管理并发性的依赖关系(如sql.DB))。把你所有的服务整合到例如一个容器中,然后查询上下文该值:

container := request.Context.Value("container").(*Container) 
blogs,err := container.GetBlogService().ListBlogs() 

阅读下列材料:

https://golang.org/pkg/context/

https://golang.org/pkg/net/http/#Request.Context

+0

非常感谢您的回答。有了请求/响应周期,你的意思是为每个请求实例化一个服务吗?如果是这样,为什么不直接在处理程序中实例化,而是将它传递给它?这对我来说并不完全清楚。对不起,我的困惑。 –

+0

如果你想堆叠中间件并在那之间共享信息会怎样? – mpm

+0

好点。为了确保我理解正确;使用上下文包的Background函数创建非零空上下文,在容器结构中初始化和加载服务,将该容器结构放在上下文中,并在处理程序中使用它? –