These five concepts become much easier once you see how they fit together:
flowchart TD
M["Module<br/>Whole Go project"]
P1["Package main"]
P2["Package fmt"]
F["Function<br/>add()"]
T["Type<br/>Person"]
ME["Method<br/>person.Greet()"]
I["Interface<br/>Speaker"]
M --> P1
P1 --> F
P1 --> T
T --> ME
I -. "method satisfies" .-> ME
P1 -->|"imports"| P2
The simplest mental model is:
Module = Project
Package = Folder / code group
Function = Standalone action
Method = Action belonging to a type
Interface = Required behavior
1. Module
What is a Module?
A module is your Go project.
It is normally a directory containing a file called:
go.mod
Example:
myapp/
├── go.mod
└── main.go
Think:
Module = entire project
Why do we need a Module?
Go uses the module to know:
- the name of your project
- which external dependencies your project uses
- which versions of dependencies should be downloaded
When do we use it?
Normally when starting a new Go project:
mkdir myapp
cd myapp
go mod init myapp
Go creates:
go.mod
Complete Example
Run:
mkdir module-demo
cd module-demo
go mod init module-demo
You’ll see:
go: creating new go.mod: module module-demo
Now create:
main.go
package main
import "fmt"
func main() {
// This is our program.
fmt.Println("Hello from my Go module!")
}
Run:
go run .
Output:
Hello from my Go module!
Your directory now looks like:
module-demo/
├── go.mod
└── main.go
And go.mod will look approximately like:
module module-demo
go 1.26
What does this mean?
module module-demo
means:
The name/path of this module is
module-demo.
And:
go 1.26
tells Go which Go language/module version this project targets.
Where does Module sit?
flowchart TD
A["module-demo<br/>MODULE"]
B["go.mod"]
C["main.go"]
D["package main"]
A --> B
A --> C
C --> D
Remember
One project usually has one
go.mod.
2. Package
What is a Package?
A package is a group of related Go code.
Every .go file must declare which package it belongs to.
For example:
package main
Why do we need Packages?
Packages help organize code.
Imagine a large application:
shopping-app/
├── main.go
├── users/
├── payments/
├── orders/
└── products/
You could have packages such as:
main
users
payments
orders
products
Instead of putting everything into one huge file.
When do we use Packages?
Always.
Every Go file belongs to a package.
Even the smallest Go program has:
package main
Complete Example
Create main.go:
package main
// ↑ This file belongs to the "main" package.
import "fmt"
// ↑ We are using another package called "fmt".
// fmt is part of Go's standard library.
func main() {
// Println is a function inside the fmt package.
fmt.Println("Hello Go!")
}
Run:
go run main.go
Output:
Hello Go!
Look carefully at this
fmt.Println("Hello Go!")
Here:
fmt
is the package.
And:
Println
is a function inside the package.
So:
fmt.Println()
│ │
│ └── Function
│
└────── Package
What is special about package main?
This is important.
package main
means:
This package is intended to build an executable program.
For an executable Go program, you normally need:
package main
func main() {
}
So:
package main
+
func main()
=
executable Go program
Package relationship
flowchart LR
A["package main"] -->|"uses"| B["package fmt"]
B --> C["Println()"]
Remember
Module contains packages.
3. Function
What is a Function?
A function is a named block of code that performs a task.
Example:
func add(a int, b int) int {
return a + b
}
Think:
Function = reusable action
Examples:
add()
login()
sendEmail()
calculateSalary()
printReport()
Why use Functions?
Without functions, you would repeat the same code again and again.
Instead of:
result := 10 + 20
everywhere, you can create:
add(10, 20)
Complete Example
package main
import "fmt"
// add is a FUNCTION.
//
// a int -> first input
// b int -> second input
// int -> function returns an integer
func add(a int, b int) int {
result := a + b
return result
}
func main() {
// Calling the function
answer := add(10, 20)
fmt.Println("Answer:", answer)
}
Run:
go run main.go
Output:
Answer: 30
Understand the function
func add(a int, b int) int {
return a + b
}
Break it down:
func add(a int, b int) int
│ │ │ │
│ │ │ └── return type
│ │ │
│ │ └──────────────── parameters
│ │
│ └──────────────────── function name
│
└───────────────────────── function keyword
How do we call it?
answer := add(10, 20)
Flow:
flowchart LR
A["main()"] --> B["add(10,20)"]
B --> C["10 + 20"]
C --> D["return 30"]
D --> A
Where can a function exist?
A normal function belongs to a package.
For example:
package main
func add() {
}
add() belongs to package main.
Remember
Function = standalone behavior.
4. Method
This is where many Go learners get confused.
A method is almost the same as a function.
The difference is:
A method belongs to a type.
Function vs Method
Function:
func greet() {
}
Method:
func (p Person) greet() {
}
Notice this:
(p Person)
That is called the receiver.
It connects the function to Person.
Why use Methods?
Suppose we have:
type Person struct {
Name string
}
A person may perform actions:
Person
├── Greet()
├── Walk()
├── Sleep()
└── Work()
These actions naturally belong to Person.
So methods make sense.
Complete Example
package main
import "fmt"
// Person is a custom type.
type Person struct {
Name string
}
// Greet is a METHOD belonging to Person.
//
// (p Person) is called the RECEIVER.
//
// It means:
// "This method belongs to Person."
func (p Person) Greet() {
fmt.Println("Hello, my name is", p.Name)
}
func main() {
// Create a Person value
person := Person{
Name: "Rajesh",
}
// Call the method using the Person value
person.Greet()
}
Run:
go run main.go
Output:
Hello, my name is Rajesh
Understand this line
func (p Person) Greet()
Break it down:
func (p Person) Greet()
│ │ │
│ │ └── method name
│ │
│ └────────── receiver
│
└──────────────── keyword
The receiver:
(p Person)
means:
Greet()belongs toPerson.
Therefore we can write
person.Greet()
Think:
person.Greet()
│ │
│ └── Method
│
└───────── Person object/value
Function vs Method
Normal function:
Greet(person)
Method:
person.Greet()
Conceptually:
flowchart LR
A["Person"] --> B["Greet()"]
A --> C["Walk()"]
A --> D["Work()"]
Remember
Function = standalone action
Method = action attached to a type
5. Interface
This is usually the most confusing one.
But there is a very simple way to think about it.
Interface = a list of behaviors/methods that something must have.
Suppose we create:
type Speaker interface {
Speak()
}
This means:
Anything that has a
Speak()method can be considered aSpeaker.
That’s the core idea.
Why use an Interface?
Imagine:
Dog can Speak()
Person can Speak()
Robot can Speak()
All three are completely different types.
But they have one thing in common:
Speak()
So we could create:
type Speaker interface {
Speak()
}
Now functions can work with anything that knows how to Speak.
Complete Interface Example
package main
import "fmt"
// Speaker is an INTERFACE.
//
// Anything that has:
//
// Speak()
//
// automatically satisfies this interface.
type Speaker interface {
Speak()
}
// Person is a custom type.
type Person struct {
Name string
}
// Person has a Speak method.
//
// Therefore Person automatically satisfies
// the Speaker interface.
func (p Person) Speak() {
fmt.Println(p.Name, "says hello!")
}
// This function accepts ANYTHING
// that satisfies the Speaker interface.
func makeItSpeak(s Speaker) {
s.Speak()
}
func main() {
person := Person{
Name: "Rajesh",
}
// Person has Speak()
// therefore Person can be passed as Speaker.
makeItSpeak(person)
}
Run:
go run main.go
Output:
Rajesh says hello!
The important part
We created:
type Speaker interface {
Speak()
}
And Person has:
func (p Person) Speak() {
}
Therefore:
Speaker requires Speak()
↑
│
Person has Speak()
│
↓
Person satisfies Speaker
You do NOT write something like:
Person implements Speaker
Go figures it out automatically.
This is called implicit interface implementation.
Visualize it
flowchart TD
I["Speaker Interface<br/>requires Speak()"]
P["Person"]
D["Dog"]
R["Robot"]
PM["Speak()"]
DM["Speak()"]
RM["Speak()"]
P --> PM
D --> DM
R --> RM
PM --> I
DM --> I
RM --> I
If all three types have:
Speak()
then all three satisfy:
Speaker
The Complete Mental Model
Now connect everything together.
Imagine this project:
shop/
├── go.mod
└── main.go
Module
shop
The entire project.
Package
Inside main.go:
package main
Code organization.
Function
func calculatePrice() {
}
Standalone behavior.
Type
type Customer struct {
Name string
}
Represents something.
Method
func (c Customer) Buy() {
}
Behavior attached to Customer.
Interface
type Buyer interface {
Buy()
}
Defines the behavior something must have.
How Everything Fits Together
flowchart TD
M["MODULE<br/>shopping-app"]
P["PACKAGE<br/>main"]
F["FUNCTION<br/>calculatePrice()"]
T["TYPE<br/>Customer"]
ME["METHOD<br/>customer.Buy()"]
I["INTERFACE<br/>Buyer<br/>requires Buy()"]
M --> P
P --> F
P --> T
P --> I
T --> ME
ME -. "satisfies" .-> I
That one diagram is worth remembering.
Master Comparison
| Concept | Simple Meaning | Example | Belongs To / Contains | Main Purpose |
|---|---|---|---|---|
| Module | Entire Go project | module shopping | Contains packages | Project/dependency management |
| Package | Group of Go code | package main | Belongs to module | Organize code |
| Function | Standalone action | add() | Belongs to package | Perform reusable work |
| Method | Function attached to a type | person.Greet() | Belongs to a type | Give behavior to types |
| Interface | Required methods/behavior | Speaker | Defined in a package | Allow different types to share behavior |
Module vs Package
| Module | Package |
|---|---|
| Entire project | Part of project |
Defined by go.mod | Defined by package xxx |
| Can contain many packages | Contains Go files/types/functions |
| Handles dependencies | Organizes code |
Example shopping-app | Example payment |
Think:
Company
↓
Departments
similar to:
Module
↓
Packages
Package vs Function
| Package | Function |
|---|---|
| Groups code | Performs an action |
| Contains functions | Lives inside package |
fmt | Println() |
math | Sqrt() |
Example:
fmt.Println()
fmt = package
Println = function
Function vs Method
This distinction is extremely important.
| Function | Method |
|---|---|
| Standalone | Attached to a type |
| No receiver | Has receiver |
add(10,20) | person.Greet() |
func add() | func (p Person) Greet() |
Function:
func greet() {
}
Method:
func (p Person) greet() {
}
The magic difference is:
(p Person)
Method vs Interface
| Method | Interface |
|---|---|
| Actual behavior/code | Required behavior |
| Contains implementation | Usually only method signatures |
Speak() prints something | Says “Speak() must exist” |
| Attached to a type | Can be satisfied by many types |
Example:
Interface says:
type Speaker interface {
Speak()
}
Person provides:
func (p Person) Speak() {
fmt.Println("Hello")
}
Therefore:
Person → satisfies → Speaker
Function vs Interface
| Function | Interface |
|---|---|
| Performs actual work | Describes required behavior |
| Contains code | Contains method signatures |
add() | Speaker |
| Called directly | Used as a type/contract |
For example:
func makeItSpeak(s Speaker) {
s.Speak()
}
Here:
makeItSpeak = function
Speaker = interface
Speak = required method
Module vs Everything Else
This hierarchy makes it easier:
MODULE
│
├── PACKAGE
│ │
│ ├── Function
│ │
│ ├── Type
│ │ │
│ │ └── Method
│ │
│ └── Interface
│
└── PACKAGE
│
├── Function
├── Type
└── Interface
Or visually:
flowchart TD
M["MODULE"]
P1["PACKAGE"]
P2["PACKAGE"]
F["FUNCTION"]
T["TYPE"]
ME["METHOD"]
I["INTERFACE"]
M --> P1
M --> P2
P1 --> F
P1 --> T
P1 --> I
T --> ME
One-Line Definitions You Should Memorize
| Concept | Memorize This |
|---|---|
| Module | A Go project containing one or more packages |
| Package | A group of related Go files/code |
| Function | A reusable standalone block of code |
| Method | A function attached to a type |
| Interface | A set of methods describing behavior |
The 5 Questions to Ask Yourself
Whenever you see Go code, identify these things.
1. What is the module?
Look at:
go.mod
2. What package am I in?
Look at the first line:
package main
3. Is this a function?
Look for:
func add() {
}
No receiver → function.
4. Is this a method?
Look for:
func (p Person) Greet() {
}
Receiver exists:
(p Person)
→ method
5. Is this an interface?
Look for:
type Speaker interface {
Speak()
}
→ interface
Final Example to Test Your Understanding
Don’t run this yet. Just identify each part:
package main
import "fmt"
type Person struct {
Name string
}
type Speaker interface {
Speak()
}
func add(a int, b int) int {
return a + b
}
func (p Person) Speak() {
fmt.Println(p.Name, "is speaking")
}
func main() {
p := Person{Name: "Rajesh"}
p.Speak()
fmt.Println(add(10, 20))
}
The answer is:
package main
↓
PACKAGE
type Person struct
↓
TYPE
type Speaker interface
↓
INTERFACE
func add(...)
↓
FUNCTION
func (p Person) Speak()
↓
METHOD
func main()
↓
FUNCTION
And if the directory has:
go.mod
then the entire directory/project is the:
MODULE
The Most Important Picture
Keep this mental picture:
flowchart LR
M["Module<br/>PROJECT"] --> P["Package<br/>CODE GROUP"]
P --> F["Function<br/>DO SOMETHING"]
P --> T["Type<br/>REPRESENT SOMETHING"]
T --> ME["Method<br/>TYPE CAN DO SOMETHING"]
P --> I["Interface<br/>MUST BE ABLE TO DO SOMETHING"]
ME -. "can satisfy" .-> I
In plain English
Module: This is my project.
Package: This is how I organize my project’s code.
Function: Do this work.
Method: This particular type can do this work.
Interface: I don’t care what the type is, as long as it can do this work.
If you get these five sentences clear, Go functions, methods, and interfaces become much easier to understand.