Go Language Fundamentals
Lexical Elements
Keywords
- Basic keywords (if, for, func, etc.)
- Type-related keywords (type, struct, interface)
- Package-related keywords (package, import)
- Control flow keywords (return, break, continue)
Identifiers
- Naming conventions
- Exported vs unexported names
- Package names
- Variable naming best practices
Operators
- Arithmetic operators
- Comparison operators
- Logical operators
- Address and pointer operators
- Channel operators
Data Types
-
Basic Types
- Integers (int8, int16, int32, int64)
- Floating-point (float32, float64)
- Complex numbers
- Boolean
- String
-
Composite Types
- Arrays
- Slices
- Maps
- Structs
- Pointers
Comments
- Single-line comments
- Multi-line comments
- Package documentation
- GoDoc conventions
Code Examples
Basic Types and Variables
package main
import "fmt"
func main() {
// Numeric types
var i int = 42
var f float64 = 3.14
complex := 1 + 2i
// String and rune
str := "Hello, 世界"
rune := '世'
// Arrays and slices
arr := [3]int{1, 2, 3}
slice := []int{1, 2, 3, 4}
slice = append(slice, 5)
// Maps
m := map[string]int{
"one": 1,
"two": 2,
}
fmt.Printf("Types: %T %T %T %T %T\n", i, f, complex, str, rune)
fmt.Printf("Slice: %v\n", slice)
fmt.Printf("Map: %v\n", m)
}
Composite Types
// Struct definition
type Person struct {
Name string
Age int
}
// Interface
type Speaker interface {
Speak() string
}
// Method implementation
func (p Person) Speak() string {
return fmt.Sprintf("My name is %s", p.Name)
}
// Function type
type MathFunc func(int, int) int
// Function using function type
func operate(a, b int, op MathFunc) int {
return op(a, b)
}
// Usage
func main() {
// Struct and interface usage
p := Person{Name: "Alice", Age: 30}
var s Speaker = p
fmt.Println(s.Speak())
// Function types
add := func(a, b int) int { return a + b }
result := operate(5, 3, add)
fmt.Printf("5 + 3 = %d\n", result)
}
Basic Syntax
-
Package Declaration
package main -
Import Statements
import (
"fmt"
"strings"
) -
Variable Declarations
var name string
age := 25
Control Structures
-
Conditional Statements
- if/else
- switch/case
- select (for channels)
-
Loops
- for loop variations
- range iteration
- break and continue
Functions
-
Function Declaration
func functionName(param1 type1, param2 type2) returnType {
// function body
} -
Multiple Return Values
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
} -
Variadic Functions
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
Error Handling
-
Error Type and Custom Errors
// Standard error interface
type error interface {
Error() string
}
// Custom error type
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Message)
} -
Error Handling Patterns
func processUser(name string, age int) (*User, error) {
// Input validation
if name == "" {
return nil, &ValidationError{"name", "cannot be empty"}
}
if age < 0 {
return nil, &ValidationError{"age", "must be positive"}
}
// Database operation simulation
user, err := db.CreateUser(name, age)
if err != nil {
return nil, fmt.Errorf("failed to create user: %w", err)
}
return user, nil
}
// Error handling with type assertion
func handleUser(name string, age int) {
user, err := processUser(name, age)
if err != nil {
if ve, ok := err.(*ValidationError); ok {
log.Printf("Validation error: %v", ve)
return
}
log.Printf("Unexpected error: %v", err)
return
}
fmt.Printf("Created user: %v\n", user)
}
Concurrency Patterns
-
Basic Goroutine and Channel Usage
func main() {
// Create a channel
ch := make(chan string)
// Start a goroutine
go func() {
ch <- "Hello from goroutine!"
}()
// Receive from channel
msg := <-ch
fmt.Println(msg)
} -
Worker Pool Pattern
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Printf("worker %d processing job %d\n", id, j)
time.Sleep(time.Second) // Simulate work
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Start workers
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Send jobs
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
// Collect results
for a := 1; a <= 5; a++ {
<-results
}
} -
Select Statement
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "two"
}()
// Using select to handle multiple channels
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("Received", msg1)
case msg2 := <-ch2:
fmt.Println("Received", msg2)
case <-time.After(3 * time.Second):
fmt.Println("Timeout!")
return
}
}
}
Module System and Package Management
-
Project Structure
myproject/
├── go.mod
├── go.sum
├── main.go
└── pkg/
├── models/
│ └── user.go
└── handlers/
└── user_handler.go -
Module Setup
# Initialize a new module
go mod init example.com/myproject
# Add dependencies
go get github.com/pkg/errors
go get golang.org/x/sync
# Update dependencies
go get -u ./...
# Clean up unused dependencies
go mod tidy -
Package Organization Example
// pkg/models/user.go
package models
type User struct {
ID int
Name string
Age int
}
// pkg/handlers/user_handler.go
package handlers
import (
"example.com/myproject/pkg/models"
"github.com/pkg/errors"
)
func CreateUser(name string, age int) (*models.User, error) {
if name == "" {
return nil, errors.New("name cannot be empty")
}
return &models.User{Name: name, Age: age}, nil
}
// main.go
package main
import (
"fmt"
"log"
"example.com/myproject/pkg/handlers"
)
func main() {
user, err := handlers.CreateUser("Alice", 30)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created user: %+v\n", user)
} -
Module Configuration (go.mod)
module example.com/myproject
go 1.21
require (
github.com/pkg/errors v0.9.1
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
)