go:S1186 "Functions should not be empty": allow self-documented exceptions

I have a small request for this rule - which seems to have a high false-positive rate for various use cases (anecdotal ~90% IME); in this image below it’s a fallback interface-maintaining definition:

Could the rule account for standard naming idioms that already signal intent - e.g. a function prefixed noop/Noop (as in noopAttemptDone above), or a method on a receiver whose type is prefixed Unimplemented?


I know we can also disable the rule, but I’d rather not - that would also hide the occasional real case where someone forgets to implement or document an empty function.

Hello @andy-super

Welcome to the community and thank you for your report!

Could you provide us a few real life examples where you need to implement no-op functions, please? We would like to understand your cases better and provide more accurate solution based on your cases. In Go there is no standard way how to define/mark no-op functions so we need more context here.

Best
Marcin Stachniuk

We use this pattern across several Go interfaces: a type prefixed Noop/noop (also Fake, Disabled in a few places) implements an interface where each method body is intentionally empty. The empty body is the implementation, not a stub someone forgot to fill in.

Some examples:

type noopMonitor struct{}

func (noopMonitor) OnOperation(string) func(error) {
      return func(error) {}
}

func (noopMonitor) OnAuthToken(string) func(error) {
      return func(error) {}
}

func (NoopEmitter) Emit(context.Context, Recipe) {}

func (DisabledSyncer) UpdateSchedule(_ context.Context, _ contract.RetailShop) error {
      return nil
}

func (t *fakeTicker) Stop() {}

We also have some examples where a comment was added purely to satisfy this rule:

// Sonar requires explicit acknowledgement that the empty body is deliberate.
func (noopLogger) Debug(string, map[string]any) { /* no-op */ }
func (noopLogger) Info(string, map[string]any)  { /* no-op */ }
func (noopLogger) Warn(string, map[string]any)  { /* no-op */ }
func (noopLogger) Error(string, map[string]any) { /* no-op */ }

The type name already says everything the comment would say.

It’d help if the rule recognized receiver/type names matching a common “intentionally empty” convention (Noop/NoOp/no_op, Fake, Disabled, Stub, etc.) as self-documenting, or let a project configure such a naming pattern as an exemption, rather than forcing an ignore-comment on every occurrence.

Thank you for your answer.

I can suggest to use mockery or similar mocking library for such cases. And I also understand that in many Go projects implementing no-op stubs is a preferred way of working. Because of that we can implement configuration property for this rule, I created a ticket for it in our internal JIRA.

Best
Marcin Stachniuk

Thanks Marcin.

To be clear: None¹ of these examples are from tests - they are production no-op implementations used at runtime when a feature is disabled, not stand-ins in tests.

¹ Except FakeTicker, which I missed was a test double.

Ok, then the ability to configure the rule make even more sense for you.