Skip to Content
Course content

39: Organizing Code into Packages

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Wait, does my folder name have to match the package name?

Technically? No. But in practice? Yes. Absolutely yes. If you try to name your folder billing_logic but put package payments at the top of the files inside it, you're going to confuse every other developer on your team—and probably yourself in two weeks.

In Go, the convention is that the package name should match the directory name. When you import something, you use the path to the directory, but you refer to the package by the name declared in the source file. If they differ, your import looks like this: import "myapp/billing_logic", but you call the functions using payments.DoSomething(). It's jarring and unnecessary. Just keep them the same.

I'm trying to use a function from another package, but Go says it's undefined. What's going on?

This is the "aha!" moment for most people learning Go. Go doesn't have public or private keywords like Java or C#. Instead, it uses capitalization. If a function, struct, or variable starts with an uppercase letter, it's exported (public). If it starts with a lowercase letter, it's unexported (private to that package).

Let's look at a payment processor example. If I'm building a payments package, I want the outside world to trigger a payment, but I don't want them messing with my internal validation logic.

// payments/processor.go
package payments

// ProcessPayment is exported because it starts with 'P'
func ProcessPayment(amount float64) bool {
    if validateAmount(amount) {
        // logic to hit a gateway...
        return true
    }
    return false
}

// validateAmount is unexported because it starts with 'v'
func validateAmount(amount float64) bool {
    return amount > 0
}

If you try to call payments.validateAmount(10.0) from your main.go, the compiler will yell at you. I personally love this approach because it forces you to think about your package's public API before you even write the code.

Can I put multiple packages in one folder?

Short answer: No. You can't. Every single file in a directory must belong to the same package. If you try to mix package payments and package shipping in the same folder, the Go toolchain will throw a fit.

If you feel like a folder is getting too crowded or your package is doing too many things, that's your signal to create a sub-directory. For example, if your payments package is getting huge, you might move the credit card logic into payments/stripe and the PayPal logic into payments/paypal. Each of those sub-directories becomes its own package.

Just be careful: Go does not allow circular dependencies. If package A imports package B, then package B cannot import package A. If you hit this wall, it usually means your packages are too tightly coupled and you need to extract the shared logic into a third, smaller package that both A and B can depend on.




📋 Practical Task

Build a Multi-Package Currency Converter

Your goal is to move the logic for currency conversion out of the main package and into its own dedicated package to practice visibility and organization.

  • Create a folder named converter.
  • Inside converter/converter.go, create a package named converter.
  • Implement a struct called ExchangeRate with an exported field Rate.
  • Implement an exported function Convert(amount float64, ex ExchangeRate) float64 that returns the converted amount.
  • Implement an unexported helper function logTransaction(amount float64) that simply prints a message to the console. Call this helper inside your Convert function.
  • In your main.go (root directory), import the converter package and use it to convert 100 USD to EUR (using a rate of 0.92).
  • Verify that you cannot call logTransaction from main.go.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.