Skip to content

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 name

Package 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
}
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"
)
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 executed

init 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 main

Documentation 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.go

Medium 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 files

Large 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 hyphen

Package 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 function

Detailed 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-app

Project 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

Content is for learning and research only.