Update tech_docs/golang_getting_started.md

This commit is contained in:
2025-06-30 08:32:11 +00:00
parent b4dd08b075
commit 8a315584e1

View File

@@ -3833,4 +3833,245 @@ func main() {
5. **[Go net Package Documentation](https://pkg.go.dev/net)** 5. **[Go net Package Documentation](https://pkg.go.dev/net)**
6. **[Go unix Package Documentation](https://pkg.go.dev/golang.org/x/sys/unix)** 6. **[Go unix Package Documentation](https://pkg.go.dev/golang.org/x/sys/unix)**
These guides should help you get started with each package and provide a solid foundation for building more complex Go applications that interact with the operating system and network. These guides should help you get started with each package and provide a solid foundation for building more complex Go applications that interact with the operating system and network.
---
You got it\! Here's a comprehensive Golang coding standards document, adhering to the established structure and principles, with a strong emphasis on Go's idiomatic practices and the tools that enforce them.
-----
# Golang Coding Standards Documentation
## Introduction
This document outlines our conventions and best practices for writing **Golang (Go) code**. By adhering to these standards, we ensure our projects are **consistent, readable, maintainable, and performant**. This approach fosters **seamless team collaboration**, **reduces debugging time**, and **improves overall code reliability and scalability**.
Our guidelines are heavily influenced by the official Go documentation, including ["Effective Go"](https://go.dev/doc/effective_go) and ["Go Code Review Comments"](https://go.dev/wiki/CodeReviewComments), and are designed to be enforced by standard Go tools.
-----
## Code Formatting
Go has strong opinions on formatting, largely enforced by its tooling.
### 1\. `gofmt` and `goimports`
* **Description**: **Always run `gofmt`** on your code. It automatically formats Go source code according to the official style. **Always run `goimports`** (which includes `gofmt`) to also manage import paths (adding missing ones, removing unused ones, and organizing them).
* **Benefit**: Eliminates debates over formatting, ensures consistency across the entire codebase, and streamlines dependencies.
* **Usage**: Configure your IDE/editor to run `goimports` on save. From the command line:
```bash
goimports -w .
```
### 2\. Line Length
* **No Hard Limit**: Unlike some languages, Go doesn't have a strict line length limit (like 80 characters). However, strive for **reasonable line lengths** that are easy to read without horizontal scrolling. If a line becomes too long, consider breaking it into multiple lines using natural Go syntax (e.g., after commas, operators, opening parentheses).
* **Benefit**: Promotes readability and avoids awkward line breaks that `gofmt` might otherwise introduce.
### 3\. Blank Lines
* **Logical Grouping**: Use blank lines to separate logical sections of code within functions or between related function definitions.
* **Imports**: `goimports` will handle blank lines between standard library, third-party, and internal imports automatically.
* **Usage**:
```go
package main
import (
"fmt" // Standard library
"net/http"
"time"
"github.com/gin-gonic/gin" // Third-party
)
// Two blank lines before top-level declarations
type User struct {
ID int
Name string
}
func main() {
// One blank line for logical separation
router := gin.Default()
router.GET("/users/:id", getUserHandler)
router.POST("/users", createUserHandler)
// Another logical separation
server := &http.Server{
Addr: ":8080",
Handler: router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
fmt.Println("Server starting on :8080")
server.ListenAndServe()
}
```
-----
## Naming Conventions
Go's naming conventions are crucial, especially for controlling visibility (exporting).
### 1\. Visibility (Exporting)
* **`PascalCase` (first letter capitalized)**:
* **Description**: For **exported** (publicly visible) names: packages, types, functions, methods, and variables that should be accessible from outside their defining package.
* **Usage**: `MyStruct`, `GetUserByID`, `ErrNotFound`
* **`camelCase` (first letter lowercase)**:
* **Description**: For **unexported** (private to the package) names: types, functions, methods, and variables.
* **Usage**: `myHelperFunction`, `userCache`, `errorHandler`
### 2\. General Naming Guidelines
* **Descriptive and Concise**: Names should be clear but also succinct. Avoid unnecessary verbosity.
* **Bad**: `get_user_by_unique_identifier_from_database`
* **Good**: `GetUserByID`, `fetchUser`
* **Acronyms**: Keep acronyms (e.g., `ID`, `HTTP`, `URL`, `API`) consistently cased.
* **Exported**: `userID`, `httpClient` (NOT `userId`, `httpClient`)
* **Unexported**: `apiConfig` (NOT `APIConfig` unless it's a type)
* **Receiver Names (Methods)**:
* **Description**: In method declarations, the receiver variable name should be short, usually one or two letters, and consistent across methods of the same type.
* **Usage**: `(u *User)`, `(s *Server)`
* **Interface Names**:
* **Description**: If an interface has a single method, its name is typically the method name plus `er` (e.g., `Reader`, `Writer`, `Closer`).
* **Usage**: `io.Reader`, `fmt.Stringer`
* **Package Names**:
* **Description**: Package names should be short, all lowercase, and reflect the package's purpose (e.g., `http`, `fmt`, `json`, `user`, `auth`). Avoid `_` or `.` in package names.
* **Usage**: `package main`, `package models`, `package utils`
-----
## Comments and Docstrings
Good documentation in Go means clear explanations for exported entities.
### 1\. Comments (`//`)
* **Descriptive**: Use comments to explain **why** a piece of code exists, or to clarify complex logic. Avoid commenting on obvious code.
* **Concise**: Keep comments brief and to the point.
* **Up-to-Date**: Ensure comments are updated if the code changes.
* **Usage**:
```go
// Loop through connections, attempting to reconnect with exponential backoff.
for i := 0; i < maxRetries; i++ {
if err := connectToDatabase(); err == nil {
break // Successfully connected
}
time.Sleep(time.Duration(2<<i) * time.Second) // Exponential backoff
}
```
### 2\. Docstrings (Godoc Style)
* **Exported Entities**: All exported (publicly visible) packages, functions, methods, types (structs, interfaces), and variables **must** have a docstring. Unexported entities generally do not require docstrings unless their purpose is unusually complex.
* **First Sentence**: The first sentence should be a concise summary starting with the name of the documented entity.
* **Usage**: Place docstrings immediately before the entity they describe.
* **Package Doc**: A comment just before `package [name]` in one of the package's files.
```go
// Package user provides functionality for managing user accounts.
package user
```
* **Function/Method Doc**:
```go
// GetUserByID retrieves a user from the database by their ID.
// It returns the user object and an error if the user is not found
// or a database issue occurs.
func GetUserByID(id int) (*User, error) {
// ...
}
```
* **Struct/Interface Doc**:
```go
// User represents a user account in the system.
type User struct {
ID int
Username string
Email string
}
```
* **`go doc`**: Docstrings are read by the `go doc` command and rendered on `pkg.go.dev`.
-----
## Best Practices and Principles
These principles guide our overall approach to writing effective, performant, and maintainable Go code.
### 1\. Error Handling
* **Explicit Error Returns**: Go functions explicitly return errors as the last return value.
* **Nil Checks**: Always check for `nil` errors after a function call that returns an error. Do not ignore errors.
* **Error Wrapping**: Use `fmt.Errorf` with `%w` to wrap errors, providing a chain of context.
* **Custom Error Types**: Define custom error types for specific error conditions when standard errors are insufficient.
* **Usage**:
```go
func ReadFile(filename string) ([]byte, error) {
data, err := os.ReadFile(filename)
if err != nil {
// Wrap the error to add context
return nil, fmt.Errorf("failed to read file %q: %w", filename, err)
}
return data, nil
}
func processFile() {
data, err := ReadFile("nonexistent.txt")
if err != nil {
// Check if it's a specific type of error
if errors.Is(err, os.ErrNotExist) {
log.Printf("File not found: %v", err)
} else {
log.Printf("An unexpected error occurred: %v", err)
}
return
}
fmt.Println(string(data))
}
```
### 2\. Concurrency (Goroutines and Channels)
* **`go` Keyword**: Use `go` to launch goroutines for concurrent execution.
* **Channels**: Use channels to safely communicate and synchronize between goroutines. Do not use shared memory directly without explicit synchronization (e.g., `sync.Mutex`).
* **`select` Statement**: Use `select` to handle multiple channel operations (e.g., waiting for data or a timeout).
* **`context` Package**: Pass `context.Context` (with `Done()`, `Err()`, `Value()`) to goroutines for cancellation and passing request-scoped values.
* **Avoid Global State**: Minimize reliance on global variables; pass necessary data as arguments or via channels.
### 3\. Defer Statements
* **Resource Cleanup**: Use `defer` to ensure resources (like file handles, database connections, mutexes) are properly closed or released when the surrounding function returns.
* **Usage**:
```go
func openAndProcessFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return fmt.Errorf("could not open file: %w", err)
}
defer file.Close() // Ensures file is closed when function exits
// Process file...
return nil
}
```
### 4\. Package Structure
* **Small and Focused**: Keep packages small and focused on a single responsibility.
* **Clear Dependencies**: Avoid circular dependencies between packages.
* **Internal Package**: Use an `internal/` directory for code that should only be imported by packages within the same repository.
* **Cmd Package**: For executable applications, place `main.go` files inside `cmd/[app-name]/`.
### 5\. Linter and Static Analysis Tools
* **`golangci-lint`**: Use `golangci-lint` (or similar) in your CI/CD pipeline and locally during development. This tool aggregates many Go linters (e.g., `staticcheck`, `go vet`, `nilaway`) and helps enforce best practices beyond just formatting.
* **Benefit**: Catches common errors, identifies potential bugs, and enforces style guidelines automatically.
-----
## Conclusion
By diligently applying these **Golang coding standards**, we ensure our code is not only functional but also **highly readable, maintainable, and robust**. This commitment to quality coding practices promotes a more efficient development workflow, reduces technical debt, and strengthens the overall quality and reliability of our software projects.