Update tech_docs/go_getting_started.md
This commit is contained in:
@@ -1,3 +1,405 @@
|
|||||||
|
# Go (Golang) Comprehensive Guide
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
1. Introduction to Go Structs
|
||||||
|
- Defining a Struct
|
||||||
|
- Creating Instances
|
||||||
|
- Accessing and Modifying Fields
|
||||||
|
- Embedding Structs
|
||||||
|
- Methods on Structs
|
||||||
|
- JSON Encoding/Decoding
|
||||||
|
2. Project Structure and Best Practices
|
||||||
|
- Entry Points
|
||||||
|
- Project Structure
|
||||||
|
- Explanation of Directories
|
||||||
|
- Best Practices
|
||||||
|
- Example Project
|
||||||
|
|
||||||
|
## 1. Introduction to Go Structs
|
||||||
|
|
||||||
|
### Defining a Struct
|
||||||
|
|
||||||
|
A struct in Go is a composite data type that groups together variables under a single name. It is defined using the `type` and `struct` keywords.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Define a struct type called Person
|
||||||
|
type Person struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
City string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Creating an instance of the Person struct
|
||||||
|
p := Person{Name: "Alice", Age: 30, City: "New York"}
|
||||||
|
|
||||||
|
// Accessing and modifying struct fields
|
||||||
|
fmt.Println("Name:", p.Name)
|
||||||
|
fmt.Println("Age:", p.Age)
|
||||||
|
fmt.Println("City:", p.City)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating Instances
|
||||||
|
|
||||||
|
You can create instances of a struct using several methods:
|
||||||
|
|
||||||
|
- Using a struct literal:
|
||||||
|
|
||||||
|
```go
|
||||||
|
p := Person{Name: "Alice", Age: 30, City: "New York"}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Creating an instance with zero values and then setting fields:
|
||||||
|
|
||||||
|
```go
|
||||||
|
var p Person
|
||||||
|
p.Name = "Bob"
|
||||||
|
p.Age = 25
|
||||||
|
p.City = "San Francisco"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Using the `new` keyword (returns a pointer to the struct):
|
||||||
|
|
||||||
|
```go
|
||||||
|
p := new(Person)
|
||||||
|
p.Name = "Charlie"
|
||||||
|
p.Age = 28
|
||||||
|
p.City = "Los Angeles"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Accessing and Modifying Fields
|
||||||
|
|
||||||
|
Access struct fields using the dot notation:
|
||||||
|
|
||||||
|
```go
|
||||||
|
p := Person{Name: "Alice", Age: 30, City: "New York"}
|
||||||
|
|
||||||
|
// Access fields
|
||||||
|
fmt.Println(p.Name) // Output: Alice
|
||||||
|
|
||||||
|
// Modify fields
|
||||||
|
p.Age = 31
|
||||||
|
fmt.Println(p.Age) // Output: 31
|
||||||
|
```
|
||||||
|
|
||||||
|
### Embedding Structs
|
||||||
|
|
||||||
|
Go supports embedding structs within other structs to create more complex data structures.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Address struct {
|
||||||
|
City string
|
||||||
|
State string
|
||||||
|
ZipCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Address // Embedding Address struct
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p := Person{
|
||||||
|
Name: "Alice",
|
||||||
|
Age: 30,
|
||||||
|
Address: Address{
|
||||||
|
City: "New York",
|
||||||
|
State: "NY",
|
||||||
|
ZipCode: "10001",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(p.Name) // Output: Alice
|
||||||
|
fmt.Println(p.Address.City) // Output: New York
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Methods on Structs
|
||||||
|
|
||||||
|
You can define methods on structs, which are functions with a receiver argument.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Person struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Person) Greet() {
|
||||||
|
fmt.Printf("Hello, my name is %s and I am %d years old.\n", p.Name, p.Age)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p := Person{Name: "Alice", Age: 30}
|
||||||
|
p.Greet() // Output: Hello, my name is Alice and I am 30 years old.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### JSON Encoding/Decoding
|
||||||
|
|
||||||
|
Go’s standard library includes support for JSON encoding and decoding, which works seamlessly with structs.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
City string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p := Person{Name: "Alice", Age: 30, City: "New York"}
|
||||||
|
|
||||||
|
// Encode to JSON
|
||||||
|
jsonData, err := json.Marshal(p)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(string(jsonData)) // Output: {"Name":"Alice","Age":30,"City":"New York"}
|
||||||
|
|
||||||
|
// Decode from JSON
|
||||||
|
jsonStr := `{"Name":"Bob","Age":25,"City":"San Francisco"}`
|
||||||
|
var p2 Person
|
||||||
|
err = json.Unmarshal([]byte(jsonStr), &p2)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(p2) // Output: {Bob 25 San Francisco}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Project Structure and Best Practices
|
||||||
|
|
||||||
|
### Entry Points
|
||||||
|
|
||||||
|
The entry point of a Go application is the `main` package, which contains a `main` function. This is where the execution of your application begins.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// main.go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("Hello, World!")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
|
||||||
|
A typical Go project structure looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
myproject/
|
||||||
|
├── cmd/
|
||||||
|
│ └── myapp/
|
||||||
|
│ └── main.go
|
||||||
|
├── pkg/
|
||||||
|
│ └── mypackage/
|
||||||
|
│ └── mypackage.go
|
||||||
|
├── internal/
|
||||||
|
│ └── myinternalpackage/
|
||||||
|
│ └── myinternalpackage.go
|
||||||
|
├── api/
|
||||||
|
│ └── handlers.go
|
||||||
|
├── web/
|
||||||
|
│ ├── templates/
|
||||||
|
│ └── static/
|
||||||
|
├── configs/
|
||||||
|
│ └── config.yaml
|
||||||
|
├── scripts/
|
||||||
|
│ └── build.sh
|
||||||
|
├── test/
|
||||||
|
│ └── integration_test.go
|
||||||
|
├── go.mod
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Explanation of Directories
|
||||||
|
|
||||||
|
- **cmd/**: Contains the entry points of the applications. Each subdirectory under `cmd` represents a separate application. This is useful for projects with multiple binaries.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// cmd/myapp/main.go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "myproject/pkg/mypackage"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
mypackage.DoSomething()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **pkg/**: Contains library code that can be imported by other projects and applications. It is reusable and shared across different parts of the project.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// pkg/mypackage/mypackage.go
|
||||||
|
package mypackage
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func DoSomething() {
|
||||||
|
fmt.Println("Doing something!")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **internal/**: Similar to `pkg`, but the code here is only used internally by your project. It cannot be imported by other projects.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// internal/myinternalpackage/myinternalpackage.go
|
||||||
|
package myinternalpackage
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func InternalFunction() {
|
||||||
|
fmt.Println("Internal function")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **api/**: Contains code related to your API, such as handlers, routes, and middleware.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// api/handlers.go
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HelloHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintf(w, "Hello, World!")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **web/**: Contains web-related resources like HTML templates, CSS, and JavaScript files.
|
||||||
|
|
||||||
|
- **configs/**: Stores configuration files, such as YAML, JSON, or TOML files.
|
||||||
|
|
||||||
|
- **scripts/**: Contains scripts for tasks like building, deploying, and running the project.
|
||||||
|
|
||||||
|
- **test/**: Houses test files, such as integration tests or end-to-end tests.
|
||||||
|
|
||||||
|
- **go.mod**: The Go module file, which defines the module path and dependencies.
|
||||||
|
|
||||||
|
```go
|
||||||
|
module myproject
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gorilla/mux v1.8.0
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
- **Use Modules**: Always use Go modules (`go.mod`) to manage dependencies.
|
||||||
|
- **Consistent Naming**: Use consistent naming conventions for packages and files.
|
||||||
|
- **Small Packages**: Keep packages small and focused on a single responsibility.
|
||||||
|
- **Documentation**: Write documentation for your packages and functions using GoDoc comments.
|
||||||
|
- **Testing**: Write tests for your code using the `testing` package. Place unit tests in the same package with a `_test.go` suffix.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// pkg/mypackage/mypackage_test.go
|
||||||
|
package mypackage
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestDoSomething(t *testing.T) {
|
||||||
|
// Test code
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Version Control**: Use a version control system like Git. Keep your `go.mod` and `go.sum` files updated.
|
||||||
|
- **CI/CD**: Integrate Continuous Integration and Continuous Deployment pipelines to automate testing and deployment.
|
||||||
|
|
||||||
|
### Example Project
|
||||||
|
|
||||||
|
Here’s a simple example project to demonstrate the structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
simpleapp/
|
||||||
|
├── cmd/
|
||||||
|
│ └── simpleapp/
|
||||||
|
│ └── main.go
|
||||||
|
├── pkg/
|
||||||
|
│ └── greeter/
|
||||||
|
│ └── greeter.go
|
||||||
|
├── internal/
|
||||||
|
│ └── util/
|
||||||
|
│ └── util.go
|
||||||
|
├── go.mod
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**go.mod:**
|
||||||
|
|
||||||
|
```go
|
||||||
|
module simpleapp
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
```
|
||||||
|
|
||||||
|
**cmd/simpleapp/main.go:**
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"simpleapp/pkg/greeter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(greeter.Greet("World"))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**pkg/greeter/greeter.go:**
|
||||||
|
|
||||||
|
```go
|
||||||
|
package greeter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func Greet(name string) string {
|
||||||
|
return fmt.Sprintf("Hello, %s!", name)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**internal/util/util.go:**
|
||||||
|
|
||||||
|
```go
|
||||||
|
package util
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func ToUpper(s string) string {
|
||||||
|
return strings.ToUpper(s)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
With this structure, your Go projects will be organized, maintainable, and scalable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# Golang Guide
|
# Golang Guide
|
||||||
|
|
||||||
## Introduction to Golang
|
## Introduction to Golang
|
||||||
|
|||||||
Reference in New Issue
Block a user