diff --git a/tech_docs/go_getting_started.md b/tech_docs/go_getting_started.md index b32a42b..d50cfed 100644 --- a/tech_docs/go_getting_started.md +++ b/tech_docs/go_getting_started.md @@ -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 ## Introduction to Golang