Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/github_actions/golangci/golangc…
Browse files Browse the repository at this point in the history
…i-lint-action-4
  • Loading branch information
JacobOaks authored Feb 12, 2024
2 parents d9b211f + ecc5bc7 commit 14fda74
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 31 deletions.
37 changes: 31 additions & 6 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ linters:
- revive
- errorlint

# License header check:
- goheader

linters-settings:
govet:
# These govet checks are disabled by default, but they're useful.
Expand All @@ -30,6 +33,34 @@ linters-settings:
- sortslice
- unusedwrite

goheader:
values:
const:
COMPANY: 'Uber Technologies, Inc.'
regexp:
YEAR_RANGE: '\d{4}(-\d{4})?'
template: |-
Copyright (c) {{ YEAR_RANGE }} {{ COMPANY }}
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.
issues:
# Print all issues reported by all linters.
max-issues-per-linter: 0
Expand Down Expand Up @@ -62,9 +93,3 @@ issues:
- linters: [revive]
path: '_test\.go$'
text: 'should not use dot imports'

# Ignore logger.Sync() errcheck failures in example_test.go
# since those are intended to be uncomplicated examples.
- linters: [errcheck]
path: example_test.go
text: 'Error return value of `logger.Sync` is not checked'
7 changes: 1 addition & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ build:
go build ./...

.PHONY: lint
lint: golangci-lint tidy-lint license-lint fx-lint docs-lint
lint: golangci-lint tidy-lint fx-lint docs-lint

.PHONY: test
test:
Expand Down Expand Up @@ -58,10 +58,6 @@ tidy-lint:
go mod tidy && \
git diff --exit-code -- go.mod go.sum) &&) true

.PHONY: license-lint
license-lint:
./checklicense.sh

.PHONY: fx-lint
fx-lint: $(FXLINT)
@$(FXLINT) ./...
Expand All @@ -76,4 +72,3 @@ $(MDOX): tools/go.mod

$(FXLINT): tools/cmd/fxlint/main.go
cd tools && go install go.uber.org/fx/tools/cmd/fxlint

17 changes: 0 additions & 17 deletions checklicense.sh

This file was deleted.

1 change: 1 addition & 0 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ module.exports = {
{
title: 'Concepts',
children: [
'container.md',
'lifecycle.md',
'modules.md',
],
Expand Down
156 changes: 156 additions & 0 deletions docs/container.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Container

Container is the abstraction responsible for holding all constructors and values.
It’s the primary means by which an application interacts with Fx.
You teach the container about the needs of your application,
how to perform certain operations,
and then you let it handle actually running your application.

Fx does not provide direct access to the container.
Instead, you specify operations to perform on the container
by providing `fx.Option`s to the `fx.New` constructor.

```go
package fx

type App
func New(opts ...Option) *App
func (app *App) Run()

type Option
func Provide(constructors ...interface{}) Option
func Invoke(funcs ...interface{}) Option
```

Check the [API Reference](https://pkg.go.dev/go.uber.org/fx#Option)
for a complete list of options and their behaviors.

## Providing values

You must provide values to the container before you can use them.
Fx provides two ways to provide values to the container:

- `fx.Provide` for values that have a constructor.

```go
fx.Provide(
func(cfg *Config) *Logger { /* ... */ },
)
```

This says that Fx should use this function to construct a `*Logger`,
and that a `*Config` is required to build one.

- `fx.Supply` for pre-built non-interface values.

```go
fx.Provide(
fx.Supply(&Config{
Name: "my-app",
}),
)
```

This says that Fx should use the provided `*Config` as-is.

**Important**: `fx.Supply` is only for non-interface values.
See *When to use fx.Supply* for more details.

Values provided to the container are available to all other constructors.
In the example above, the `*Config` would become available to the `*Logger` constructor,
and the `*Logger` to any other constructors that need it.

### When to use fx.Supply

Usually, `fx.Provide` is the right choice because more often than not,
constructing an object requires its dependencies.
`fx.Supply` is a convenience function for the rare cases where that isn't true:
standalone values that don't depend on anything else.

```go
fx.Provide(func() *Config { return &Config{Name: "my-app"} })
// is the same as
fx.Supply(&Config{Name: "my-app"})
```

However, even then, `fx.Supply` comes with a caveat:
it can only be used for non-interface values.

<details>
<summary>Why can&#39;t I use fx.Supply for interface values?</summary>

This is a technical limitation imposed by the fact that `fx.Supply` has to rely
on runtime reflection to determine the type of the value.

Passing an interface value to `fx.Supply` is a lossy operation:
it loses the original interface type, only giving us `interface{}`,
at which point reflection will only reveal the concrete type of the value.

For example, consider:

```go
var svc RepositoryService = &repoService{ ... }
```

If you were to pass `svc` to `fx.Supply`,
the container would only know that it's a `*repoService`,
and it will not know that you intend to use it as a `RepositoryService`.
</details>
## Using values
Providing values to the container only makes them available to the application.
It doesn't do anything with them yet.
Constructors passed to `fx.Provide` are not called until they are needed.

For example, the following won't do anything:
```go
fx.New(
fx.Provide(newHTTPServer), // provides an *http.Server
).Run()
```
You next have to tell the container what is needed, and what to do with it.
Fx provides [`fx.Invoke`](https://pkg.go.dev/go.uber.org/fx#Invoke) for this purpose.
In the example above, we'll want an invocation that starts the server:

```go
fx.New(
fx.Provide(newHTTPServer),
fx.Invoke(startHTTPServer),
).Run()
```

### When to use fx.Invoke

`fx.Invoke` is typically used for root-level invocations,
like starting a server or running a main loop.
It's also useful for invoking functions that have side effects.
Examples of cases where you might use `fx.Invoke`:
- Starting a background worker
- Configuring a global logger
As an example, consider an application organized into many distinct abstractions.
```mermaid
flowchart LR
CacheWarmer --> Redis
Server[http.Server] --> UserHandler & PostHandler
UserHandler --> Redis[redis.Client] & Client[http.Client]
PostHandler --> sqlDB[sql.DB]
subgraph Roots
CacheWarmer
Server
end
```
`CacheWarmer` and `http.Server` are the roots of the application.
We'll need `fx.Invoke` for the side effects of starting the server
and the cache warmer loop.
Everything else will be handled by the container automatically.
2 changes: 1 addition & 1 deletion signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//
// 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 PURPSignalE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// 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
Expand Down
2 changes: 1 addition & 1 deletion signal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//
// 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 PURPSignalE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// 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
Expand Down

0 comments on commit 14fda74

Please sign in to comment.