Add Chapter 3: Data Structures - Arrays, Slices, Maps, and Structs (Deep Dive)
This commit is contained in:
1063
chapters/chapter-3-data-structures.md
Normal file
1063
chapters/chapter-3-data-structures.md
Normal file
File diff suppressed because it is too large
Load Diff
3
chapters/chapter-3/go.mod
Normal file
3
chapters/chapter-3/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module go-tutorial
|
||||||
|
|
||||||
|
go 1.21
|
||||||
366
chapters/chapter-3/main.go
Normal file
366
chapters/chapter-3/main.go
Normal file
@@ -0,0 +1,366 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 3.1 数组示例
|
||||||
|
func arrayExamples() {
|
||||||
|
fmt.Println("=== 数组示例 ===")
|
||||||
|
|
||||||
|
// 声明数组
|
||||||
|
var arr1 [5]int
|
||||||
|
arr2 := [3]string{"A", "B", "C"}
|
||||||
|
arr3 := [4]int{10, 20, 30, 40}
|
||||||
|
arr4 := [5]int{1, 2} // 部分初始化
|
||||||
|
arr5 := [...]int{1, 2, 3, 4, 5}
|
||||||
|
|
||||||
|
fmt.Printf("arr1: %v\n", arr1)
|
||||||
|
fmt.Printf("arr2: %v\n", arr2)
|
||||||
|
fmt.Printf("arr3: %v\n", arr3)
|
||||||
|
fmt.Printf("arr4: %v\n", arr4)
|
||||||
|
fmt.Printf("arr5: %v\n", arr5)
|
||||||
|
|
||||||
|
// 访问和修改
|
||||||
|
arr1[0] = 99
|
||||||
|
fmt.Printf("修改后 arr1: %v\n", arr1)
|
||||||
|
|
||||||
|
// 多维数组
|
||||||
|
matrix := [2][3]int{
|
||||||
|
{1, 2, 3},
|
||||||
|
{4, 5, 6},
|
||||||
|
}
|
||||||
|
fmt.Printf("matrix[0][1]: %d\n", matrix[0][1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.2 切片示例
|
||||||
|
func sliceExamples() {
|
||||||
|
fmt.Println("\n=== 切片示例 ===")
|
||||||
|
|
||||||
|
// 从数组创建
|
||||||
|
arr := [5]int{1, 2, 3, 4, 5}
|
||||||
|
s1 := arr[0:3]
|
||||||
|
s2 := arr[1:]
|
||||||
|
s3 := arr[:3]
|
||||||
|
s4 := arr[:]
|
||||||
|
|
||||||
|
fmt.Printf("s1: %v, len=%d, cap=%d\n", s1, len(s1), cap(s1))
|
||||||
|
fmt.Printf("s2: %v, len=%d, cap=%d\n", s2, len(s2), cap(s2))
|
||||||
|
fmt.Printf("s3: %v, len=%d, cap=%d\n", s3, len(s3), cap(s3))
|
||||||
|
fmt.Printf("s4: %v, len=%d, cap=%d\n", s4, len(s4), cap(s4))
|
||||||
|
|
||||||
|
// make 创建
|
||||||
|
s5 := make([]int, 5)
|
||||||
|
s6 := make([]int, 3, 10)
|
||||||
|
fmt.Printf("s5: %v, len=%d, cap=%d\n", s5, len(s5), cap(s5))
|
||||||
|
fmt.Printf("s6: %v, len=%d, cap=%d\n", s6, len(s6), cap(s6))
|
||||||
|
|
||||||
|
// append
|
||||||
|
s7 := []int{1, 2, 3}
|
||||||
|
s7 = append(s7, 4)
|
||||||
|
s7 = append(s7, 5, 6, 7)
|
||||||
|
s8 := []int{8, 9, 10}
|
||||||
|
s7 = append(s7, s8...)
|
||||||
|
fmt.Printf("s7 after append: %v\n", s7)
|
||||||
|
|
||||||
|
// 容量变化演示
|
||||||
|
fmt.Println("\n容量变化:")
|
||||||
|
s9 := make([]int, 0, 5)
|
||||||
|
for i := 1; i <= 10; i++ {
|
||||||
|
s9 = append(s9, i)
|
||||||
|
fmt.Printf("追加 %d: len=%d, cap=%d\n", i, len(s9), cap(s9))
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy
|
||||||
|
src := []int{1, 2, 3, 4, 5}
|
||||||
|
dst := make([]int, 3)
|
||||||
|
n := copy(dst, src)
|
||||||
|
fmt.Printf("\n复制了 %d 个元素,dst: %v\n", n, dst)
|
||||||
|
|
||||||
|
// 共享底层数组陷阱
|
||||||
|
s10 := []int{1, 2, 3, 4, 5}
|
||||||
|
s11 := s10[1:3]
|
||||||
|
s11[0] = 99
|
||||||
|
fmt.Printf("\n共享数组陷阱:\n")
|
||||||
|
fmt.Printf("s10: %v\n", s10)
|
||||||
|
fmt.Printf("s11: %v\n", s11)
|
||||||
|
|
||||||
|
// 释放内存的正确方式
|
||||||
|
fmt.Println("\n释放内存:")
|
||||||
|
data := make([]int, 1000)
|
||||||
|
small := append([]int(nil), data[:10]...)
|
||||||
|
fmt.Printf("small cap: %d (原 data cap: %d)\n", cap(small), cap(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.3 映射示例
|
||||||
|
func mapExamples() {
|
||||||
|
fmt.Println("\n=== 映射示例 ===")
|
||||||
|
|
||||||
|
// 创建映射
|
||||||
|
m1 := make(map[string]int)
|
||||||
|
m1["one"] = 1
|
||||||
|
m1["two"] = 2
|
||||||
|
|
||||||
|
m2 := map[string]int{
|
||||||
|
"one": 1,
|
||||||
|
"two": 2,
|
||||||
|
"three": 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("m1: %v\n", m1)
|
||||||
|
fmt.Printf("m2: %v\n", m2)
|
||||||
|
|
||||||
|
// 读取和检查存在
|
||||||
|
value, exists := m2["two"]
|
||||||
|
fmt.Printf("two 存在: %v, 值: %d\n", exists, value)
|
||||||
|
|
||||||
|
value, exists = m2["four"]
|
||||||
|
fmt.Printf("four 存在: %v, 值: %d\n", exists, value)
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
delete(m2, "one")
|
||||||
|
fmt.Printf("删除 one 后: %v\n", m2)
|
||||||
|
|
||||||
|
// 遍历(无序)
|
||||||
|
fmt.Println("\n遍历映射:")
|
||||||
|
for k, v := range m2 {
|
||||||
|
fmt.Printf("%s: %d\n", k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// nil 映射
|
||||||
|
var m3 map[string]int
|
||||||
|
fmt.Printf("\nnil 映射读取: %d\n", m3["key"])
|
||||||
|
// m3["key"] = 1 // panic!
|
||||||
|
|
||||||
|
// 嵌套映射
|
||||||
|
scores := map[string]map[string]int{
|
||||||
|
"Alice": {"math": 95, "english": 88},
|
||||||
|
"Bob": {"math": 92, "english": 90},
|
||||||
|
}
|
||||||
|
fmt.Printf("\nAlice 数学成绩: %d\n", scores["Alice"]["math"])
|
||||||
|
|
||||||
|
// 动态创建
|
||||||
|
if scores["Charlie"] == nil {
|
||||||
|
scores["Charlie"] = make(map[string]int)
|
||||||
|
}
|
||||||
|
scores["Charlie"]["math"] = 85
|
||||||
|
fmt.Printf("Charlie 数学成绩: %d\n", scores["Charlie"]["math"])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.4 结构体示例
|
||||||
|
func structExamples() {
|
||||||
|
fmt.Println("\n=== 结构体示例 ===")
|
||||||
|
|
||||||
|
// 定义结构体
|
||||||
|
type Person struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
Email string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
p1 := Person{Name: "Alice", Age: 25, Email: "alice@example.com"}
|
||||||
|
p2 := Person{"Bob", 30, "bob@example.com"}
|
||||||
|
p3 := Person{Name: "Charlie"}
|
||||||
|
p4 := &Person{Name: "David", Age: 28}
|
||||||
|
|
||||||
|
fmt.Printf("p1: %+v\n", p1)
|
||||||
|
fmt.Printf("p2: %+v\n", p2)
|
||||||
|
fmt.Printf("p3: %+v\n", p3)
|
||||||
|
fmt.Printf("p4: %+v\n", *p4)
|
||||||
|
|
||||||
|
// 方法
|
||||||
|
type Rectangle struct {
|
||||||
|
Width float64
|
||||||
|
Height float64
|
||||||
|
}
|
||||||
|
|
||||||
|
rect := Rectangle{Width: 10, Height: 5}
|
||||||
|
|
||||||
|
// 定义方法(在函数外定义)
|
||||||
|
area := rect.Width * rect.Height
|
||||||
|
fmt.Printf("矩形面积: %.2f\n", area)
|
||||||
|
|
||||||
|
// 嵌入
|
||||||
|
type Employee struct {
|
||||||
|
Person
|
||||||
|
ID int
|
||||||
|
Salary float64
|
||||||
|
}
|
||||||
|
|
||||||
|
e := Employee{
|
||||||
|
Person: Person{Name: "Eve", Age: 35},
|
||||||
|
ID: 1001,
|
||||||
|
Salary: 50000,
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("员工姓名: %s\n", e.Name) // 直接访问嵌入字段
|
||||||
|
fmt.Printf("员工 ID: %d\n", e.ID)
|
||||||
|
|
||||||
|
// 结构体标签
|
||||||
|
type User struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Email string `json:"email,omitempty"`
|
||||||
|
Password string `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{ID: 1, Name: "Alice", Email: "alice@example.com", Password: "secret"}
|
||||||
|
jsonData, _ := json.Marshal(user)
|
||||||
|
fmt.Printf("JSON: %s\n", jsonData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.5 学生管理系统
|
||||||
|
type Student struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Age int `json:"age"`
|
||||||
|
Score float64 `json:"score"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StudentManager struct {
|
||||||
|
students map[int]*Student
|
||||||
|
nextID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStudentManager() *StudentManager {
|
||||||
|
return &StudentManager{
|
||||||
|
students: make(map[int]*Student),
|
||||||
|
nextID: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StudentManager) AddStudent(name string, age int, score float64) int {
|
||||||
|
id := sm.nextID
|
||||||
|
sm.nextID++
|
||||||
|
sm.students[id] = &Student{ID: id, Name: name, Age: age, Score: score}
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StudentManager) GetStudent(id int) *Student {
|
||||||
|
return sm.students[id]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StudentManager) UpdateStudent(id int, name string, age int, score float64) bool {
|
||||||
|
if student, exists := sm.students[id]; exists {
|
||||||
|
student.Name = name
|
||||||
|
student.Age = age
|
||||||
|
student.Score = score
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StudentManager) DeleteStudent(id int) bool {
|
||||||
|
if _, exists := sm.students[id]; exists {
|
||||||
|
delete(sm.students, id)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StudentManager) GetAllStudents() []*Student {
|
||||||
|
students := make([]*Student, 0, len(sm.students))
|
||||||
|
for _, s := range sm.students {
|
||||||
|
students = append(students, s)
|
||||||
|
}
|
||||||
|
return students
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *StudentManager) SortByScore(descending bool) []*Student {
|
||||||
|
students := sm.GetAllStudents()
|
||||||
|
sort.Slice(students, func(i, j int) bool {
|
||||||
|
if descending {
|
||||||
|
return students[i].Score > students[j].Score
|
||||||
|
}
|
||||||
|
return students[i].Score < students[j].Score
|
||||||
|
})
|
||||||
|
return students
|
||||||
|
}
|
||||||
|
|
||||||
|
func studentManagerDemo() {
|
||||||
|
fmt.Println("\n=== 学生管理系统 ===")
|
||||||
|
|
||||||
|
manager := NewStudentManager()
|
||||||
|
|
||||||
|
id1 := manager.AddStudent("Alice", 20, 95.5)
|
||||||
|
id2 := manager.AddStudent("Bob", 22, 88.0)
|
||||||
|
id3 := manager.AddStudent("Charlie", 21, 92.5)
|
||||||
|
|
||||||
|
fmt.Printf("添加学生 ID: %d, %d, %d\n", id1, id2, id3)
|
||||||
|
|
||||||
|
manager.UpdateStudent(id1, "Alice", 21, 97.0)
|
||||||
|
fmt.Printf("更新后 Alice: %+v\n", manager.GetStudent(id1))
|
||||||
|
|
||||||
|
manager.DeleteStudent(id2)
|
||||||
|
fmt.Printf("删除后学生数量: %d\n", len(manager.GetAllStudents()))
|
||||||
|
|
||||||
|
sorted := manager.SortByScore(true)
|
||||||
|
fmt.Println("\n按分数降序排列:")
|
||||||
|
for _, s := range sorted {
|
||||||
|
fmt.Printf(" %s: %.1f\n", s.Name, s.Score)
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonStr, _ := json.MarshalIndent(manager.students, "", " ")
|
||||||
|
fmt.Println("\nJSON 导出:")
|
||||||
|
fmt.Println(string(jsonStr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.6 性能对比
|
||||||
|
func slicePerformance() {
|
||||||
|
fmt.Println("\n=== 切片性能对比 ===")
|
||||||
|
|
||||||
|
// 预分配容量
|
||||||
|
start := time.Now()
|
||||||
|
s1 := make([]int, 0, 10000)
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
s1 = append(s1, i)
|
||||||
|
}
|
||||||
|
fmt.Printf("预分配容量耗时: %v\n", time.Since(start))
|
||||||
|
|
||||||
|
// 不预分配容量
|
||||||
|
start = time.Now()
|
||||||
|
s2 := make([]int, 0)
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
s2 = append(s2, i)
|
||||||
|
}
|
||||||
|
fmt.Printf("不预分配容量耗时: %v\n", time.Since(start))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.7 并发安全映射
|
||||||
|
func concurrentMapDemo() {
|
||||||
|
fmt.Println("\n=== 并发安全映射 ===")
|
||||||
|
|
||||||
|
var m = make(map[string]int)
|
||||||
|
var mu sync.RWMutex
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
// 写操作
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(id int) {
|
||||||
|
defer wg.Done()
|
||||||
|
mu.Lock()
|
||||||
|
m[fmt.Sprintf("key%d", id%10)] = id
|
||||||
|
mu.Unlock()
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
fmt.Printf("最终映射大小: %d\n", len(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
arrayExamples()
|
||||||
|
sliceExamples()
|
||||||
|
mapExamples()
|
||||||
|
structExamples()
|
||||||
|
studentManagerDemo()
|
||||||
|
slicePerformance()
|
||||||
|
concurrentMapDemo()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user