Go Library Design Principles: From Repositories to Resources
Programming involves creating applications and the libraries that support them. A library is a collection of shareable resources, primarily source code. Distinguishing between terms helps in designing robust components.
A repository contains code files within a file system structure. A package in Go is a group of .go files that perform a single task, with a mandatory package declaration at the top of each file. A module groups packages together, with dependencies fixed in go.mod.
A library enables code sharing without duplication. For example: a MaxInt function copied into different packages foo and baz is inefficient without a single source of truth. Packages solve the compilation and import problem.
package foo
func MaxInt(a, b int) int {
if a > b {
return a
}
return b
}
Component isolation prevents knowledge of other code, and decomposition simplifies interaction with the compiler.
Resources in Libraries
Libraries include not only code but also external resources: dynamic and static.
Dynamic resources depend on runtime. An example is GPU access via CUDA in the cu package from Gorgonia:
d := cu.CurrentDevice()
ctx := cu.NewContext(d, cu.SchedAuto|cu.MapHost)
mem, err := ctx.MemAlloc(1024)
Here, ctx is a GPU descriptor for GPGPU tasks. Its state is unknown at compile time.
Static resources are known to the compiler. An example is Shakespeare's texts in the willshakes package:
package willshakes
const AllsWellThatEndsWell = `Act 1 Scene 1
COUNTESS.
In delivering my son from me, I bury a second husband.
...`
const MacBeth = `Act 1 Scene 1
FIRST WITCH.
When shall we three meet again
...`
Access via: willshakes.MacBeth. Similarly for fonts or datasets like MNIST.
Library Classification
Libraries are classified by their resources:
- Code libraries: Shared source code in packages/modules.
- Driver libraries: Wrappers over drivers (cu for CUDA, go-gl for OpenGL).
- Resource libraries: Static data (willshakes) or loaders (mnist in Go).
| Type | Example | Characteristic |
|------|---------|----------------|
| Code | Utility package | Static code |
| Driver | cu | Dynamic access |
| Resource | willshakes | Embedded constants |
Drivers add abstractions for cross-language interaction.
Qualities of a Good Library
A good library facilitates two dialogues: with the machine (compiler/runtime) and with the developer.
Criteria:
- Isolation: Components are unaware of external libraries.
- Decomposition: Clear functional boundaries.
- Composition: Easy integration into applications.
- Predictability: Behavior matches documentation.
- Performance: Minimal overhead without compromises.
Avoid package main in libraries—focus on utilities. Test edge cases, ensure thread safety.
Key Takeaways
- A library is a shareable resource, not just a repository or package.
- Separate static (constants) and dynamic (drivers) resources.
- Ensure isolation so developers can focus on a single task.
- Use Go packages for compilation and modules for dependencies.
- Design for composition: easy import and usage.
— Editorial Team
No comments yet.