Channels are a great feature of Golang but have several footguns that can lead to deadlocks. In particular, if the receiving channel stops processing the messages, a non-blocking channel send would fail to continue. In certain mission-critical sections of code, this could lead to a complete deadlock.
This linter currently has three features:
- Non-blocking sends
- Non-buffered channel creation detection
- Buffered channel size exceeds maximum size checks
Many of these will lead to false positives or situations where we want a blocking channel send. In these cases, nolint:channelcheck
is easy to add. Regardless, having this issue pointed out automatically is a good way to fix bugs; this doesn't necessarily have to be included in CI.
This is the recommended way to use the linter. golangci-lint has a module plugin system that works very well. To install the linter this way, do the following:
- Download this repo locally.
- In your target repo, create a
.custom-gcl.yml
file. Add the following content: NOTE: This can't be directly copied. Use the contents of.example-custom-gcl.yml
.version: v1.64.5 plugins: # a plugin from local source - module: github.com/asymmetric-research/channel_linter/channelcheck path: /Path/to/channelcheck_repo name: golangci-lint-with-channelcheck
- In your
.golangci.yaml
file, add the following and enable the linter. NOTE: This can't be directly copied. Use the contents of.example-golangci.yml
.linters-settings: custom: channelcheck: type: "module" description: Static analysis for go channel issues settings: CheckBlockingSends: true CheckUnbufferedChannels: false
- Build the custom version of
golangci-lint
. This is literally recompiling the linter binary and adding our linter into it.golangci-lint custom -v
- Run the new binary on your repo:
./golangci-lint-with-channelcheck run
- To remove false positives, add
nolint:channelcheck
above the line that had the linter error.
The linter can be used by itself. Simply run the following to install the binary:
go install ./cmd/channellint/main.go
Usage:
channellint ./examples
This is NOT recommended because false positives cannot be tuned out via nolint
comments.