Source File
doc.go
Belonging Package
go.uber.org/dig
// Copyright (c) 2019 Uber Technologies, Inc.//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to deal// in the Software without restriction, including without limitation the rights// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell// copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN// THE SOFTWARE.// Package dig provides an opinionated way of resolving object dependencies.//// # Status//// STABLE. No breaking changes will be made in this major version.//// # Container//// Dig exposes type Container as an object capable of resolving a directed// acyclic dependency graph. Use the New function to create one.//// c := dig.New()//// # Provide//// Constructors for different types are added to the container by using the// Provide method. A constructor can declare a dependency on another type by// simply adding it as a function parameter. Dependencies for a type can be// added to the graph both, before and after the type was added.//// err := c.Provide(func(conn *sql.DB) (*UserGateway, error) {// // ...// })// if err != nil {// // ...// }//// if err := c.Provide(newDBConnection); err != nil {// // ...// }//// Multiple constructors can rely on the same type. The container creates a// singleton for each retained type, instantiating it at most once when// requested directly or as a dependency of another type.//// err := c.Provide(func(conn *sql.DB) *CommentGateway {// // ...// })// if err != nil {// // ...// }//// Constructors can declare any number of dependencies as parameters and// optionally, return errors.//// err := c.Provide(func(u *UserGateway, c *CommentGateway) (*RequestHandler, error) {// // ...// })// if err != nil {// // ...// }//// if err := c.Provide(newHTTPServer); err != nil {// // ...// }//// Constructors can also return multiple results to add multiple types to the// container.//// err := c.Provide(func(conn *sql.DB) (*UserGateway, *CommentGateway, error) {// // ...// })// if err != nil {// // ...// }//// Constructors that accept a variadic number of arguments are treated as if// they don't have those arguments. That is,//// func NewVoteGateway(db *sql.DB, options ...Option) *VoteGateway//// Is treated the same as,//// func NewVoteGateway(db *sql.DB) *VoteGateway//// The constructor will be called with all other dependencies and no variadic// arguments.//// # Invoke//// Types added to the container may be consumed by using the Invoke method.// Invoke accepts any function that accepts one or more parameters and// optionally, returns an error. Dig calls the function with the requested// type, instantiating only those types that were requested by the function.// The call fails if any type or its dependencies (both direct and transitive)// were not available in the container.//// err := c.Invoke(func(l *log.Logger) {// // ...// })// if err != nil {// // ...// }//// err := c.Invoke(func(server *http.Server) error {// // ...// })// if err != nil {// // ...// }//// Any error returned by the invoked function is propagated back to the// caller.//// # Parameter Objects//// Constructors declare their dependencies as function parameters. This can// very quickly become unreadable if the constructor has a lot of// dependencies.//// func NewHandler(users *UserGateway, comments *CommentGateway, posts *PostGateway, votes *VoteGateway, authz *AuthZGateway) *Handler {// // ...// }//// A pattern employed to improve readability in a situation like this is to// create a struct that lists all the parameters of the function as fields and// changing the function to accept that struct instead. This is referred to as// a parameter object.//// Dig has first class support for parameter objects: any struct embedding// dig.In gets treated as a parameter object. The following is equivalent to// the constructor above.//// type HandlerParams struct {// dig.In//// Users *UserGateway// Comments *CommentGateway// Posts *PostGateway// Votes *VoteGateway// AuthZ *AuthZGateway// }//// func NewHandler(p HandlerParams) *Handler {// // ...// }//// Handlers can receive any combination of parameter objects and parameters.//// func NewHandler(p HandlerParams, l *log.Logger) *Handler {// // ...// }//// # Result Objects//// Result objects are the flip side of parameter objects. These are structs// that represent multiple outputs from a single function as fields in the// struct. Structs embedding dig.Out get treated as result objects.//// func SetupGateways(conn *sql.DB) (*UserGateway, *CommentGateway, *PostGateway, error) {// // ...// }//// The above is equivalent to,//// type Gateways struct {// dig.Out//// Users *UserGateway// Comments *CommentGateway// Posts *PostGateway// }//// func SetupGateways(conn *sql.DB) (Gateways, error) {// // ...// }//// # Optional Dependencies//// Constructors often don't have a hard dependency on some types and// are able to operate in a degraded state when that dependency is missing.// Dig supports declaring dependencies as optional by adding an// `optional:"true"` tag to fields of a dig.In struct.//// Fields in a dig.In structs that have the `optional:"true"` tag are treated// as optional by Dig.//// type UserGatewayParams struct {// dig.In//// Conn *sql.DB// Cache *redis.Client `optional:"true"`// }//// If an optional field is not available in the container, the constructor// will receive a zero value for the field.//// func NewUserGateway(p UserGatewayParams, log *log.Logger) (*UserGateway, error) {// if p.Cache == nil {// log.Print("Caching disabled")// }// // ...// }//// Constructors that declare dependencies as optional MUST handle the case of// those dependencies being absent.//// The optional tag also allows adding new dependencies without breaking// existing consumers of the constructor.//// # Named Values//// Some use cases call for multiple values of the same type. Dig allows adding// multiple values of the same type to the container with the use of Named// Values.//// Named Values can be produced by passing the dig.Name option when a// constructor is provided. All values produced by that constructor will have// the given name.//// Given the following constructors,//// func NewReadOnlyConnection(...) (*sql.DB, error)// func NewReadWriteConnection(...) (*sql.DB, error)//// You can provide *sql.DB into a Container under different names by passing// the dig.Name option.//// c.Provide(NewReadOnlyConnection, dig.Name("ro"))// c.Provide(NewReadWriteConnection, dig.Name("rw"))//// Alternatively, you can produce a dig.Out struct and tag its fields with// `name:".."` to have the corresponding value added to the graph under the// specified name.//// type ConnectionResult struct {// dig.Out//// ReadWrite *sql.DB `name:"rw"`// ReadOnly *sql.DB `name:"ro"`// }//// func ConnectToDatabase(...) (ConnectionResult, error) {// // ...// return ConnectionResult{ReadWrite: rw, ReadOnly: ro}, nil// }//// Regardless of how a Named Value was produced, it can be consumed by another// constructor by accepting a dig.In struct which has exported fields with the// same name AND type that you provided.//// type GatewayParams struct {// dig.In//// WriteToConn *sql.DB `name:"rw"`// ReadFromConn *sql.DB `name:"ro"`// }//// The name tag may be combined with the optional tag to declare the// dependency optional.//// type GatewayParams struct {// dig.In//// WriteToConn *sql.DB `name:"rw"`// ReadFromConn *sql.DB `name:"ro" optional:"true"`// }//// func NewCommentGateway(p GatewayParams, log *log.Logger) (*CommentGateway, error) {// if p.ReadFromConn == nil {// log.Print("Warning: Using RW connection for reads")// p.ReadFromConn = p.WriteToConn// }// // ...// }//// # Value Groups//// Added in Dig 1.2.//// Dig provides value groups to allow producing and consuming many values of// the same type. Value groups allow constructors to send values to a named,// unordered collection in the container. Other constructors can request all// values in this collection as a slice.//// Constructors can send values into value groups by returning a dig.Out// struct tagged with `group:".."`.//// type HandlerResult struct {// dig.Out//// Handler Handler `group:"server"`// }//// func NewHelloHandler() HandlerResult {// ..// }//// func NewEchoHandler() HandlerResult {// ..// }//// Any number of constructors may provide values to this named collection.// Other constructors can request all values for this collection by requesting// a slice tagged with `group:".."`. This will execute all constructors that// provide a value to that group in an unspecified order.//// type ServerParams struct {// dig.In//// Handlers []Handler `group:"server"`// }//// func NewServer(p ServerParams) *Server {// server := newServer()// for _, h := range p.Handlers {// server.Register(h)// }// return server// }//// Note that values in a value group are unordered. Dig makes no guarantees// about the order in which these values will be produced.//// Value groups can be used to provide multiple values for a group from a// dig.Out using slices, however considering groups are retrieved by requesting// a slice this implies that the values must be retrieved using a slice of// slices. As of dig v1.9.0, if you want to provide individual elements to the// group instead of the slice itself, you can add the `flatten` modifier to the// group from a dig.Out.//// type IntResult struct {// dig.Out//// Handler []int `group:"server"` // [][]int from dig.In// Handler []int `group:"server,flatten"` // []int from dig.In// }package dig // import "go.uber.org/dig"
![]() |
The pages are generated with Golds v0.8.2. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |