惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Security @ Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
AWS News Blog
AWS News Blog
Spread Privacy
Spread Privacy
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Security Latest
Security Latest
Simon Willison's Weblog
Simon Willison's Weblog
C
Cybersecurity and Infrastructure Security Agency CISA
G
GRAHAM CLULEY
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
I
Intezer
S
Securelist
Google DeepMind News
Google DeepMind News
S
Schneier on Security
T
Troy Hunt's Blog
Help Net Security
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
Security Archives - TechRepublic
Security Archives - TechRepublic
O
OpenAI News
博客园 - Franky
G
Google Developers Blog
Stack Overflow Blog
Stack Overflow Blog
TaoSecurity Blog
TaoSecurity Blog
MyScale Blog
MyScale Blog
P
Privacy International News Feed
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Google Online Security Blog
Google Online Security Blog
Latest news
Latest news
Vercel News
Vercel News
T
The Blog of Author Tim Ferriss
博客园_首页
S
Security Affairs
PCI Perspectives
PCI Perspectives
WordPress大学
WordPress大学
C
Cisco Blogs
Recent Announcements
Recent Announcements
L
LangChain Blog
GbyAI
GbyAI
F
Fortinet All Blogs
N
News and Events Feed by Topic
T
Tor Project blog
IT之家
IT之家
P
Palo Alto Networks Blog
D
DataBreaches.Net
小众软件
小众软件
宝玉的分享
宝玉的分享
F
Full Disclosure

DigitalOcean Community Tutorials

Mastering grep with Regular Expressions for Efficient Text Search It's Time to Break Up with Your Cloud: Why AI Teams are Switching We Built a Private-Document AI App to Test Platform Security. Here Is What We Could Actually Verify. PostgreSQL Explained: A Complete Beginner-to-Advanced Guide How To Install and Configure Postfix on Ubuntu How To Build a Web Application Using Flask in Python 3 Build AI Reading List with DigitalOcean Functions and Mistral How To Concatenate Strings in Python How to Allow MySQL Remote Access Securely How To Install and Use Docker on Rocky Linux How To Build a Multi-Agent AI System with Docker Agent DSPy Use Cases: Build Optimized LLM Pipelines How To Submit AJAX Forms with jQuery Build an AI-Powered GPU Fleet Optimizer with the DigitalOcean AI Platform ADK Monitor GPU Utilization in Real Time: A Complete Guide Reduce File Size of Images in Linux - CLI and GUI methods Reduce PDF File Size in Linux: Tools and Methods How To Set Up a Private Docker Registry on Ubuntu How To Troubleshoot Terraform: Errors and Fixes How to Use Go Modules Python Multiprocessing Example: Process, Pool & Queue Convert Class Components to Functional Components with React Hooks How To Install and Configure Ansible on Ubuntu LLM Tokenizers Simplified: BPE, SentencePiece, and More How To Monitor System Authentication Logs on Ubuntu How to Use Traceroute and MTR to Diagnose Network Issues How to Deploy Postgres to Kubernetes Cluster Create RAID Arrays with mdadm on Ubuntu How To Make an HTTP Server in Go How To Set Up Time Synchronization on Ubuntu How To Use Struct Tags in Go apt-key Deprecation: Add Repositories with GPG on Ubuntu Linux ps Command: 20 Real-World Examples Python struct.pack and struct.unpack for Binary Data Deadlock in Java: Examples, Detection, and Prevention How To Use Find and Locate to Search for Files on Linux Structured Resume Skill Extraction Using Mistral-7B Inference How to Use the Python Main Function How to Set Up NemoClaw on a DigitalOcean Droplet with 1-Click Build an End-to-End RAG Pipeline for LLM Applications From Single to Multi-Agent Systems: Key Infrastructure Needs Back Up Data to Object Storage Using Restic How to Generate Videos with LTX-2.3 on DigitalOcean GPU Droplets How To Install LAMP Stack (Apache, MySQL, PHP) on Ubuntu How to Download Files with cURL How To Use Variadic Functions in Go Generate UUIDs with uuidgen on Linux How To Use EJS to Template Your Node Application How to Install Node.js on Ubuntu (Step-by-Step Guide) MongoDB Indexes: Improve Query Performance with Node.js LLM Tool Calling with DigitalOcean AI Platform and Databases What are Text Diffusion Models? - An Overview Crafting a Game from Scratch with GPT-5.4 Building Long-Term Memory in AI Agents with LangGraph and Mem0 How To Install PHP 7.4 and Set Up a Local Development Environment on Ubuntu 20.04 Build a GraphQL API in Go to Upload Files to Spaces How To Lint and Format Code with ESLint in Visual Studio Code Train YOLO26 for Retail Object Detection on DigitalOcean GPUs How To Work with JSON in MySQL How to Use the JavaScript .map() Method Building a Scalable App with MongoDB Using DigitalOcean's MCP Server How to Create an SSH Key in Linux: Easy Step-by-Step Guide Measure MySQL Query Performance with mysqlslap How To Use *args and **kwargs in Python 3 Nemotron 3 helped me find the perfect dish rack? A2A vs MCP - How These AI Agent Protocols Actually Differ How To Install and Manage Supervisor Docker Container Images with Watchtower on Ubuntu Getting Started with Qwen3.5 Vision-Language Models How To Create a New Sudo-Enabled User on Ubuntu How to Use Ansible to Install and Set Up Docker on Ubuntu How To Enable Remote Desktop Protocol Using xrdp on Ubuntu 22.04 How To Convert a String to a List in Python How To Check If a String Contains Another String in Python How to Read a Properties File in Python Python Command Line Arguments: sys.argv, argparse, getopt Mastering Grep command in Linux/Unix: A Beginner's Tutorial Understanding Python Data Types How to Implement a Stack in C With Code Examples Python os.system() vs subprocess: Run System Commands How To Install and Use Docker Compose on Ubuntu How to Add and Delete Users on Ubuntu How To Order Query Results in Laravel Eloquent How To Define and Use Handlers in Ansible Playbooks How To Install and Use SQLite on Ubuntu How To Install and Use Homebrew on macOS How To Manage DateTime with Carbon in Laravel and PHP How To Install Git on Ubuntu How To Install and Secure Redis on Ubuntu How To Build and Install Go Programs on Linux Using ldflags to Set Version Information for Go Applications How To Build a Node.js Application with Docker How To Add JavaScript to HTML How To Reset Your MySQL or MariaDB Root Password How To Add Images in Markdown How To Set Up a Production Elasticsearch Cluster with Ansible How To Set Up a Firewall Using firewalld on CentOS Understanding Systemd Units and Unit Files How To Set Up Replication in MySQL How To Use the .htaccess File
Importing Packages in Go: A Complete Guide
2026-03-25 · via DigitalOcean Community Tutorials

Introduction

Importing packages in Go is how you reuse code from the standard library, your own module, and third-party modules. This tutorial walks through the import keyword, module-aware imports, package aliases, blank imports, dot imports, dependency management with go.mod and go.sum, and workspace mode with go.work.

You build small runnable examples in each step: generating random numbers, importing a third-party UUID package, importing a local package inside the same module, resolving package name collisions, and automating import formatting with goimports. By the end, you have a practical model for how package paths, module paths, and import syntax fit together in real Go projects.

Modules are versioned collections of packages. If you need a deeper module primer, read How To Use Go Modules.

Prerequisites

Install Go for your operating system:

How Packages Work in Go

A package in Go is a directory of .go files that share the same package declaration. You import packages by import path, then reference exported identifiers from the imported package name.

The package name and import path are related, but they are not the same thing:

  • Package name is the identifier in source files, such as package mathutil.
  • Import path is how the compiler locates code, such as github.com/sammy/random/mathutil.

When you write import "net/http", the compiler looks inside $GOROOT/src, where the Go standard library lives. When you write import "github.com/google/uuid", it looks in the module cache at $GOMODCACHE. You never manage these paths manually. Understanding the lookup order explains two common situations: why your IDE resolves standard library packages instantly without any setup, and why a third-party package causes a cannot find module providing package error until you run go get.

If a replace directive is present in go.mod, or if a go.work file is active, those paths take precedence over the module cache. This is how workspace mode lets you develop a local version of a dependency without publishing it first.

Packages live inside modules. A single module often contains many packages, including package main entrypoints and reusable library packages.

myapp/
├── go.mod
├── main.go          # package main
└── mathutil/
    └── mathutil.go  # package mathutil

In this layout, main.go imports myapp/mathutil if module myapp appears in go.mod, or github.com/you/myapp/mathutil if the module path is fully qualified.

Understanding GOPATH, GOROOT, and Go Modules

GOROOT points to the Go toolchain installation, GOPATH is the default workspace area for binaries and module cache, and go.mod defines module-based dependency management for your project.

  • GOROOT: location of the Go SDK, managed by installer or package manager.
  • GOPATH: defaults to ~/go, used for bin/ and module cache.
  • go.mod: per-module dependency manifest, used by modern Go development.

Check each value in your environment:

  1. go env GOROOT
/usr/local/go
  1. go env GOPATH
/Users/sammy/go
  1. go env GOMODCACHE
/Users/sammy/go/pkg/mod

GOPATH still matters for go install destinations and module cache location, but your project does not need to live under $GOPATH/src.

Using the import Keyword

Go uses the import keyword to bring package identifiers into the current file. You can import one package per line or use a grouped import block.

Single import:

import "fmt"

Grouped imports:

import (
    "fmt"
    "os"
)

The compiler rejects unused imports, which keeps import blocks accurate and easy to scan.

In practice, you should always use the grouped block form even when importing a single package. The goimports tool enforces this automatically, and the Go style guide discourages chaining multiple single-line import statements. Using blocks from the start also makes it easier to add packages later without restructuring your import declaration.

Step 1 – Importing Standard Library Packages

Use standard library imports for common functionality such as output, random numbers, filesystem access, and HTTP clients. This first example uses math/rand.

Create random.go:

  1. nano random.go

Add this code:

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    for i := 0; i < 5; i++ {
        fmt.Println(rand.Intn(10))
    }
}

Run it:

  1. go run random.go
1
7
7
9
1

In older Go versions, many examples call rand.Seed(time.Now().UnixNano()). Go 1.20 changes this behavior.

In Go 1.20 and later, the global random source is automatically seeded with a random value. Calling rand.Seed() is no longer necessary and the function is deprecated. If you are on Go 1.20+, remove explicit seeding code.

If you want explicit, local random sources, use rand.New:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    r := rand.New(rand.NewSource(time.Now().UnixNano()))
    for i := 0; i < 5; i++ {
        fmt.Println(r.Intn(10))
    }
}

This pattern keeps randomness scoped to one *rand.Rand instance and avoids package-global state.

Step 2 – Using Third-Party Packages with Go Modules

Third-party imports use fully qualified module paths, and go.mod plus go.sum track versions and checksums.

Initialize a module:

  1. go mod init github.com/sammy/random
go: creating new go.mod: module github.com/sammy/random

Inspect go.mod:

  1. cat go.mod
module github.com/sammy/random

go 1.22.0

Add a dependency:

  1. go get github.com/google/uuid@latest
go: downloading github.com/google/uuid v1.6.0
go: added github.com/google/uuid v1.6.0

Inspect go.mod again:

  1. cat go.mod
module github.com/sammy/random

go 1.22.0

require github.com/google/uuid v1.6.0 // indirect

require directives pin module versions. The // indirect suffix means the module is not imported directly by source code in the current module at that moment, but it is still required in the build graph.

Inspect go.sum:

  1. cat go.sum
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

go.sum stores cryptographic hashes for downloaded modules and their go.mod files.

Commit both go.mod and go.sum to version control. The go.sum file records cryptographic hashes of each module version and its go.mod file, which lets Go verify future downloads.

Now create uuid.go:

package main

import (
    "fmt"
    "github.com/google/uuid"
)

func main() {
    for i := 0; i < 3; i++ {
        fmt.Println(uuid.New().String())
    }
}

Run it:

  1. go run uuid.go
243811a3-ddc6-4e26-9649-060622bba2b0
b8129aa1-3803-4dae-bd9f-6ba8817f44b2
3ae27c71-caa8-4eaa-b8e6-e629b7c1cb49

When dependencies drift, clean the module graph:

  1. go mod tidy
[no output on success]

Run go mod tidy after adding or removing imports, before committing, and in CI checks.

Step 3 – Importing Local Packages Within a Module

Local package imports inside a module use the module path prefix from go.mod, not relative paths like ./mathutil.

First, create the mathutil directory:

  1. mkdir mathutil

Then create mathutil/mathutil.go:

package mathutil

// Double returns n multiplied by 2.
func Double(n int) int {
    return n * 2
}

Update main.go:

package main

import (
    "fmt"
    "github.com/sammy/random/mathutil"
)

func main() {
    fmt.Println(mathutil.Double(4))
}

Run it:

  1. go run main.go
8

If you see cannot find module providing package github.com/sammy/random/mathutil, confirm two things: the mathutil/ directory exists at the root of your module, and the module path in go.mod matches the prefix used in your import statement exactly.

Step 4 – Importing Identically-Named Packages Using Aliases

Use aliases when two imports expose the same package name or when a long import path reduces readability.

When two packages share the same base name, assign an alias to one of them in the import block. The alias replaces the package name everywhere in that file:

package main

import (
    "fmt"
    "math/rand"
    crand "crypto/rand"
    "io"
)

func main() {
    // math/rand referenced as rand
    fmt.Println(rand.Intn(100))

    // crypto/rand referenced as crand
    b := make([]byte, 4)
    _, err := io.ReadFull(crand.Reader, b)
    if err != nil {
        panic(err)
    }
    fmt.Println(b)
}

You can also alias for readability when a package name is ambiguous in context:

package main

import (
    logging "log"
)

func main() {
    logging.Println("application started")
}

Comparing math/rand and crypto/rand (Optional)

This optional section keeps the larger side-by-side example and adds Go 1.20 guidance for crypto/rand.

Create compare.go:

package main

import (
    crand "crypto/rand"
    "fmt"
    "io"
    "math/rand"
    "os"
    "strconv"
    "time"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println("Usage:")
        fmt.Println("  go run compare.go <numberOfInts>")
        return
    }

    n, err := strconv.Atoi(os.Args[1])
    if err != nil {
        panic(err)
    }

    b1 := make([]byte, n)
    start := time.Now()
    r := rand.New(rand.NewSource(start.UnixNano()))
    for i := 0; i < n; i++ {
        b1[i] = byte(r.Intn(256))
    }
    elapsed := time.Since(start)
    for i := 0; i < 5 && i < len(b1); i++ {
        fmt.Println(b1[i])
    }
    fmt.Printf("Time to generate %v pseudo-random numbers with math/rand: %v\n", n, elapsed)

    b2 := make([]byte, n)
    start = time.Now()
    _, err = io.ReadFull(crand.Reader, b2)
    elapsed = time.Since(start)
    if err != nil {
        panic(err)
    }
    for i := 0; i < 5 && i < len(b2); i++ {
        fmt.Println(b2[i])
    }
    fmt.Printf("Time to generate %v pseudo-random numbers with crypto/rand: %v\n", n, elapsed)
}

As of Go 1.20, crand.Read() is deprecated. Use io.ReadFull(crand.Reader, b) as shown here.

Run it:

  1. go run compare.go 10
145
65
231
211
250
Time to generate 10 pseudo-random numbers with math/rand: 32.5µs
101
188
250
45
208
Time to generate 10 pseudo-random numbers with crypto/rand: 42.667µs

Step 5 – Using the Blank Identifier to Import for Side Effects

A blank import runs a package’s init() function without exposing its exported identifiers to your code.

Common use cases include SQL drivers, image decoders, and plugin registration packages.

package main

import (
    "database/sql"
    _ "github.com/lib/pq" // registers the PostgreSQL driver
)

func main() {
    db, err := sql.Open("postgres", "postgres://user:pass@localhost/db?sslmode=disable")
    if err != nil {
        panic(err)
    }
    _ = db.Close()
}

Without the blank import, the driver’s init() does not register "postgres" with database/sql, and sql.Open("postgres", ...) returns an unknown driver error.

Blank imports are intentional. If your linter reports an unused import, first confirm that the package registers behavior through init() before suppressing the warning.

Read more about initialization behavior in Understanding init in Go.

Step 6 – Using Dot Imports

Dot imports copy exported identifiers from another package into the current file namespace.

Syntax:

import . "fmt"

With dot import:

package main

import . "fmt"

func main() {
    Println("dot import")
}

Without dot import:

package main

import "fmt"

func main() {
    fmt.Println("qualified import")
}

Avoid dot imports in production code. They hide identifier origins and can create conflicts when different packages export the same name.

The one widely accepted use case is in test files, where dot-importing the package under test removes the need to qualify every identifier. For example:

package mathutil_test

import (
    . "github.com/sammy/random/mathutil"
    "testing"
)

func TestDouble(t *testing.T) {
    if Double(4) != 8 {
        t.Errorf("expected 8, got %d", Double(4))
    }
}

Without the dot import, every reference to Double would need to be written as mathutil.Double. In assertion-heavy test files, dot imports reduce that repetition. Outside of test files, the tradeoff does not hold: the readability cost of hidden identifier origins outweighs the saved keystrokes.

Managing Dependencies with go mod

The go mod commands manage the full lifecycle of your module’s dependencies: creating the module, adding and removing packages, and keeping go.mod and go.sum consistent with your source code.

Starting a module

Every project that uses external packages needs a go.mod file. Create one with:

  1. go mod init github.com/sammy/project
go: creating new go.mod: module github.com/sammy/project

Adding and upgrading dependencies

Use go get with a version suffix to add a new package or upgrade an existing one:

  1. go get github.com/google/uuid@v1.6.0
go: added github.com/google/uuid v1.6.0

To pin to the latest released version, use @latest instead of a specific version tag.

Removing a dependency

Pass @none as the version to remove a package from the module graph:

  1. go get github.com/google/uuid@none
go: removed github.com/google/uuid v1.6.0

Keeping go.mod and go.sum consistent

After adding, removing, or reorganizing imports in your source files, run:

  1. go mod tidy
[no output on success]

go mod tidy does two things: it adds any missing require entries for packages your code imports, and it removes require entries for packages your code no longer uses. If you remove an import from your source but forget to run go mod tidy, the stale entry stays in go.mod and bloats your dependency graph. Run it before every commit and in CI.

If go mod tidy removes a package you intended to keep, check whether that package is still imported anywhere in your source. If it is not, the removal is correct. If it is, verify that your import path matches the module path exactly, including capitalisation.

Preloading the module cache

To download all dependencies to your local cache without building:

  1. go mod download
[no output on success]

This is useful in CI pipelines where you want to separate the download step from the build step.

Verifying the cache

To confirm that your locally cached modules have not been modified since download:

  1. go mod verify
all modules verified

Listing the full dependency graph

  1. go list -m all
github.com/sammy/project
github.com/google/uuid v1.6.0
Command Purpose
go mod init <module-path> Create a new module and go.mod
go get <package>@<version> Add or upgrade a dependency
go get <package>@none Remove a dependency from the module graph
go mod tidy Add missing and remove unused module requirements
go mod download Download dependencies to local module cache
go mod verify Validate cached modules against go.sum
go list -m all Print the full module dependency graph

Go Workspace Mode for Multi-Module Development (Go 1.18+)

Workspace mode solves a specific problem: you are developing a library (mylib) and an application (myapp) that depends on it, and you want to test changes to mylib in myapp without publishing a new version of mylib first. Before workspace mode, the only way to do this was a replace directive in go.mod, which you had to remember to remove before committing. Workspace mode handles this with a separate go.work file that stays outside version control.

Set up a workspace with two modules:

  1. mkdir workspace && cd workspace
  1. mkdir myapp mylib
  1. cd myapp && go mod init github.com/sammy/myapp && cd ..
  1. cd mylib && go mod init github.com/sammy/mylib && cd ..
  1. go work init ./myapp ./mylib
[no output on success]

Verify the workspace file was created correctly:

  1. cat go.work
go 1.21

use (
    ./myapp
    ./mylib
)

To add a module to an existing workspace after initialization, run go work use ./module-path.

go.work files are typically local-development artifacts. Add go.work and go.work.sum to .gitignore unless your repository is intentionally organized as a shared multi-module workspace.

Step 7 – Using Goimports

goimports formats Go source files and fixes imports in one pass. It removes unused imports and adds missing imports when it can resolve package paths.

Install it:

  1. go install golang.org/x/tools/cmd/goimports@latest

Check installation:

  1. goimports --help
usage: goimports [flags] [path ...]

Run a diff-only rewrite:

  1. goimports -d random.go
diff -u random.go.orig random.go
--- random.go.orig 2024-01-15 10:22:04
+++ random.go 2024-01-15 10:22:04
@@ -1,5 +1,10 @@
 package main
 
+import (
+ "fmt"
+ "math/rand"
+)
+
 func main() {
  for i := 0; i < 5; i++ {
   fmt.Println(rand.Intn(10))
  }
 }

Write changes back to file:

  1. goimports -w random.go

For editor-driven import management, gopls provides integrated auto-import behavior in supported IDEs. For CI pipelines and pre-commit hooks, goimports remains a reliable command-line choice.

Common Import Errors

These are the errors Go developers encounter most often when working with imports, and what each one means.

imported and not used

Go will not compile a file that imports a package without using at least one of its exported identifiers. Remove the unused import, or replace it with a blank import (_) if you need it for side effects only.

cannot find module providing package

This error means the package path in your import statement does not match any module in your build graph. The most common causes are:

  • You forgot to run go get for a third-party package.
  • The import path has a typo or incorrect capitalisation.
  • You are outside the module root (no go.mod in the current directory or any parent).

Run go get <package-path> to add the missing module, then verify your import path matches pkg.go.dev exactly.

package X is not in GOROOT

This error appears when you use a bare package name that the compiler expects to find in the standard library but cannot. It usually means you typed a partial import path (for example, "rand" instead of "math/rand"). Check the full import path on Go Standard Library.

ambiguous import

This happens when two modules in your dependency graph provide the same package path. It is uncommon but occurs with forked or renamed modules. Use a replace directive in go.mod to pin the version you want, or alias one of the imports to disambiguate at the call site.

// indirect stays after adding an import

After you add an import to your source code, the // indirect comment on the corresponding require line in go.mod disappears only after you run go mod tidy. Until then, Go has not re-evaluated which packages are directly imported. Run go mod tidy to update the annotation.

Import Syntax Reference Table

Import Style Syntax Example Use Case
Standard import "fmt" Import a single package
Block import ( ... ) Group multiple packages in parentheses, one path per line
Alias import mrand "math/rand" Resolve name conflicts or shorten long paths
Dot import . "fmt" Promote identifiers into current namespace (test files only)
Blank import _ "github.com/lib/pq" Side-effect-only import (driver/codec registration)

Key Takeaways

  • A Go package is a directory of .go files with one shared package declaration.
  • Import paths identify package location, package names identify code references in source.
  • Modules (go.mod) define dependency versions, go.sum verifies integrity.
  • Local package imports use your module path prefix, not relative filesystem imports.
  • Aliases solve naming collisions and improve readability when needed.
  • Blank imports trigger side effects from init(), usually for registration patterns.
  • Dot imports reduce boilerplate but reduce clarity, keep them for narrow test scenarios.
  • Use goimports or gopls to keep imports correct and consistent.

FAQ

Q: How do you import a package in Go?
A: Use the import keyword and specify the package path as a string. For example, import "fmt" imports the fmt package. You then reference exported members with fmt.Println.

Q: Which keyword is used to import packages in Go?
A: Go uses the import keyword. It accepts single-line imports or grouped imports in parentheses. Unused imports trigger a compiler error.

Q: How do you import multiple packages in Go?
A: Use an import block with parentheses. List each path on its own line:

import (
    "fmt"
    "os"
)

Tools like goimports keep this block sorted and consistent.

Q: How do packages work in Go?
A: A package is a directory of source files sharing the same package clause. Other files import that package by import path, and only exported identifiers are accessible. Packages are versioned and distributed through modules.

Q: What is the difference between GOPATH and Go modules?
A: GOPATH is a workspace location that still hosts installed binaries and module cache. Go modules are the dependency system used by current Go development, based on go.mod and go.sum. Your project no longer depends on being inside GOPATH/src.

Q: What does a blank identifier import do in Go?
A: A blank import (_ "pkg/path") imports a package only for side effects. It runs init() and discards direct identifier access. This pattern is common with SQL drivers and codec registration packages.

Q: When should you use a package alias in Go?
A: Use aliases when two packages have the same name, or when a path is long and clarity improves with a short local name. Good aliases stay descriptive, such as crand for crypto/rand. Avoid aliases that obscure package purpose.

Q: What is the difference between go get and go install?
A: go get adds or updates a package in your current module’s go.mod and makes it available to import in your code. go install compiles and installs an executable binary to $GOPATH/bin. Use go get when you want to use a package as a library dependency. Use go install when you want to install a command-line tool, such as goimports or staticcheck.

Q: How do I know whether a package is in the standard library or third-party?
A: Standard library packages have short, unqualified import paths with no domain prefix, such as fmt, os, net/http, or crypto/rand. Third-party packages always include a domain, such as github.com/google/uuid. Browse the full standard library at pkg.go.dev/std. Use go doc <package> in your terminal to read documentation for any package already in your module graph.

Conclusion

You now have a practical import workflow for standard library packages, module dependencies, local packages, aliases, blank imports, dot imports, and workspace-mode development. These patterns cover day-to-day package management in modern Go projects.

Continue with How To Write Packages in Go, then revisit How To Use Go Modules for deeper dependency workflows. For related topics, read Understanding init in Go, How To Use the Flag Package in Go, and How To Build Go Executables for Multiple Platforms on Ubuntu.

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.