如何在遵守接口上的golang CodeReviewComments规则的同时强制执行正确的构造?

The Interfaces rule in the official Go Code Review Comments document says that packages should return concrete types rather than interfaces. The motivation for this is so that:

...new methods can be added to implementations without requiring extensive refactoring.

which I accept could be a good thing.

But what if a type I'm writing has a dependency without which it cannot serve its purpose? If I export the concrete type, developers will be able to instantiate instances without that dependency. To code defensively for the missing dependency, I then have to check for it in every method implementation and return errors if it is absent. If the developer missed any hints not to do this in my documentation, she or he won't learn about the problem until run time.

On the other hand, if I declare and return an interface with the methods the client needs, I can unexport the concrete type and enforce the use of a factory method which accepts the dependency as an argument and returns the interface plus an error. This seems like a better way to ensure correct use of the package.

Am I somehow not properly getting into the go spirit by thinking like this? Is the ethic of the language that it's okay to have a less-than-perfect encapsulation to give more flexibility to developers?

You may expect developers to read the doc you provide, and you may rely on them following the rules you set. Yes, lazy developers will bump their head from time to time, but the process of developing isn't without having to learn. Everything cannot be made explicit or enforced, and that's all right.

If you have an exported struct type Example and you provide a constructor function NewExample(), that's a clear indication that NewExample() should be used to construct values of Example. Anyone attempting to construct Example manually is expected to know what fields must be set for it to be "operational". The aim is always to make the zero value fully functional, but if that can't be achieved, the constructor function is the idiomatic way to go.

This isn't uncommon, there are countless examples in the standard library, e.g. http.Request, json.Encoder, json.Decoder, io.SectionReader, template.Template.

What you must ensure is that if your package returns values of your structs, they must (should) be properly initialized. And also if others are expected to pass values of your structs created by them, you must provide an easy way for them to create valid values of your structs (constructor function). Whether the custom struct values other developers create themselves are "valid", that shouldn't be of your concern.