• A package is a folder that contains a bunch of go files, a bunch of packages is known as a module, defined by a go.mod file.

    • A package is a directory inside your $GOPATH/src directory containing, amongst other things, .go source files.
    • Package names should be all lower case and only letters.
  • All the files in a package’s directory must have the same package declaration.

  • You can pick almost any string as your module path but focus on uniqueness to avoid potential import conflict with other people’s projects or the standard library in the future.

    • You want to pick a path that is globally unique, a common convention is to base your module paths on a URL that you own.

      app.hamada.com
      
  • You can view Go's packages documentations using go doc package-name (e.g., go doc fmt).

  • Package main will only contain integration of other packages and not unit-testable code.

  • Go is good for tooling because it is simple with syntax that is easy to parse, built-in packages for parsing + formatting code, and has tools like gofmt, godoc, and gofix because of this design.

  • Go uses naming conventions to control visibility (exported vs unexported identifiers):

    • Identifiers that start with an uppercase letter are exported (public) and can be accessed from other packages.
    • Identifiers that start with a lowercase letter are unexported (private to the package they are defined in).
    • This applies to variables, constants, functions, methods, structs, interfaces, and fields.
    package wallet
    
    type Wallet struct {      // exported
        balance int          // unexported
    }
    
    func (w *Wallet) Deposit(amount int) {} // exported
    func (w *Wallet) reset() {}             // unexported
    
    • Code in another package can use Wallet and Deposit, but cannot access balance or call reset.

    • Go does not have public or private keywords; capitalization determines visibility.

    • To access exported identifiers from another package, import the package and reference them using dot notation:

      package main
      
      import "example/wallet"
      
      func main() {
          w := wallet.Wallet{} // OK: Wallet is exported
      
          w.Deposit(100)       // OK: Deposit is exported
      
          // w.balance = 100   // ERROR: balance is unexported
          // w.reset()         // ERROR: reset is unexported
      }