This is a creation in Article, where the information may have evolved or changed. This article will list a short list of things I would like to get from a good Go library (in no particular order). This is a list of [effective go] (https://golang.org/doc/effective_go.html), [Go Code review] (https://github.com/golang/go/ wiki/codereviewcomments) List and a list of [Go Proverbs] (https://go-proverbs.github.io/). In general, when there are two reasonable ways of doing something, choose the one that does not violate these rules. These rules are violated only when there are very strong reasons. # # relies on the # # Tagged library version to manage your library version using the Git tab. Semantic versioning is a reasonable system. If you have a semantic version of [https://news.ycombinator.com/item?id=13378637], then you are not the target reader of this article:) # # # no non-standard library dependencies This can sometimes be difficult to achieve, but, Managing a library's dependencies makes it easy to upgrade to the latest version, and allows library users to better derive logic from the application. [If you keep the dependency tree fairly small, then you can really make your program easier to maintain. ] (https://youtu.be/PAAkCSZUG1c?t=598) # # # abstract non-standard libraries rely on their own packages this is the inevitable result of the above non-standard library dependency requirements. If your library absolutely needs non-standard library dependencies, try dividing it into two packages: one for core logic, and the other for external dependencies, using the logic of the previous package. For example, if you are writing a package that captures the stack trace of Go and then uploads it to [Amazon's S3] (https://aws.amazon.com/s3/), write two packages. 1. A package captures the stack trace of Go, and then it is delivered to an interface 2. The S3 implementation of the interface used by the first package. The second package simplifies the two-part bonding for the user. This level of abstraction allows users to take advantage of your core functionality while replacing S3 with their own storage tier. The glue operation in the second package avoids adding extra burdens to most people who want to upload their data to S3. The key part here is the two * * separate * * package. This allows users to inject your core logic without contaminating their own dependency trees. # # # Don't use/vendor if your library uses vendor to manage dependencies, then in Package ManagerWhen trying to expand vendor, weird side effects can occur, or vendor pollute your public API, making integration difficult or impossible. If you really need an exact implementation, then [please explicitly copy it] (https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s). # # # Use Dependency management so others can run your test and your library should try not to have external dependencies. However, if you have to, use some type of dependency management to communicate the dependent version of the initial run of your tests, so that the library user can run your unit tests in a consistent way. # # api### No Global mutable state [global mutable State] (https://dev.to/ericnormand/global-mutable-state) makes code difficult to infer, expand, stub, test, and exit. # # # Empty objects have reasonable behavior to make [0 value useful] (https://www.youtube.com/watch?v=PAAkCSZUG1c&t=6m25s). The read operation on the nil instance is consistent with the read behavior on the empty instance many Go internal structures [reflect] (Https://play.golang.org/p/LrkSriba5V) This behavior. # # # is not necessary, avoid constructor functions this is a side effect of getting [0 value useful] (https://www.youtube.com/watch?v=PAAkCSZUG1c&t=6m25s). # # # Minimize the public function to do fewer things the library tends to do better. # # # A small interface with a few functions [the larger the interface, the less abstract] (https://www.youtube.com/watch?v=PAAkCSZUG1c&t=5m17s). # # Accept interface, return structure read [here] (https:// medium.com/@cep21/what-accept-interfaces-return-structs-means-in-go-2fe879e25ee8) for more details. # # # To configure runtime variability without violating the competition if your library maintains a complex state, then just reinitialization, allowing users to modify reasonable configuration parameters while the app is running, is a non-trivial process. # # # I can interface, and no need to import your library's API your library is great, but someday I'll want to get rid of it. Go type System [sometimes causes obstruction] (https://medium.com/statuscode/go-EXPERIENCE-REPORT-GOS-TYPE-SYSTEM-C4D4DFCC964C). However, in general, implicit interfaces are better than static types that are too powerful. If possible, it is a good idea to use the standard library type as the function parameter type and the return value type, so that users can create interfaces based on your structure so that the libraries are replaced later. ' ' Gotype avoidthis struct {} type Key string func (a *avoidthis) Convert (k Key) {...} ' ' ' Gotype preferthis struct {} func (P *preferthis) Convert (k string) {...} The "# # # API call to create the smallest object (GC) CPU is usually avoided, but re-thinking of your API makes it possible to minimize garbage collection during API calls. For example, create an API that does not enforce garbage collection. * * It is easy to optimize the implementation afterwards, but it is almost impossible to optimize the API afterwards. ' Gotype avoidthis struct {} func (a *avoidthis) Bytes () []byte {...} ' ' ' Gotype preferthis struct {} func (P *preferthis) writeto (w Writer) (n Int64, err error) {...} "# # # No side effects import I personally disapprove of creating [Global side effects behavior] (Https://golang.org/doc/effective_go.html#blank_import) based on import [go] (https:// golang.org/pkg/expvar/) [Standard library] (https://golang.org/pkg/net/http/pprof/) mode. This behavior typically involves a globally mutable state, which can cause interesting problems when multiple libraries are included in/vendor, and many custom options are removed. # # # When there is an alternative, avoid using the context. value[my previous post] (https://medium.com/@cep21/how-to-correctly-use-context-context-in-go-1-7-8f2c0fafdf39) There is an extension on this idea. Avoid using complex logic [init function] in # # # init(Https://golang.org/doc/effective_go.html#init) is useful for creating default values, but it is also a logic that users cannot customize or ignore. If there is no good reason, don't take control of your library from the user. Therefore, instead of generating a background goroutine in Init, it is better to let the user explicitly request background behavior. # # # allows injecting global dependencies such as when allowing the user to provide ' HTTP. Client ', do not force the use of ' http '. Defaultclient '. # # # # error # # # Check all errors if your library accepts an interface as input and someone gives you an implementation that returns an error, then the user expects you to check and somehow handle the error, or somehow pass it back to the caller. Checking for errors does not just mean [returning them to the upper call stack] (https://www.youtube.com/watch?v=PAAkCSZUG1c&t=17m25s), although this is sometimes reasonable, but you can record it, Change the return value and use it as a result, using [fallback code] (https://github.com/Netflix/Hystrix/wiki/How-To-Use#Fallback), or simply adding an Intrastat counter, so that Users will know that something has happened * * rather than fail without knowing what's wrong. # # # Through behavior exposes errors, not types this is a library-centric Dave's _assert errors for behaviour, not type. _ 's equivalent description. For more information, see [here] (https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully). # # # Don't panic[just don't] (https://github.com/golang/go/wiki/CodeReviewComments#dont-panic) # # Concurrency Avoid creating goroutine this is by [ Synchronization function in Codereviewcomments] (https://github.com/golang/go/wiki/CodeReviewComments#synchronous-functions) Some of the more explicit rules deduced. The synchronization function provides more control for the library user. Goroutine is sometimes useful when parallelizing logic, but, as a library author, you should never use Goroutine and find out the reasons for using them * * start instead of using Goroutine first, then argue about getting rid of them. # # # allows background goroutine to cleanly stop this is [Goroutine life cycle] (https://github.com/golang/go/wiki/CodeReviewComments# Goroutine-lifetimes) The preferred limit for feedback. There should be a way to end any goroutine created by your library in a way that does not emit false errors. # # # Public API Avoid using channel This is a code odor, [implied concurrency] (https://github.com/golang/go/wiki/CodeReviewComments#synchronous-functions Occurs at the library level, rather than letting your library users control concurrency. # # # All long blocking operations are using the context. Contextcontext is the standard way for your library users to control when they should interrupt operations. # # Debug # # # Export Intrastat information I need to monitor your library's efficiency, usage patterns, and time-consuming. To expose these statistics in some way, so that I can import them into my [favorite] (https://prometheus.io/) [measure] (https://signalfx.com/) [System] (https://grafana.com/). # # # Public Expvar. Var information exposes internal configuration and state information through Expvar, allowing users to quickly debug how their app uses your library, not just how they think they're using it. # # # Support for debugging finally, your library will have errors. Or the user will mistakenly use your library, and then need to figure out why. If your library has any reasonable complexity, then provide a way to debug or track this information. You can use the debug log, or [context Debug mode] (https://medium.com/@cep21/go-1-7-httptrace-and-context-debug-patterns-608ae887224a). # # # reasonable Stringer implementation [Stringer] (https://golang.org/pkg/fmt/#Stringer) It is easier for people to debug your code with your library. # # # Easy-to-customize logger without a widely accepted Go log library. Exposes a log interface, which does not force me to import your favorite log library. # # # code Neat # # # through a fitGometalinter Check subset Go simple syntax and excellent standard library functions allow a wide range of static code inspectors, which are summarized in [Gometalinter] (https://github.com/alecthomas/gometalinter). Your default state, especially when you are Go's little moe new, should just pass through all these inspectors. Only violate them when you can provide them, and then provide two reasonable implementations and choose that one through Linter. # # # no 0% unit test coverage for function 100% test coverage is extreme, and 0% test coverage is hardly a good thing. This is a hard-to-quantify rule, so I've decided that "no function should have 0% test coverage" is the minimum. You can use Go's cover tool to get each function test coverage. "console# Go test-coverprofile=cover.out context OK context 2.651s coverage:97.0% of statements" "console# go Tool Cover-func=cover.out context/context.go:162:error 100.0% context/context.go:163:timeout 100.0% context/context.go : 164:temporary 100.0% context/context.go:170:deadline 100.0% context/context.go:174:done 100.0% context/context.go : 178:err 100% ... "# # Storage Layout # # # Avoid splitting a struct's function into multiple files go allows you to put a structure function in multiple files. This is when using the [Build flag] (Https://dave.cheney.net/2013/10/12/how-to-use-conditional-compilation-with-the-go-build-tool), is very useful, however, if you use it as an organizational structure, then it means that your structure is too large and should be broken down into multiple parts. # # # Use/internal/internal package serious use insufficient. I recommend that both binaries and libraries use/internal to hide the public that you do not intend to importFunction. Hiding your public import space also makes the user more aware of which packages should be imported and where to look for useful logic.
via:https://medium.com/@cep21/aspects-of-a-good-go-library-7082beabb403
Author: Jack Lindamood Translator: Ictar proofreading: Rxcai
This article by GCTT original compilation, go language Chinese network honor launches
This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove
1018 Reads