Introduction to Go

Go (also known as Golang) is an open-source programming language developed by Google, designed to enable developers to efficiently build simple, reliable, and high-performance software.

The Go language was born in 2007, co-designed by three senior Google engineers — Robert Griesemer, Rob Pike, and Ken Thompson — and officially released as open source in 2009.

Go was originally designed to solve the pain points of large-scale software development at Google: C++ compilation was too slow, Java's runtime was too bloated, and scripting languages lacked performance. The three designers wanted to create a language that combinedPerformance of compiled languagesandDevelopment efficiency of dynamic languagesprogramming language.

The Go language mascot is a groundhog named Gopher, symbolizing the pragmatism and vitality of the Go community.

The key design goals of the Go language can be summarized as follows:

Design goalsDescription
Compilation speedCompilation of large projects should complete in seconds, not minutes.
Concurrency supportNative concurrency support at the language level, without third-party libraries.
ConcisenessMinimal syntax, no classes or inheritance, reducing cognitive burden.
Memory safetyAutomatic garbage collection (GC), avoiding the risks of manual memory management.
Static typingCompile-time type checking reduces runtime errors
Cross-platformA single set of code can be compiled into executable files for multiple platforms such as Windows, Linux, and macOS.

Three core problems Go was born to solve

ProblemThe dilemma of traditional languagesGo's solution
Slow compilation speedLarge C++ projects often take minutes or even hours to compile.Dependency management is extremely simple, and compilation speed is extremely fast, typically completing in seconds.
Concurrent programming is complexThe combination of threads, locks, and callbacks makes concurrent code difficult to write and maintain.Built-in goroutines and channels make concurrency as easy as writing sequential code.
Code is difficult to maintainC++ has too many features, and Java is over-engineered, making collaboration in large teams difficult.Minimal syntax, enforced formatting, and exactly one way to write a given solution.

Go's core design philosophy

Go's official slogan isSimple, Fast, ReliableThese three words summarize all of its design trade-offs.

Go deliberately keeps the language specification lean. The entire language specification is only about 60 pages, with only 25 keywords (compared to 80+ in C++), meaning an experienced developer can grasp the full syntax in a day or two and then focus on business logic.


The history of the Go language

The development history of Go did not happen overnight. Below are the key milestones from project inception to today.

TimeVersions/EventsDescription
2007Project initiationRob Pike, Ken Thompson, and Robert Griesemer begin designing the Go language
November 2009Go's first open source releaseOpen-sourced on GitHub under the BSD license.
March 2012Go 1.0First stable version released, promising backward compatibility.
August 2015Go 1.5Compiler bootstrapped in Go (previously written in C), removing the C dependency.
August 2018Go 1.11Introduced Go Modules, providing an initial solution to dependency management.
February 2020Go 1.14Go Modules became the officially recommended dependency management solution
March 2022Go 1.18Introduced generics, the largest language feature change since Go was released.
February 2024Go 1.22Optimized for-loop variable semantics and enhanced route pattern matching.
August 2025Go 1.24Continuously improving runtime performance, toolchain experience, and the standard library

When Go 1.0 was released, the core team made a major promise: all subsequent 1.x versions of Go would remain backward compatible. This means that Go code written ten years ago can still be compiled and run directly with today's latest compiler.


Core features of the Go language

Go's design philosophy determines its feature set — streamlined yet powerful. Below, we break down Go's most core language features one by one.

Native Concurrency: Goroutines and Channels

Concurrency is the most eye-catching feature of the Go language.GoroutineIt is an execution unit much lighter than an OS thread — each Goroutine's initial stack size is only about 2 KB, while OS threads are typically over 1 MB.

You can run hundreds of thousands of Goroutines simultaneously on an ordinary machine, something impossible with the traditional thread model.

ChannelIt is a communication pipe between Goroutines, following Go's concurrency philosophy:

Don't communicate by sharing memory; share memory by communicating. (Don't communicate by sharing memory; share memory by communicating.)

A simple Goroutine and Channel example:

Example

package main

import (
    "fmt"
    "time"
)

// worker simulates a worker goroutine, receives tasks from the channel and processes them
func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Printf("worker %d starts processing task %d\n", id, j)
        time.Sleep(time.Second) // simulate a time-consuming operation
        results <- j * 2        // send the processing result to the results channel
        fmt.Printf("worker %d completed task %d\n", id, j)
    }
}

func main() {
    const numJobs = 5
    jobs := make(chan int, numJobs)    // create a buffered task channel
    results := make(chan int, numJobs) // create a buffered result channel

    // start 3 worker goroutines
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    // send 5 tasks to the jobs channel
    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs) // Close the channel to notify workers that no more tasks will be added.

    // Collect all processing results.
    for a := 1; a <= numJobs; a++ {
        fmt.Printf("Result: %d\n\n", <-results)
    }
}

Static typing and type inference

Go is a statically typed language; all variable types are determined at compile time. But unlike C/Java, Go supportsType inference— the compiler can automatically infer variable types, so developers do not need to repeatedly declare type names.

This design maintains type safety while making code as concise as a dynamically typed language.

Example

package main

import "fmt"

func main() {
    // Full declaration: explicitly specify the type.
    var name string = "example"

    // Type inference: the compiler automatically infers the type.
    var version = 1.24      // Inferred as float64.
    count := 100            // Short variable declaration, inferred as int.
    message := "Hello Go"   // Inferred as string.

    // Multiple variable declaration.
    x, y := 10, 20          // Declare multiple variables at once.

    fmt.Println(name, version, count, message, x, y)
}

Fast compilation

Go's compilation speed is extremely fast; even large projects (hundreds of thousands of lines) can compile within seconds.

This benefits from Go's carefully designed dependency analysis mechanism: it only compiles packages that are actually referenced, and eliminates the overhead of repeatedly parsing header files found in C/C++.

Built-in garbage collection (GC)

Go usesConcurrent tri-color mark-sweep algorithmAutomatic garbage collection is implemented. The GC runs concurrently with user code, and pause times are typically at the microsecond level, without significantly affecting service response time.

Developers don't need to manually manage memory, while still achieving runtime performance close to C.

Rich standard library

Go's standard library covers most needs of modern development, allowing common tasks to be completed without introducing third-party dependencies. The table below lists the most commonly used standard library packages:

Package nameFeaturesTypical use
net/httpHTTP client and serverBuild web services and RESTful APIs
encoding/jsonJSON encoding and decodingAPI data serialization and deserialization
database/sqlDatabase access interfacesWork with drivers to operate MySQL, PostgreSQL, etc.
osOperating system interactionFile reading and writing, environment variables, process management
fmtFormatted input/outputLogging, formatting strings
syncSynchronization primitivesConcurrency control such as Mutex, WaitGroup, Once
testingTesting frameworkUnit testing, benchmarking, example testing
timeTime handlingTimers, tickers, time formatting
contextContext propagationTimeout control, request cancellation, value passing
ioI/O abstractionUnified read/write interfaces
cryptoCryptographic algorithmsHashing, symmetric/asymmetric encryption, TLS
flagCommand-line argument parsingCLI tool development

Cross-platform compilation

Go compiler supportCross-compilationOn any platform, compile executable files for other target platforms. Just setGOOSandGOARCHJust two environment variables.

# 在 macOS 上编译 Linux 可执行文件
$ GOOS=linux GOARCH=amd64 go build -o app-linux main.go

# 在 Linux 上编译 Windows 可执行文件
$ GOOS=windows GOARCH=amd64 go build -o app.exe main.go

The build output is a standalone binary; the target machine doesn't need to install the Go runtime or any dependencies—just run it directly.


Application areas of the Go language

With the advantages of high performance, easy deployment, and native concurrency, Go has been widely adopted in the following areas.

Cloud-native and infrastructure

Go is the modern cloud-native technology stack'sDe facto standard languageAlmost all well-known cloud-native projects are written in Go.

ProjectDescriptionDomain
DockerContainerization platform that changed the way software is delivered.Container
Kubernetes (K8s)Container orchestration system, the de facto standard for cloud-native.Container Orchestration
etcdDistributed key-value store, a core component of K8s.Distributed storage
PrometheusMonitoring and alerting systemsObservability
GrafanaData visualization platform (backend)Observability
TerraformInfrastructure as Code (IaC) toolsDevOps
ConsulService discovery and configuration managementService mesh
TraefikCloud-native reverse proxy and load balancerNetworking

Microservices and API development

Go relies onExtremely low memory footprintandExcellent concurrency processing capability, making it an ideal choice for building microservices. A simple HTTP service can run with just a few MB of memory.

Common Go web frameworks include Gin, Echo, Fiber, etc. In performance benchmarks, they usually far outperform comparable frameworks in other languages.

CLI tool development

Go's ability to compile into a single binary makes it the first choice for CLI tool development. Users don't need to install any runtime; just download one file and use it.

Well-known projects include:Hugo(static site generator),fzf(fuzzy search tool),gh(GitHub CLI) andkubectl(Kubernetes command-line tool).

Network programming and distributed systems

In Go's standard librarynetThe package provides comprehensive network programming support, and the goroutine model naturally fits high-concurrency network services (such as proxy servers, message queues, and game servers). The Go implementation of the gRPC framework is also a mainstream solution for inter-service communication in distributed systems.

Blockchain

Go also has important applications in the blockchain field.go-ethereum(Geth)It is the most mainstream Ethereum client implementation, and core components of Hyperledger Fabric are also written in Go.

AI and machine learning (emerging field)

Although Python remains the dominant language in the AI/ML field, Go is gradually entering this field.Ollama(local large model runtime tool) andLangChainGoThe rise of such projects showcases Go's potential in AI infrastructure and LLM application development.


Quick start

Setting up a Go development environment from scratch takes only three steps: install, configure, and write code.

Install Go

Visitgo.dev/dlDownload the installer for your platform. macOS users can also install via Homebrew.

# macOS (Homebrew)
$ brew install go

# 验证安装
$ go version
go version go1.24.0 darwin/arm64

The first Go program

Create a project directory and write the classic Hello World program.

Example

// File path: main.go
// Every Go program must belong to a package; the main package is the entry point of an executable.

package main

// Import the standard library package for formatted output.
import "fmt"

// main function: the entry point of the program, no parameters, no return value.
func main() {
    // Println prints a line and automatically adds a newline at the end
    fmt.Println("Hello, EXAMPLE!")
    fmt.Println("Welcome to the world of Go language")
}

There are two ways to run it: directly (without producing a binary) or after compiling.

# 方式一:直接运行(开发调试时常用)
$ go run main.go
Hello, EXAMPLE!
欢迎来到 Go 语言的世界

# 方式二:编译为二进制文件后执行(生产部署时常用)
$ go build -o hello main.go
$ ./hello
Hello, EXAMPLE!
欢迎来到 Go 语言的世界

Go Modules initialization

For formal projects, it is recommended to use Go Modules to manage dependencies. Module names usually use repository paths (such as GitHub URLs) so that others can reference them.

# 初始化 Go Module
$ mkdir my-go-project && cd my-go-project
$ go mod init github.com/example/my-go-project
go: creating new go.mod: module github.com/example/my-go-project

# go.mod 文件内容
module github.com/example/my-go-project

go 1.24

Basic syntax overview

Go's syntax is concise and consistent. Here's a quick tour of the most common syntax elements; each example is a complete, directly runnable program.

Variables and Constants

Go provides multiple variable declaration methods to suit different scenarios. Constants useconstKeyword declaration.

Example

package main

import "fmt"

func main() {
    // Method 1: Standard declaration (explicit type)
    var age int = 25

    // Method 2: Declare then assign (type specified at declaration)
    var score float64
    score = 98.5

    // Method 3: Short variable declaration (most common, only inside functions)
    name := "example"

    // Method 4: Multiple variables declared simultaneously
    x, y := 10, 20

    // Constant declaration (determined at compile time, cannot be modified)
    const Pi = 3.14159
    const AppName = "EXAMPLE"

    fmt.Println(name, age, score, x, y, Pi, AppName)
}

Control Flow

Go's control flow is streamlined toif、forandswitchThree.Go has no while keyword; all loops are implemented with for.

Example

package main

import "fmt"

func main() {
    // if statement: The condition expression doesn't need parentheses, but braces are required.
    score := 85
    if score >= 90 {
        fmt.Println("EXAMPLE rating: A")
    } else if score >= 60 {
        fmt.Println("EXAMPLE rating: B")
    } else {
        fmt.Println("EXAMPLE rating: C")
    }

    // for loop 1: Standard three-element form (similar to C's for)
    fmt.Print("Count: ")
    for i := 0; i < 5; i++ {
        fmt.Print(i, " ")
    }
    fmt.Println()

    // for loop 2: Condition only (similar to while)
    sum := 0
    n := 1
    for n <= 10 {
        sum += n
        n++
    }
    fmt.Println("Sum of 1 to 10:", sum)

    // for loop 3: range iteration (most common)
    fruits := []string{"apple", "banana", "cherry"}
    for index, fruit := range fruits {
        fmt.Printf("Index %d: %s\n", index, fruit)
    }

    // switch statement: Each case automatically breaks, no need to add manually
    day := "Monday"
    switch day {
    case "Monday":
        fmt.Println(A new week has begun.)
    case Friday:
        fmt.Println(The weekend is approaching.)
    default:
        fmt.Println(An ordinary day.)
    }
}

Function

Go function usagefuncKeyword declarations, supportingMultiple return values— this is the basis of Go's error handling mechanism.

Example

package main

import (
    "errors"
    "fmt"
)

// add function: both parameters are of type int, returns an int
func add(a, b int) int {
    return a + b
}

// divide function: returns two values — result and error
// Go idiomatic (result, error) pattern for error handling
func divide(a, b float64) (float64, error) {
    if b == 0 {
        // return zero value and custom error
        return 0, errors.New(Divisor cannot be zero)
    }
    return a / b, nil // nil means no error
}

// swap function: uses multiple return values to return multiple results
func swap(x, y string) (string, string) {
    return y, x
}

func main() {
    // calling an ordinary function
    sum := add(10, 20)
    fmt.Println("10 + 20 =", sum)

    // calling a function with multiple return values and checking the error
    result, err := divide(10, 2)
    if err != nil {
        fmt.Println(Error:, err)
    } else {
        fmt.Println("10 / 2 =", result)
    }

    // test division by zero case
    _, err = divide(10, 0) // _ is used to ignore unwanted return values
    if err != nil {
        fmt.Println(Division by zero error:, err) // expected to output this error
    }

    // multiple return value swap
    first, second := swap("EXAMPLE", "Hello")
    fmt.Println(After swap:, first, second)
}

Go does not have a try-catch exception mechanism; instead, it explicitly handles errors by returning error values from functions. This design makes error handling paths clear at a glance and avoids implicit control flow.

Structs and methods

Go has no concept of classes; it usesstruct(structs) to organize data, throughDefining methods for typesTo implement object-oriented style behavior. Methods are functions with a receiver.

Example

package main

import "fmt"

// User defines a user struct (similar to classes in other languages)
type User struct {
    Name  string // Capitalized initial letter = public field (accessible from external packages)
    Email string
    age   int    // Lowercase initial letter = private field (only accessible within the package)
}

// Greet is a method defined for the User type
// (u User) is a value receiver; modifications to u inside the method do not affect the original value
func (u User) Greet() string {
    return fmt.Sprintf("Hello, I am %s, email is %s", u.Name, u.Email)
}

// Birthday uses a pointer receiver; the method can modify the original value
func (u *User) Birthday() {
    u.age++ // Modify the age field of the original struct directly through the pointer
}

func main() {
    // Create a struct instance
    user := User{
        Name:  "example",
        Email: "example@example.com",
        age:   25,
    }

    // Call the method
    fmt.Println(user.Greet())
    fmt.Printf("Age before birthday: %d\n", user.age)

    user.Birthday() // Using a pointer receiver, age is incremented by 1
    fmt.Printf("Age after birthday: %d\n", user.age)
}

interface

Go's interface isImplicit implementation— as long as a type implements all the methods of an interface, it automatically satisfies the interface without explicitly declaring `implements`. This design greatly reduces code coupling.

Example

package main

import (
    "fmt"
    "math"
)

// Shape interface: defines the behavioral specification for geometric shapes
type Shape interface {
    Area() float64      // Calculate area
    Perimeter() float64 // Calculate perimeter
}

// Circle struct
type Circle struct {
    Radius float64
}

// Circle implements the Shape interface (implicit implementation, no explicit declaration needed)
func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

// Rectangle struct
type Rectangle struct {
    Width, Height float64
}

// Rectangle also implicitly implements the Shape interface
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

// PrintShape accepts any type that implements the Shape interface
func PrintShape(s Shape) {
    fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}

func main() {
    c := Circle{Radius: 5}          // A circle with radius 5
    r := Rectangle{Width: 4, Height: 6} // A rectangle with width 4 and height 6

    fmt.Println("Circle (EXAMPLE example):")
    PrintShape(c)

    fmt.Println(Rectangle (EXAMPLE Example):)
    PrintShape(r)
}

Go's interface design encourages "small interfaces" — typically containing only 1-3 methods. The standard library's io.Reader (only a Read method) and io.Writer (only a Write method) are the most classic examples.


Common Examples

The following are two complete examples close to real-world scenarios, showing Go's usage in actual development.

Building an HTTP server

You can build a fully functional web service using only the standard library net/http, without any third-party framework.

Example

// File path: server.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
    "net/http"
)

// Response defines the data structure of the JSON response
type Response struct {
    Code    int    `json:"code"`    // Struct tags specify JSON field names
    Message string `json:"message"`
    Data    any    `json:"data,omitempty"` // omitempty: omit the field when its value is empty
}

// helloHandler handles requests for the /hello route
func helloHandler(w http.ResponseWriter, r *http.Request) {
    // Only allow GET requests
    if r.Method != http.MethodGet {
        http.Error(w, Only GET requests are supported, http.StatusMethodNotAllowed)
        return
    }

    // Get name from query parameter, default is "EXAMPLE"
    name := r.URL.Query().Get("name")
    if name == "" {
        name = "EXAMPLE"
    }

    // Build response data
    resp := Response{
        Code:    200,
        Message: fmt.Sprintf(Hello, %s! Welcome to the Go HTTP service, name),
    }

    // Set response headers and return JSON
    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    json.NewEncoder(w).Encode(resp)
}

func main() {
    // Register route handler functions
    http.HandleFunc("/hello", helloHandler)

    addr := ":8080"
    fmt.Printf(EXAMPLE server started, listening at: http://localhost%s\n", addr)
    fmt.Printf(Example access: http://localhost%s/hello?name=Go developer\n", addr)

    // Start HTTP service (blocking, until the service stops)
    log.Fatal(http.ListenAndServe(addr, nil))
}

After starting the service, visit the corresponding address to get a JSON response:

$ go run server.go
EXAMPLE 服务器启动,监听地址: http://localhost:8080
访问示例: http://localhost:8080/hello?name=Go开发者

# 使用 curl 测试
$ curl http://localhost:8080/hello?name=Go开发者
{"code":200,"message":"你好,Go开发者!欢迎访问 Go HTTP 服务"}

$ curl http://localhost:8080/hello
{"code":200,"message":"你好,EXAMPLE!欢迎访问 Go HTTP 服务"}

For production-grade web services, it is recommended to choose a suitable framework based on actual needs. For small projects, the standard library is sufficient; when routing groups, middleware, and other features are needed, Gin or Echo can be chosen.

Concurrent worker pool

This is a classic application scenario for Go concurrency: using a limited number of goroutines to process a large batch of tasks in parallel.

Example

// File path: workerpool.go
package main

import (
    "fmt"
    "sync"
    "time"
)

// worker reads tasks from the jobs channel, processes them, and writes the results to the results channel
// call wg.Done() when task processing is complete to notify the WaitGroup
func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
    defer wg.Done() // mark this worker as done regardless of how the function exits
    for job := range jobs {
        fmt.Printf("[Worker %d] processing task %d\n\n", id, job)
        time.Sleep(200 * time.Millisecond) // simulate task processing time
        results <- job * job               // compute the square as the result
    }
}

func main() {
    const numJobs = 10    // total number of tasks
    const numWorkers = 3  // number of concurrent workers

    jobs := make(chan int, numJobs)     // buffered task channel
    results := make(chan int, numJobs)  // buffered result channel
    var wg sync.WaitGroup               // used to wait for all workers to complete

    fmt.Println("=== EXAMPLE Worker Pool Example ===")

    // start a fixed number of worker goroutines
    for w := 1; w <= numWorkers; w++ {
        wg.Add(1) // increment the WaitGroup counter for each worker started
        go worker(w, jobs, results, &wg)
    }

    // send all tasks to the channel
    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs) // closing the jobs channel causes the workers' range loops to exit automatically

    // wait for all workers to complete, then close the results channel
    go func() {
        wg.Wait()
        close(results)
    }()

    // collect and print all results
    fmt.Println("Result Summary:")
    for result := range results {
        fmt.Printf("%d ", result)
    }
    fmt.Println("\nAll tasks have been processed)
}
$ go run workerpool.go
=== EXAMPLE Worker Pool 示例 ===
[Worker 3] 处理任务 1
[Worker 1] 处理任务 3
[Worker 2] 处理任务 2
[Worker 1] 处理任务 4
[Worker 3] 处理任务 5
[Worker 2] 处理任务 6
...
结果汇总:
1 4 9 16 25 36 49 64 81 100
所有任务处理完成

Common tools and commands

Go comes with a complete development toolchain, eliminating the need to install additional build tools. The following is a quick reference for the most commonly used go commands:

CommandFeaturesCommon Scenarios
go buildCompile source codeGenerate executable files for deployment
go runCompile and runQuickly test code, develop and debug
go testRun testsRun test functions in _test.go files
go mod initInitialize moduleGenerate a go.mod file when creating a new project.
go mod tidyTidy dependenciesDownload missing dependencies and remove unused dependencies.
go fmtFormat codeUnify code style (mandatory in the Go community).
go vetStatic analysisCheck for suspicious constructs in code
go getInstall dependency packagesDownload and install the specified package
go docView documentationView package or function documentation in the terminal
go envView environment variablesView configurations such as GOPATH and GOROOT
go cleanClean build cacheFree up disk space

go fmt is a mandatory convention in the Go community—all Go code should be formatted with go fmt. This eliminates arguments about code style and keeps codebases highly consistent. Most editors (VS Code, GoLand, etc.) support running go fmt automatically on save.


Caveats and common issues

The following are some of the most common problems encountered by Go beginners and best-practice recommendations.

GOPATH and Go Modules

Since Go 1.16, Go Modules has become the default mode.New projects no longer need to be placed in the GOPATH directory; they can be created anywhere.

If you see tutorials mentioning complex GOPATH configuration, you can usually ignore it—Go Modules can meet the vast majority of development needs.

Error handling cannot be ignored

The Go compiler does not force you to handle error, but ignoring errors is bad practice. At the very least, log or print error information during development.

Example

package main

import (
    "fmt"
    "os"
)

func main() {
    // Not recommended: ignoring errors
    data, _ := os.ReadFile("config.txt")
    fmt.Println(string(data))

    // Recommended: explicitly handle errors
    data, err := os.ReadFile("config.txt")
    if err != nil {
        fmt.Printf("Failed to read file: %v\n", err)
        return
    }
    fmt.Println(string(data))
}

Goroutine leak

After starting a goroutine, if it blocks forever and cannot exit, it causes a goroutine leak. In long-running services, goroutine leaks can gradually exhaust memory.

Best practices:

  • Ensure every goroutine has an exit path.
  • Usagecontext.ContextPass cancellation signals
  • Usagesync.WaitGroupTrack the goroutine lifecycle.

Slices share underlying arrays.

Multiple slices may share the same underlying array. When you perform append or modification on one slice, you need to be careful whether it affects other slices referencing the same underlying array.

When in doubt, use copy() to create an independent copy.

The difference between a nil interface and a nil pointer.

This is a classic Go pitfall: when an interface value contains a nil pointer, the interface itself is not nil. This meansif err != nilmay return true, but the actual pointer is nil.

When returning an error, you should directly return nil rather than returning an error interface variable containing a nil pointer.

Go's type system is simple but has its own "personality." Developers coming from other languages should take the time to read the official Effective Go documentation (golang.org/doc/effective_go) to learn idiomatic Go coding practices and design patterns.

Code Organization

Go usesPackageOrganize code, not the folder directory structure.

All .go files in the same directory must belong to the same package, and the package name usually matches the directory name (except for the main package and _test files). Go has no concept of 'subpackages'—packages in different directories are completely independent even if their paths are similar.


Summary

With its minimalist syntax, excellent performance, and native concurrency support, Go has established an irreplaceable position in fields such as cloud-native, microservices, and DevOps.

It is not a language that pursues features, but a language that pursues engineering efficiency—letting teams write less code and get more stable systems.

The advantages and applicable scenarios of Go are summarized as follows:

DimensionGo's performance
Learning CurveMinimalist syntax; developers with a programming background can get started within a week.
Compilation speedLarge projects compile in seconds, providing an extremely fast development feedback loop
Runtime performanceClose to C/C++, far exceeds Python/Ruby/JavaScript
Memory usageA basic HTTP service only requires 5-10 MB of memory.
Concurrency HandlingGoroutines are extremely lightweight; tens of thousands of concurrent tasks are not a problem.
Deployment difficultyCompiles to a standalone binary; just copy and run
Best forCloud-native services, microservices, CLI tools, distributed systems, and network programming.
Less suitableGUI desktop applications, mobile development, OS kernels, and embedded low-level systems.

If you are building a concurrent backend service, a CLI tool, or an infrastructure project, Go is a choice worth serious consideration.

other extensions