doc.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. // Copyright (c) 2019 Uber Technologies, Inc.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. // Package dig provides an opinionated way of resolving object dependencies.
  21. //
  22. // Status
  23. //
  24. // STABLE. No breaking changes will be made in this major version.
  25. //
  26. // Container
  27. //
  28. // Dig exposes type Container as an object capable of resolving a directed
  29. // acyclic dependency graph. Use the New function to create one.
  30. //
  31. // c := dig.New()
  32. //
  33. // Provide
  34. //
  35. // Constructors for different types are added to the container by using the
  36. // Provide method. A constructor can declare a dependency on another type by
  37. // simply adding it as a function parameter. Dependencies for a type can be
  38. // added to the graph both, before and after the type was added.
  39. //
  40. // err := c.Provide(func(conn *sql.DB) (*UserGateway, error) {
  41. // // ...
  42. // })
  43. // if err != nil {
  44. // // ...
  45. // }
  46. //
  47. // if err := c.Provide(newDBConnection); err != nil {
  48. // // ...
  49. // }
  50. //
  51. // Multiple constructors can rely on the same type. The container creates a
  52. // singleton for each retained type, instantiating it at most once when
  53. // requested directly or as a dependency of another type.
  54. //
  55. // err := c.Provide(func(conn *sql.DB) *CommentGateway {
  56. // // ...
  57. // })
  58. // if err != nil {
  59. // // ...
  60. // }
  61. //
  62. // Constructors can declare any number of dependencies as parameters and
  63. // optionally, return errors.
  64. //
  65. // err := c.Provide(func(u *UserGateway, c *CommentGateway) (*RequestHandler, error) {
  66. // // ...
  67. // })
  68. // if err != nil {
  69. // // ...
  70. // }
  71. //
  72. // if err := c.Provide(newHTTPServer); err != nil {
  73. // // ...
  74. // }
  75. //
  76. // Constructors can also return multiple results to add multiple types to the
  77. // container.
  78. //
  79. // err := c.Provide(func(conn *sql.DB) (*UserGateway, *CommentGateway, error) {
  80. // // ...
  81. // })
  82. // if err != nil {
  83. // // ...
  84. // }
  85. //
  86. // Constructors that accept a variadic number of arguments are treated as if
  87. // they don't have those arguments. That is,
  88. //
  89. // func NewVoteGateway(db *sql.DB, options ...Option) *VoteGateway
  90. //
  91. // Is treated the same as,
  92. //
  93. // func NewVoteGateway(db *sql.DB) *VoteGateway
  94. //
  95. // The constructor will be called with all other dependencies and no variadic
  96. // arguments.
  97. //
  98. // Invoke
  99. //
  100. // Types added to to the container may be consumed by using the Invoke method.
  101. // Invoke accepts any function that accepts one or more parameters and
  102. // optionally, returns an error. Dig calls the function with the requested
  103. // type, instantiating only those types that were requested by the function.
  104. // The call fails if any type or its dependencies (both direct and transitive)
  105. // were not available in the container.
  106. //
  107. // err := c.Invoke(func(l *log.Logger) {
  108. // // ...
  109. // })
  110. // if err != nil {
  111. // // ...
  112. // }
  113. //
  114. // err := c.Invoke(func(server *http.Server) error {
  115. // // ...
  116. // })
  117. // if err != nil {
  118. // // ...
  119. // }
  120. //
  121. // Any error returned by the invoked function is propagated back to the
  122. // caller.
  123. //
  124. // Parameter Objects
  125. //
  126. // Constructors declare their dependencies as function parameters. This can
  127. // very quickly become unreadable if the constructor has a lot of
  128. // dependencies.
  129. //
  130. // func NewHandler(users *UserGateway, comments *CommentGateway, posts *PostGateway, votes *VoteGateway, authz *AuthZGateway) *Handler {
  131. // // ...
  132. // }
  133. //
  134. // A pattern employed to improve readability in a situation like this is to
  135. // create a struct that lists all the parameters of the function as fields and
  136. // changing the function to accept that struct instead. This is referred to as
  137. // a parameter object.
  138. //
  139. // Dig has first class support for parameter objects: any struct embedding
  140. // dig.In gets treated as a parameter object. The following is equivalent to
  141. // the constructor above.
  142. //
  143. // type HandlerParams struct {
  144. // dig.In
  145. //
  146. // Users *UserGateway
  147. // Comments *CommentGateway
  148. // Posts *PostGateway
  149. // Votes *VoteGateway
  150. // AuthZ *AuthZGateway
  151. // }
  152. //
  153. // func NewHandler(p HandlerParams) *Handler {
  154. // // ...
  155. // }
  156. //
  157. // Handlers can receive any combination of parameter objects and parameters.
  158. //
  159. // func NewHandler(p HandlerParams, l *log.Logger) *Handler {
  160. // // ...
  161. // }
  162. //
  163. // Result Objects
  164. //
  165. // Result objects are the flip side of parameter objects. These are structs
  166. // that represent multiple outputs from a single function as fields in the
  167. // struct. Structs embedding dig.Out get treated as result objects.
  168. //
  169. // func SetupGateways(conn *sql.DB) (*UserGateway, *CommentGateway, *PostGateway, error) {
  170. // // ...
  171. // }
  172. //
  173. // The above is equivalent to,
  174. //
  175. // type Gateways struct {
  176. // dig.Out
  177. //
  178. // Users *UserGateway
  179. // Comments *CommentGateway
  180. // Posts *PostGateway
  181. // }
  182. //
  183. // func SetupGateways(conn *sql.DB) (Gateways, error) {
  184. // // ...
  185. // }
  186. //
  187. // Optional Dependencies
  188. //
  189. // Constructors often don't have a hard dependency on some types and
  190. // are able to operate in a degraded state when that dependency is missing.
  191. // Dig supports declaring dependencies as optional by adding an
  192. // `optional:"true"` tag to fields of a dig.In struct.
  193. //
  194. // Fields in a dig.In structs that have the `optional:"true"` tag are treated
  195. // as optional by Dig.
  196. //
  197. // type UserGatewayParams struct {
  198. // dig.In
  199. //
  200. // Conn *sql.DB
  201. // Cache *redis.Client `optional:"true"`
  202. // }
  203. //
  204. // If an optional field is not available in the container, the constructor
  205. // will receive a zero value for the field.
  206. //
  207. // func NewUserGateway(p UserGatewayParams, log *log.Logger) (*UserGateway, error) {
  208. // if p.Cache == nil {
  209. // log.Print("Logging disabled")
  210. // }
  211. // // ...
  212. // }
  213. //
  214. // Constructors that declare dependencies as optional MUST handle the case of
  215. // those dependencies being absent.
  216. //
  217. // The optional tag also allows adding new dependencies without breaking
  218. // existing consumers of the constructor.
  219. //
  220. // Named Values
  221. //
  222. // Some use cases call for multiple values of the same type. Dig allows adding
  223. // multiple values of the same type to the container with the use of Named
  224. // Values.
  225. //
  226. // Named Values can be produced by passing the dig.Name option when a
  227. // constructor is provided. All values produced by that constructor will have
  228. // the given name.
  229. //
  230. // Given the following constructors,
  231. //
  232. // func NewReadOnlyConnection(...) (*sql.DB, error)
  233. // func NewReadWriteConnection(...) (*sql.DB, error)
  234. //
  235. // You can provide *sql.DB into a Container under different names by passing
  236. // the dig.Name option.
  237. //
  238. // c.Provide(NewReadOnlyConnection, dig.Name("ro"))
  239. // c.Provide(NewReadWriteConnection, dig.Name("rw"))
  240. //
  241. // Alternatively, you can produce a dig.Out struct and tag its fields with
  242. // `name:".."` to have the corresponding value added to the graph under the
  243. // specified name.
  244. //
  245. // type ConnectionResult struct {
  246. // dig.Out
  247. //
  248. // ReadWrite *sql.DB `name:"rw"`
  249. // ReadOnly *sql.DB `name:"ro"`
  250. // }
  251. //
  252. // func ConnectToDatabase(...) (ConnectionResult, error) {
  253. // // ...
  254. // return ConnectionResult{ReadWrite: rw, ReadOnly: ro}, nil
  255. // }
  256. //
  257. // Regardless of how a Named Value was produced, it can be consumed by another
  258. // constructor by accepting a dig.In struct which has exported fields with the
  259. // same name AND type that you provided.
  260. //
  261. // type GatewayParams struct {
  262. // dig.In
  263. //
  264. // WriteToConn *sql.DB `name:"rw"`
  265. // ReadFromConn *sql.DB `name:"ro"`
  266. // }
  267. //
  268. // The name tag may be combined with the optional tag to declare the
  269. // dependency optional.
  270. //
  271. // type GatewayParams struct {
  272. // dig.In
  273. //
  274. // WriteToConn *sql.DB `name:"rw"`
  275. // ReadFromConn *sql.DB `name:"ro" optional:"true"`
  276. // }
  277. //
  278. // func NewCommentGateway(p GatewayParams, log *log.Logger) (*CommentGateway, error) {
  279. // if p.ReadFromConn == nil {
  280. // log.Print("Warning: Using RW connection for reads")
  281. // p.ReadFromConn = p.WriteToConn
  282. // }
  283. // // ...
  284. // }
  285. //
  286. // Value Groups
  287. //
  288. // Added in Dig 1.2.
  289. //
  290. // Dig provides value groups to allow producing and consuming many values of
  291. // the same type. Value groups allow constructors to send values to a named,
  292. // unordered collection in the container. Other constructors can request all
  293. // values in this collection as a slice.
  294. //
  295. // Constructors can send values into value groups by returning a dig.Out
  296. // struct tagged with `group:".."`.
  297. //
  298. // type HandlerResult struct {
  299. // dig.Out
  300. //
  301. // Handler Handler `group:"server"`
  302. // }
  303. //
  304. // func NewHelloHandler() HandlerResult {
  305. // ..
  306. // }
  307. //
  308. // func NewEchoHandler() HandlerResult {
  309. // ..
  310. // }
  311. //
  312. // Any number of constructors may provide values to this named collection.
  313. // Other constructors can request all values for this collection by requesting
  314. // a slice tagged with `group:".."`. This will execute all constructors that
  315. // provide a value to that group in an unspecified order.
  316. //
  317. // type ServerParams struct {
  318. // dig.In
  319. //
  320. // Handlers []Handler `group:"server"`
  321. // }
  322. //
  323. // func NewServer(p ServerParams) *Server {
  324. // server := newServer()
  325. // for _, h := range p.Handlers {
  326. // server.Register(h)
  327. // }
  328. // return server
  329. // }
  330. //
  331. // Note that values in a value group are unordered. Dig makes no guarantees
  332. // about the order in which these values will be produced.
  333. //
  334. // Value groups can be used to provide multiple values for a group from a
  335. // dig.Out using slices, however considering groups are retrieved by requesting
  336. // a slice this implies that the values must be retrieved using a slice of
  337. // slices. As of dig v1.9.0, if you want to provide individual elements to the
  338. // group instead of the slice itself, you can add the `flatten` modifier to the
  339. // group from a dig.Out.
  340. //
  341. // type IntResult struct {
  342. // dig.Out
  343. //
  344. // Handler []int `group:"server"` // [][]int from dig.In
  345. // Handler []int `group:"server,flatten"` // []int from dig.In
  346. // }
  347. //
  348. package dig // import "go.uber.org/dig"