Go Program Structure
Go programs have a clear organizational structure. Understanding program structure is the foundation of learning Go. This chapter will detail the various components of Go programs.
🏗️ Basic Structure of Go Programs
Simplest Go Program
go
// hello.go
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}Program Structure Analysis
go
package main // 1. Package declaration
import "fmt" // 2. Import packages
func main() { // 3. Function definition
// 4. Function body
fmt.Println("Hello, World!")
}📦 Package (Package)
Package Concept
Packages are the basic unit of code organization in Go. Every Go file must belong to a package.
Package Declaration Rules
go
// Package declaration must be the first line of the file (except comments)
package main // Package name for executable programs
package utils // Package name for library packages
package calculator // Custom package namePackage Naming Conventions
- Package names should be short and clear
- Use lowercase letters
- Avoid underscores and mixed case
- Package names usually match directory names
main Package
go
// main package is the entry package for executable programs
package main
import "fmt"
// main function is the entry point of program execution
func main() {
fmt.Println("This is an executable program")
}Library Package Example
go
// math/calculator.go
package calculator
// Add calculates the sum of two numbers
func Add(a, b int) int {
return a + b
}
// Subtract calculates the difference of two numbers
func Subtract(a, b int) int {
return a - b
}📥 Import (Import)
Basic Import Syntax
go
// Single import
import "fmt"
import "math"
// Multiple imports (recommended)
import (
"fmt"
"math"
"strings"
)Import Methods Detailed
1. Standard Import
go
import "fmt"
import "net/http"
func main() {
fmt.Println("Hello")
http.ListenAndServe(":8080", nil)
}2. Alias Import
go
import (
f "fmt" // Give fmt package alias f
"net/http"
)
func main() {
f.Println("Using alias") // Use alias to call
}3. Dot Import (Not Recommended)
go
import . "fmt"
func main() {
Println("Call function directly") // No package prefix needed
}4. Anonymous Import
go
import _ "net/http/pprof" // Only execute package's init function
func main() {
// pprof package is imported but not directly used
}Import Paths
Standard Library Import
go
import (
"fmt" // Formatted I/O
"os" // Operating system interface
"net/http" // HTTP client and server
"encoding/json" // JSON encoding/decoding
)Third-Party Package Import
go
import (
"github.com/gin-gonic/gin"
"github.com/gorilla/mux"
"golang.org/x/crypto/bcrypt"
)Relative Path Import (Not Recommended)
go
import (
"./utils" // utils package in current directory
"../config" // config package in parent directory
)🔧 Function (Function)
main Function
go
package main
// main function is the entry point of the program
// 1. Must be in main package
// 2. Cannot have parameters
// 3. Cannot have return values
func main() {
// Program logic
}init Function
go
package main
import "fmt"
// init function executes automatically before main function
func init() {
fmt.Println("Init function executed")
}
func main() {
fmt.Println("Main function executed")
}
// Output:
// Init function executed
// Main function executedinit Function Characteristics
- Executes automatically without calling
- Each package can have multiple init functions
- Executes in code order
- Executes before main function
Function Definition Syntax
go
// Basic function syntax
func functionName(parameters) returnType {
// Function body
return value
}
// Example
func greet(name string) string {
return "Hello, " + name
}📝 Comments (Comments)
Single-line Comments
go
package main
import "fmt"
func main() {
// This is a single-line comment
fmt.Println("Hello") // End-of-line comment
}Multi-line Comments
go
/*
This is a multi-line comment
Can span multiple lines
Usually used for documentation
*/
package mainDocumentation Comments
go
// Package calculator provides basic mathematical operations
package calculator
// Add calculates the sum of two integers
// Parameters a and b are the numbers to add
// Returns the result of a + b
func Add(a, b int) int {
return a + b
}
/*
Divide calculates division operation
Supports floating-point division, returns error when divisor is 0
Parameters:
- dividend: Dividend
- divisor: Divisor
Return values:
- result: Division result
- error: Error message, not nil when divisor is 0
*/
func Divide(dividend, divisor float64) (float64, error) {
if divisor == 0 {
return 0, fmt.Errorf("divisor cannot be zero")
}
return dividend / divisor, nil
}🏢 Project Structure Example
Small Project Structure
myapp/
├── go.mod
├── go.sum
├── main.go
├── README.md
└── utils/
└── helper.goMedium Project Structure
myproject/
├── go.mod
├── go.sum
├── main.go
├── README.md
├── cmd/ # Command-line programs
│ ├── server/
│ │ └── main.go
│ └── client/
│ └── main.go
├── pkg/ # Library code that can be used externally
│ ├── auth/
│ │ ├── auth.go
│ │ └── auth_test.go
│ └── database/
│ ├── db.go
│ └── db_test.go
├── internal/ # Internal packages, cannot be imported externally
│ ├── config/
│ │ └── config.go
│ └── handlers/
│ └── handler.go
├── web/ # Web related files
│ ├── templates/
│ └── static/
├── docs/ # Documentation
└── scripts/ # Script filesLarge Project Structure
enterprise-app/
├── go.mod
├── go.sum
├── README.md
├── Makefile
├── Dockerfile
├── cmd/ # Application entry points
│ ├── api/
│ │ └── main.go
│ ├── worker/
│ │ └── main.go
│ └── cli/
│ └── main.go
├── internal/ # Private application code
│ ├── app/
│ │ ├── api/
│ │ ├── worker/
│ │ └── cli/
│ ├── pkg/
│ │ ├── config/
│ │ ├── database/
│ │ ├── logger/
│ │ └── middleware/
│ └── domain/
│ ├── user/
│ ├── order/
│ └── product/
├── pkg/ # Library code that external applications can use
│ ├── client/
│ └── types/
├── api/ # API definition files
│ ├── openapi/
│ └── proto/
├── web/ # Web application related
│ ├── static/
│ └── template/
├── configs/ # Configuration files
├── deployments/ # Deployment configuration
├── docs/ # Design and user documentation
├── examples/ # Application examples
├── scripts/ # Build, install, analysis scripts
├── test/ # Additional external test applications and test data
└── vendor/ # Application dependencies (manually or tool-managed)📋 File Organization Standards
File Naming Conventions
go
// Good file naming
user.go // Singular form
user_test.go // Test file
user_model.go // Specific functionality
database.go // Function description
// Avoid
users.go // Plural form
UserModel.go // Capitalized beginning
user-model.go // Using hyphenPackage File Organization
go
// user/user.go - Main type definitions
package user
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
// user/service.go - Business logic
package user
func (u *User) Save() error {
// User save logic
return nil
}
// user/repository.go - Data access
package user
type Repository interface {
Create(user *User) error
FindByID(id int) (*User, error)
}
// user/user_test.go - Test file
package user
import "testing"
func TestUser_Save(t *testing.T) {
// Test code
}🔄 Program Execution Order
Execution Flow Diagram
1. Initialize imported packages
├── Execute package-level variable initialization
├── Execute init functions (in import order)
└── Recursively process all dependent packages
2. Initialize main package
├── Execute package-level variable initialization
└── Execute main package's init function
3. Execute main functionDetailed Example
go
// package a
package a
import "fmt"
var A = func() int {
fmt.Println("Variable A initialized")
return 1
}()
func init() {
fmt.Println("Package a's init function")
}
// package b
package b
import (
"fmt"
_ "path/to/a" // Import package a
)
var B = func() int {
fmt.Println("Variable B initialized")
return 2
}()
func init() {
fmt.Println("Package b's init function")
}
// main.go
package main
import (
"fmt"
_ "path/to/b" // Import package b
)
var MainVar = func() int {
fmt.Println("main package variable initialized")
return 3
}()
func init() {
fmt.Println("main package's init function")
}
func main() {
fmt.Println("main function executed")
}
// Output order:
// Variable A initialized
// Package a's init function
// Variable B initialized
// Package b's init function
// main package variable initialized
// main package's init function
// main function executed🎯 Practical Example
Create a Complete Project
bash
# 1. Create project directory
mkdir calculator-app
cd calculator-app
# 2. Initialize module
go mod init github.com/username/calculator-appProject File Structure
go
// main.go
package main
import (
"fmt"
"github.com/username/calculator-app/pkg/calculator"
)
func main() {
fmt.Println("Calculator Application")
result := calculator.Add(10, 5)
fmt.Printf("10 + 5 = %d\n", result)
result = calculator.Multiply(3, 4)
fmt.Printf("3 * 4 = %d\n", result)
}
// pkg/calculator/calculator.go
package calculator
// Add calculates the sum of two numbers
func Add(a, b int) int {
return a + b
}
// Subtract calculates the difference of two numbers
func Subtract(a, b int) int {
return a - b
}
// Multiply calculates the product of two numbers
func Multiply(a, b int) int {
return a * b
}
// Divide calculates the quotient of two numbers
func Divide(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("divisor cannot be zero")
}
return a / b, nil
}
// pkg/calculator/calculator_test.go
package calculator
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("Add(2, 3) = %d; want %d", result, expected)
}
}
func TestDivide(t *testing.T) {
// Normal case
result, err := Divide(10, 2)
if err != nil {
t.Errorf("Divide(10, 2) returned error: %v", err)
}
expected := 5
if result != expected {
t.Errorf("Divide(10, 2) = %d; want %d", result, expected)
}
// Zero divisor case
_, err = Divide(10, 0)
if err == nil {
t.Error("Divide(10, 0) should return error")
}
}Run Project
bash
# Run main program
go run main.go
# Run tests
go test ./...
# Build program
go build -o calculator📚 Standard Library Import Example
Common Standard Library Packages
go
package main
import (
"fmt" // Formatted I/O
"os" // Operating system interface
"time" // Time handling
"strings" // String operations
"strconv" // String conversion
"math" // Mathematical functions
"net/http" // HTTP client and server
"encoding/json" // JSON handling
"io/ioutil" // I/O utilities
"log" // Logging
)
func main() {
// Use various standard libraries
fmt.Println("Hello, World!")
now := time.Now()
fmt.Println("Current time:", now.Format("2006-01-02 15:04:05"))
str := strings.ToUpper("hello")
fmt.Println("Converted to uppercase:", str)
num, _ := strconv.Atoi("123")
fmt.Println("String to integer:", num)
}🎓 Summary
In this chapter, we learned the basic structure of Go programs:
- ✅ Package Declaration: Every Go file must declare a package name
- ✅ Import Statements: Import packages that need to be used
- ✅ Function Definition: main function is the program entry point
- ✅ Comment Standards: Single-line, multi-line, and documentation comments
- ✅ Project Organization: Reasonable directory structure and file naming
- ✅ Execution Order: Understanding program initialization and execution flow
Understanding program structure is the foundation of writing Go programs. Next, we will learn the basic syntax of Go language.
Next chapter, we will learn Go Basic Syntax to master the syntax foundation of Go language.
Best Practices
- Keep package names short and descriptive
- Use consistent project structure
- Write documentation comments for exported functions and types
- Organize files reasonably, avoid individual files being too large