├── README.md ├── go.mod ├── chapter01 ├── 04-float.go ├── 03-operator.go ├── 02-constant.go ├── 09-map.go ├── 01-variable.go ├── 10-pointer.go ├── 07-array.go ├── 08-slice.go ├── 05-string.go └── 06-transform.go ├── chapter04 ├── animal │ ├── pet.go │ ├── animal.go │ └── dog.go ├── 03-compose.go ├── interface │ ├── struct_assign.go │ ├── type_assertion.go │ └── interface_assign.go ├── 01-type.go ├── 02-class.go └── reflect │ ├── sample.go │ └── generic.go ├── chapter06 ├── hash │ └── md5.go ├── tree │ └── demo.go ├── sort │ ├── insert.go │ ├── bubble.go │ ├── select.go │ ├── quick.go │ └── merge.go ├── search │ ├── greater.go │ ├── less.go │ ├── first.go │ ├── last.go │ └── binary.go ├── string │ ├── bf.go │ ├── kmp.go │ └── trie.go ├── stack │ └── list.go ├── queue │ └── list.go ├── linkedlist │ └── single.go └── double.go ├── chapter03 ├── 02-params.go ├── 04-error.go ├── 05-anonymous_func.go ├── 03-generic.go ├── 06-closure.go ├── 01-func.go ├── 07-decorator.go ├── 10-pipeline.go ├── 08-recursive.go └── 09-map_reduce.go ├── chapter05 ├── panic │ ├── demo.go │ └── recover.go ├── defer │ └── demo.go └── error │ ├── os.go │ └── add.go └── .idea ├── go_tutorial.iml └── workspace.xml /README.md: -------------------------------------------------------------------------------- 1 | # golang-tutorial 2 | Go 入门教程源码合集 3 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module go-tutorial 2 | 3 | go 1.15 4 | -------------------------------------------------------------------------------- /chapter01/04-float.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | floatValue4 := 0.1 7 | floatValue5 := 0.7 8 | floatValue6 := floatValue4 + floatValue5 9 | 10 | fmt.Println(floatValue6) 11 | } 12 | -------------------------------------------------------------------------------- /chapter04/animal/pet.go: -------------------------------------------------------------------------------- 1 | package animal 2 | 3 | type Pet struct { 4 | name string 5 | } 6 | 7 | func NewPet(name string) Pet { 8 | return Pet{name: name} 9 | } 10 | 11 | func (p Pet) GetName() string { 12 | return p.name 13 | } 14 | -------------------------------------------------------------------------------- /chapter06/hash/md5.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/md5" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | data := []byte("Hello, World!") 10 | hash := md5.Sum(data) 11 | fmt.Printf("原始值: %s\n", data) 12 | fmt.Printf("MD5值: %x\n", hash) 13 | } 14 | -------------------------------------------------------------------------------- /chapter03/02-params.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func add(a, b *int) int { 6 | *a *= 2 7 | *b *= 3 8 | return *a + *b 9 | } 10 | 11 | func main() { 12 | x, y := 1, 2 13 | z := add(&x, &y) 14 | fmt.Printf("add(%d, %d) = %d\n", x, y, z) 15 | } 16 | -------------------------------------------------------------------------------- /chapter05/panic/demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | defer func() { 7 | fmt.Println("代码清理逻辑") 8 | }() 9 | 10 | var i = 1 11 | var j = 0 12 | if j == 0 { 13 | panic("除数不能为0!") 14 | } 15 | k := i / j 16 | fmt.Printf("%d / %d = %d\n", i, j, k) 17 | } -------------------------------------------------------------------------------- /chapter04/03-compose.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | . "go-tutorial/chapter04/animal" 6 | ) 7 | 8 | func main() { 9 | animal := NewAnimal("中华田园犬") 10 | pet := NewPet("宠物狗") 11 | dog := NewDog(&animal, pet) 12 | 13 | fmt.Println(dog.GetName()) 14 | fmt.Println(dog.Call()) 15 | fmt.Println(dog.FavorFood()) 16 | } -------------------------------------------------------------------------------- /chapter01/03-operator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var intValueBit uint8 7 | intValueBit = 255 8 | intValueBit = ^intValueBit // 按位取反 9 | fmt.Println(intValueBit) // 0 10 | intValueBit = 1 11 | intValueBit = intValueBit << 3 // 左移 3 位,相当于乘以 2^3 = 8 12 | fmt.Println(intValueBit) // 8 13 | } 14 | -------------------------------------------------------------------------------- /.idea/go_tutorial.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /chapter06/tree/demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Node struct { 4 | Value string 5 | Left *Node 6 | Right *Node 7 | } 8 | 9 | func NewNode(data string) *Node { 10 | return &Node{data, nil, nil} 11 | } 12 | 13 | func main() { 14 | root := NewNode("A") 15 | left := NewNode("B") 16 | right := NewNode("C") 17 | root.Left = left 18 | root.Right = right 19 | } -------------------------------------------------------------------------------- /chapter05/defer/demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func printError() { 6 | fmt.Println("兜底执行") 7 | } 8 | 9 | func main() { 10 | defer printError() 11 | defer func() { 12 | fmt.Println("除数不能是0!") 13 | }() 14 | 15 | var i = 1 16 | var j = 0 17 | var k = i / j 18 | 19 | fmt.Printf("%d / %d = %d\n", i, j, k) 20 | } -------------------------------------------------------------------------------- /chapter01/02-constant.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const ( // iota 被重置为 0 6 | c0 = iota // c0 = 0 7 | c1 // c1 = 1 8 | c2 // c2 = 2 9 | ) 10 | 11 | const ( 12 | u = iota * 2 // u = 0 13 | v // v = 2 14 | w // w = 4 15 | ) 16 | 17 | const x = iota // x = 0 18 | const y = iota // y = 0 19 | 20 | func main() { 21 | fmt.Printf("x:%v\n", x) 22 | fmt.Printf("y:%v\n", y) 23 | } -------------------------------------------------------------------------------- /chapter01/09-map.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var testMap map[string]int 7 | testMap = map[string]int{ 8 | "one": 1, 9 | "two": 2, 10 | "three": 3, 11 | } 12 | 13 | k := "two" 14 | v, ok := testMap[k] 15 | if ok { 16 | fmt.Printf("The element of key %q: %d\n", k, v) 17 | } else { 18 | fmt.Println("Not found!") 19 | } 20 | 21 | fmt.Println(testMap) 22 | } 23 | -------------------------------------------------------------------------------- /chapter04/animal/animal.go: -------------------------------------------------------------------------------- 1 | package animal 2 | 3 | type Animal struct { 4 | name string 5 | } 6 | 7 | func NewAnimal(name string) Animal { 8 | return Animal{name: name} 9 | } 10 | 11 | func (a Animal) Call() string { 12 | return "动物的叫声..." 13 | } 14 | 15 | func (a Animal) FavorFood() string { 16 | return "爱吃的食物..." 17 | } 18 | 19 | func (a Animal) GetName() string { 20 | return a.name 21 | } -------------------------------------------------------------------------------- /chapter05/panic/recover.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func divide() { 8 | defer func() { 9 | if err := recover(); err != nil { 10 | fmt.Printf("捕获到运行时 panic: %v\n", err) 11 | } 12 | }() 13 | 14 | var i = 1 15 | var j = 1 16 | k := i / j 17 | fmt.Printf("%d / %d = %d\n", i, j, k) 18 | } 19 | 20 | func main() { 21 | divide() 22 | fmt.Println("divide 方法调用完毕,回到 main 函数") 23 | } -------------------------------------------------------------------------------- /chapter04/animal/dog.go: -------------------------------------------------------------------------------- 1 | package animal 2 | 3 | type Dog struct { 4 | animal *Animal 5 | pet Pet 6 | } 7 | 8 | func NewDog(animal *Animal, pet Pet) Dog { 9 | return Dog{animal: animal, pet: pet} 10 | } 11 | 12 | func (d Dog) FavorFood() string { 13 | return d.animal.FavorFood() + "骨头" 14 | } 15 | 16 | func (d Dog) Call() string { 17 | return d.animal.Call() + "汪汪汪" 18 | } 19 | 20 | func (d Dog) GetName() string { 21 | return d.pet.GetName() 22 | } -------------------------------------------------------------------------------- /chapter03/04-error.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | func add2(a, b *int) (int, error) { 9 | if (*a < 0 || *b < 0) { 10 | err := errors.New("只支持非负整数相加") 11 | return 0, err 12 | } 13 | *a *= 2 14 | *b *= 3 15 | return *a + *b, nil 16 | } 17 | 18 | func main() { 19 | x, y := -1, 2 20 | z, err := add2(&x, &y) 21 | if err != nil { 22 | fmt.Println(err.Error()) 23 | return 24 | } 25 | fmt.Printf("add(%d, %d) = %d\n", x, y, z) 26 | } 27 | 28 | -------------------------------------------------------------------------------- /chapter04/interface/struct_assign.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Integer int 6 | 7 | func (a *Integer) Add(b Integer) { 8 | *a = (*a) + b 9 | } 10 | 11 | func (a Integer) Multiply(b Integer) Integer { 12 | return a * b 13 | } 14 | 15 | type Math interface { 16 | Add(i Integer) 17 | Multiply(i Integer) Integer 18 | } 19 | 20 | func main() { 21 | var a Integer = 1 22 | var m Math = &a 23 | m.Add(2) 24 | fmt.Printf("1 + 2 = %d\n", a) 25 | } 26 | -------------------------------------------------------------------------------- /chapter03/05-anonymous_func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // 将函数作为返回值类型 8 | func deferAdd(a, b int) func() int { 9 | return func() int { 10 | return a + b 11 | } 12 | } 13 | 14 | func main() { 15 | add := func(a, b int) int { 16 | return a + b 17 | } 18 | 19 | // 将匿名函数作为参数 20 | func(call func(int, int) int) { 21 | fmt.Println(call(1, 2)) 22 | }(add) 23 | 24 | // 此时返回的是匿名函数 25 | addFunc := deferAdd(1, 2) 26 | // 这里才会真正执行加法操作 27 | fmt.Println(addFunc()) 28 | } 29 | -------------------------------------------------------------------------------- /chapter06/sort/insert.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func insertionSort(nums []int) []int { 6 | if len(nums) <= 1 { 7 | return nums 8 | } 9 | 10 | for i := 0; i < len(nums); i++ { 11 | value := nums[i] 12 | j := i - 1 13 | for ; j >= 0; j-- { 14 | if nums[j] > value { 15 | nums[j+1] = nums[j] 16 | } else { 17 | break 18 | } 19 | } 20 | nums[j+1] = value 21 | } 22 | 23 | return nums 24 | } 25 | 26 | func main() { 27 | nums := []int{4, 5, 6, 7, 8, 3, 2, 1} 28 | nums = insertionSort(nums) 29 | fmt.Println(nums) 30 | } -------------------------------------------------------------------------------- /chapter03/03-generic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func myPrintf(args ...interface{}) { 9 | for _, arg := range args { 10 | switch reflect.TypeOf(arg).Kind() { 11 | case reflect.Int: 12 | fmt.Println(arg, "is an int value.") 13 | case reflect.String: 14 | fmt.Printf("\"%s\" is a string value.\n", arg) 15 | case reflect.Array: 16 | fmt.Println(arg, "is an array type.") 17 | default: 18 | fmt.Println(arg, "is an unknown type.") 19 | } 20 | } 21 | } 22 | 23 | func main() { 24 | myPrintf(1, "1", [1]int{1}, true) 25 | } 26 | -------------------------------------------------------------------------------- /chapter06/sort/bubble.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func bubbleSort(nums []int) []int { 6 | if len(nums) <= 1 { 7 | return nums 8 | } 9 | 10 | // 冒泡排序核心实现代码 11 | for i := 0; i < len(nums); i++ { 12 | flag := false 13 | for j := 0; j < len(nums) - i - 1; j++ { 14 | if nums[j] > nums[j+1] { 15 | nums[j], nums[j+1] = nums[j+1], nums[j] 16 | flag = true 17 | } 18 | } 19 | if !flag { 20 | break 21 | } 22 | } 23 | 24 | return nums 25 | } 26 | 27 | func main() { 28 | nums := []int{4, 5, 6, 7, 8, 3, 2, 1} 29 | nums = bubbleSort(nums) 30 | fmt.Println(nums) 31 | } 32 | -------------------------------------------------------------------------------- /chapter04/01-type.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Integer int 6 | 7 | type Math interface { 8 | Add(i Integer) Integer 9 | Multiply(i Integer) Integer 10 | } 11 | 12 | func (a Integer) Equal(b Integer) bool { 13 | return a == b 14 | } 15 | 16 | func (a Integer) Add(b Integer) Integer { 17 | return a + b 18 | } 19 | 20 | func (a Integer) Multiply(b Integer) Integer { 21 | return a * b 22 | } 23 | 24 | func main() { 25 | var x Integer 26 | var y Integer 27 | x, y = 10, 15 28 | fmt.Println(x.Equal(y)) 29 | 30 | var a Integer = 1 31 | var m Math = &a 32 | fmt.Println(m.Add(1)) 33 | } 34 | -------------------------------------------------------------------------------- /chapter03/06-closure.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func main() { 8 | /*var j int = 1 9 | 10 | f := func() { 11 | var i int = 1 12 | fmt.Printf("i, j: %d, %d\n", i, j) 13 | } 14 | 15 | f() 16 | j += 2 17 | f()*/ 18 | 19 | // 普通的加法操作 20 | add1 := func(a, b int) int { 21 | return a + b 22 | } 23 | 24 | // 定义多种加法算法 25 | base := 10 26 | add2 := func(a, b int) int { 27 | return a * base + b 28 | } 29 | 30 | handleAdd(1, 2, add1) 31 | handleAdd(1, 2, add2) 32 | } 33 | 34 | // 将匿名函数作为参数 35 | func handleAdd(a, b int, call func(int, int) int) { 36 | fmt.Println(call(a, b)) 37 | } 38 | 39 | -------------------------------------------------------------------------------- /chapter05/error/os.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | ) 8 | 9 | func main() { 10 | // 获取指定路径文件信息,对应类型是 FileInfo 11 | // 如果文件不存在,则返回 PathError 类型错误 12 | fi, err := os.Stat("add.go") 13 | if err != nil { 14 | switch err.(type) { 15 | case *os.PathError: 16 | fmt.Println(err) 17 | case *os.LinkError: 18 | fmt.Println(err) 19 | case *os.SyscallError: 20 | fmt.Println(err) 21 | case *exec.Error: 22 | fmt.Println(err) 23 | } 24 | } else { 25 | fmt.Print(fi) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /chapter06/sort/select.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func selectionSort(nums []int) { 6 | if len(nums) <= 1 { 7 | return 8 | } 9 | // 已排序区间初始化为空,未排序区间初始化待排序切片 10 | for i := 0; i < len(nums); i++ { 11 | // 未排序区间最小值初始化为第一个元素 12 | min := i 13 | // 从未排序区间第二个元素开始遍历,直到找到最小值 14 | for j := i + 1; j < len(nums); j++ { 15 | if nums[j] < nums[min] { 16 | min = j 17 | } 18 | } 19 | // 将最小值与未排序区间第一个元素互换位置(等价于放到已排序区间最后一个位置) 20 | if min != i { 21 | nums[i],nums[min] = nums[min], nums[i] 22 | } 23 | } 24 | } 25 | 26 | func main() { 27 | nums := []int{4, 5, 6, 7, 8, 3, 2, 1} 28 | selectionSort(nums) 29 | fmt.Println(nums) 30 | } 31 | -------------------------------------------------------------------------------- /chapter04/interface/type_assertion.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | . "go-tutorial/chapter04/animal" 6 | "reflect" 7 | ) 8 | 9 | /* 10 | type IAnimal interface { 11 | GetName() string 12 | Call() string 13 | FavorFood() string 14 | }*/ 15 | 16 | func main() { 17 | var animal = NewAnimal("中华田园犬") 18 | var pet = NewPet("泰迪") 19 | var any interface{} = NewDog(&animal, pet) 20 | if dog, ok := any.(Dog); ok { 21 | fmt.Println(dog.GetName()) 22 | fmt.Println(dog.Call()) 23 | fmt.Println(dog.FavorFood()) 24 | fmt.Println(reflect.TypeOf(dog)) 25 | } 26 | fmt.Println(reflect.TypeOf(any)) 27 | } 28 | -------------------------------------------------------------------------------- /chapter04/02-class.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Student struct { 6 | id uint 7 | name string 8 | male bool 9 | score float64 10 | } 11 | 12 | func NewStudent(id uint, name string, score float64) *Student { 13 | return &Student{id: id, name:name, score:score} 14 | } 15 | 16 | func (s Student) GetName() string { 17 | return s.name 18 | } 19 | 20 | func (s *Student) SetName(name string) { 21 | s.name = name 22 | } 23 | 24 | func (s Student) String() string { 25 | return fmt.Sprintf("{id: %d, name: %s, male: %t, score: %f}", 26 | s.id, s.name, s.male, s.score) 27 | } 28 | 29 | func main() { 30 | student := NewStudent(1, "学院君", 100) 31 | fmt.Println(student) 32 | } 33 | -------------------------------------------------------------------------------- /chapter01/01-variable.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var v1 int // 整型 7 | var v2 string // 字符串 8 | var v3 bool // 布尔型 9 | var v4 [10]int // 数组,数组元素类型为整型 10 | var v5 struct { // 结构体,成员变量 f 的类型为64位浮点型 11 | f float64 12 | } 13 | var v6 *int // 指针,指向整型 14 | var v7 map[string]int // map(字典),key为字符串类型,value为整型 15 | var v8 func(a int) int // 函数,参数类型为整型,返回值类型为整型 16 | 17 | // 打印上述变量值 18 | fmt.Printf("v1: %v\n", v1) 19 | fmt.Printf("v2: %v\n", v2) 20 | fmt.Printf("v3: %v\n", v3) 21 | fmt.Printf("v4: %v\n", v4) 22 | fmt.Printf("v5: %v\n", v5) 23 | fmt.Printf("v6: %v\n", v6) 24 | fmt.Printf("v7: %v\n", v7) 25 | fmt.Printf("v8: %v\n", v8) 26 | } 27 | -------------------------------------------------------------------------------- /chapter01/10-pointer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | a := 100 10 | var ptr *int // 声明指针类型 11 | ptr = &a // 初始化指针类型值为变量 a 12 | fmt.Println(ptr) 13 | fmt.Println(*ptr) 14 | 15 | // 通过指针传值 16 | b := 200 17 | swap(&a, &b) 18 | fmt.Println(a, b) 19 | 20 | // 指针类型转化 21 | i := 10 22 | var p *int = &i 23 | 24 | var fp *float32 = (*float32)(unsafe.Pointer(p)) 25 | *fp = *fp * 10 26 | fmt.Println(i) // 100 27 | 28 | // 指针运算 29 | arr := []int{1, 2, 3} 30 | ap := &arr 31 | 32 | sp := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(ap)) + unsafe.Sizeof(arr[0]))) 33 | *sp += 3 34 | fmt.Println(arr) 35 | } 36 | 37 | func swap(a, b *int) { 38 | *a, *b = *b, *a 39 | fmt.Println(*a, *b) 40 | } 41 | -------------------------------------------------------------------------------- /chapter03/01-func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | p1 := new(int) // 返回 int 类型指针,相当于 var p1 *int 5 | p2 := new(string) // 返回 string 类型指针 6 | p3 := new([3]int) // 返回数组类型指针,数组长度是 3 7 | 8 | type Student struct { 9 | id int 10 | name string 11 | grade string 12 | } 13 | p4 := new(Student) // 返回对象类型指针 14 | 15 | println("p1: ", p1) 16 | println("p2: ", p2) 17 | println("p3: ", p3) 18 | println("p4: ", p4) 19 | 20 | s1 := make([]int, 3) // 返回初始化后的切片类型值,即 []int{0, 0, 0} 21 | m1 := make(map[string]int, 2) // 返回初始化的字典类型值,即散列化的 map 结构 22 | 23 | println(len(s1)) // 3 24 | for i, v := range s1 { 25 | println(i, v) 26 | } 27 | 28 | println(len(m1)) // 0 29 | m1["test"] = 100 30 | for k, v := range m1 { 31 | println(k, v) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /chapter05/error/add.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | "strconv" 9 | ) 10 | 11 | func add(a, b int) (c int, err error) { 12 | if a < 0 || b < 0 { 13 | err = errors.New("只支持非负整数相加") 14 | return 15 | } 16 | a *= 2 17 | b *= 3 18 | c = a + b 19 | return 20 | } 21 | 22 | func main() { 23 | if len(os.Args) != 3 { 24 | fmt.Printf("Usage: %s num1 num2\n", filepath.Base(os.Args[0])) 25 | return 26 | } 27 | x, _ := strconv.Atoi(os.Args[1]) 28 | y, _ := strconv.Atoi(os.Args[2]) 29 | z, err := add(x, y) 30 | if err != nil { 31 | fmt.Println(err) 32 | } else { 33 | fmt.Printf("add(%d, %d) = %d\n", x, y, z) 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /chapter06/search/greater.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // 二分查找变形版本3:查找第一个大于等于给定值的元素 6 | func binarySearchV3(nums []int, num, low, high int) int { 7 | if low > high { 8 | return -1 9 | } 10 | 11 | mid := (low + high) / 2 12 | if num <= nums[mid] { 13 | // 判断条件变更,找到第一个大于等于给定值的元素 14 | // 最左侧元素值,或者当前 mid 位置前一个元素值小于给定值 15 | if mid == 0 || nums[mid-1] < num { 16 | return mid 17 | } else { 18 | return binarySearchV3(nums, num, low, mid-1) 19 | } 20 | } else { 21 | return binarySearchV3(nums, num, mid+1, high) 22 | } 23 | } 24 | 25 | func main() { 26 | nums := []int{1, 2, 3, 3, 4, 5, 6} 27 | num := 3 28 | index := binarySearchV3(nums, num, 0, len(nums) - 1) 29 | if index != -1 { 30 | fmt.Printf("Find first num greater or equal than %d at index %d\n", num, index) 31 | } else { 32 | fmt.Printf("Num %d not exists in nums\n", num) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | -------------------------------------------------------------------------------- /chapter06/search/less.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // 二分查找变形版本4:查找最后一个小于等于给定值的元素 6 | func binarySearchV4(nums []int, num, low, high int) int { 7 | if low > high { 8 | return -1 9 | } 10 | 11 | mid := (low + high) / 2 12 | if num >= nums[mid] { 13 | // 判断条件变更,找到最后一个小于等于给定值的元素 14 | // 最右侧元素值,或者当前 mid 位置后一个元素值大于给定值 15 | if mid == len(nums) - 1 || nums[mid + 1] > num { 16 | return mid 17 | } else { 18 | return binarySearchV4(nums, num, mid + 1, high) 19 | } 20 | } else { 21 | return binarySearchV4(nums, num, low, mid - 1) 22 | } 23 | } 24 | 25 | func main() { 26 | nums:= []int{1, 2, 3, 3, 4, 5, 6} 27 | num := 3 28 | index := binarySearchV4(nums, num, 0, len(nums) - 1) 29 | if index != -1 { 30 | fmt.Printf("Find last num less or equal than %d at index %d\n", num, index) 31 | } else { 32 | fmt.Printf("Num %d not exists in nums\n", num) 33 | } 34 | } -------------------------------------------------------------------------------- /chapter01/07-array.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // 数组的初始化 7 | a1 := [5]uint8{1, 2} 8 | fmt.Println(a1) 9 | 10 | a2 := [3]string{"hello", "world"} 11 | fmt.Println(a2) 12 | 13 | // 遍历数组 14 | arr := [5]int{1,2,3,4,5} 15 | /*for i := 0; i < len(arr); i++ { 16 | fmt.Println("Element", i, "of arr is", arr[i]) 17 | }*/ 18 | for i, v := range arr { 19 | fmt.Println("Element", i, "of arr is", v) 20 | } 21 | 22 | // 通过二维数组打印九九乘法表 23 | var multi [9][9]string 24 | for j := 0; j < 9; j++ { 25 | for i := 0; i < 9; i++ { 26 | n1 := i + 1 27 | n2 := j + 1 28 | if n1 < n2 { // 摒除重复的记录 29 | continue 30 | } 31 | multi[i][j] = fmt.Sprintf("%dx%d=%d", n2, n1, n1 * n2) 32 | } 33 | } 34 | 35 | // 打印九九乘法表 36 | for _, v1 := range multi { 37 | for _, v2 := range v1 { 38 | fmt.Printf("%-8s", v2) // 位宽为8,左对齐 39 | } 40 | fmt.Println() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /chapter06/search/first.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // 二分查找变形版本1:查找第一个值等于给定值的元素 8 | func binarySearchV1(nums []int, num, low, high int) int { 9 | if low > high { 10 | return -1 11 | } 12 | 13 | mid := (low + high) / 2 14 | if num < nums[mid] { 15 | return binarySearchV1(nums, num, low, mid - 1) 16 | } else if num > nums[mid] { 17 | return binarySearchV1(nums, num, mid + 1, high) 18 | } else { 19 | // 除了需要判断第一个与 num 相等的元素索引外,其他和普通二分查找逻辑一致 20 | if mid == 0 || nums[mid-1] != num { 21 | return mid 22 | } else { 23 | return binarySearchV1(nums, num, low, mid - 1) 24 | } 25 | } 26 | } 27 | 28 | func main() { 29 | nums := []int{1, 2, 3, 3, 4, 5, 6} 30 | num := 3 31 | index := binarySearchV1(nums, num, 0, len(nums) - 1) 32 | if index != -1 { 33 | fmt.Printf("Find num %d first at index %d\n", num, index) 34 | } else { 35 | fmt.Printf("Num %d not exists in nums\n", num) 36 | } 37 | } -------------------------------------------------------------------------------- /chapter01/08-slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // 基本使用 7 | months := [...]string{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} 8 | 9 | q2 := months[3:6] // 第二季度 10 | summer := months[5:8] // 夏季 11 | 12 | fmt.Println(q2) 13 | fmt.Println(summer) 14 | 15 | // 切片复制 16 | //slice1 := []int{1, 2, 3, 4, 5} 17 | //slice2 := []int{5, 4, 3} 18 | 19 | // 复制 slice1 到 slice 2 20 | //copy(slice2, slice1) // 只会复制 slice1 的前 3 个元素到 slice2 中 21 | //fmt.Println(slice2) 22 | // 复制 slice2 到 slice 1 23 | //copy(slice1, slice2) // 只会复制 slice2 的 3 个元素到 slice1 的前 3 个位置 24 | //fmt.Println(slice1) 25 | 26 | // 数据共享 27 | slice1 := make([]int, 4, 5) 28 | slice2 := slice1[1:3] 29 | slice1 = append(slice1, 0) 30 | slice1[1] = 2 31 | slice2[1] = 6 32 | 33 | fmt.Println("slice1:", slice1) 34 | fmt.Println("slice2:", slice2) 35 | } 36 | -------------------------------------------------------------------------------- /chapter06/search/last.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // 二分查找变形版本2:查找最后一个值等于给定值的元素 6 | func binarySearchV2(nums []int, num, low, high int) int { 7 | if low > high { 8 | return -1 9 | } 10 | 11 | mid := (low + high) / 2 12 | if num < nums[mid] { 13 | return binarySearchV2(nums, num, low, mid - 1) 14 | } else if num > nums[mid] { 15 | return binarySearchV2(nums, num, mid + 1, high) 16 | } else { 17 | // 除了需要判断最后一个与 num 相等的元素索引外,其他和普通二分查找逻辑一致 18 | if mid == len(nums) - 1 || nums[mid + 1] != num { 19 | return mid 20 | } else { 21 | return binarySearchV2(nums, num, mid + 1, high) 22 | } 23 | } 24 | } 25 | 26 | func main() { 27 | nums := []int{1, 2, 3, 3, 4, 5, 6} 28 | num := 3 29 | index := binarySearchV2(nums, num, 0, len(nums) - 1) 30 | if index != -1 { 31 | fmt.Printf("Find num %d last at index %d\n", num, index) 32 | } else { 33 | fmt.Printf("Num %d not exists in nums\n", num) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /chapter01/05-string.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | func main() { 9 | // 转义字符 10 | results := "Search results for \"Golang\":\n" + 11 | "- Go\n" + 12 | "- Golang\n" + 13 | "- Golang Programming\n" 14 | fmt.Printf("%s", results) 15 | 16 | // 字符串切片 17 | str := "hello, world" 18 | str1 := str[:5] // 获取索引5(不含)之前的子串 19 | str2 := str[7:] // 获取索引7(含)之后的子串 20 | str3 := str[0:5] // 获取从索引0(含)到索引5(不含)之间的子串 21 | fmt.Println("str1:", str1) 22 | fmt.Println("str2:", str2) 23 | fmt.Println("str3:", str3) 24 | 25 | str4 := str[:] 26 | fmt.Println("str4:", str4) 27 | 28 | // 字符编码 29 | msg := "Hello, 世界" 30 | n := len(msg) // 获取到的是 msg 的字节长度 31 | for i := 0; i < n; i++ { 32 | ch := msg[i] // 依据下标取字符串中的字符,ch 类型为 byte 33 | fmt.Println(i, ch, reflect.TypeOf(ch)) 34 | } 35 | 36 | for i, ch := range msg { 37 | fmt.Println(i, string(ch), reflect.TypeOf(ch)) // 通过 range 遍历,ch 类型是 rune 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /chapter04/interface/interface_assign.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | type Number1 interface { 9 | Equal(i int) bool 10 | LessThan(i int) bool 11 | MoreThan(i int) bool 12 | } 13 | 14 | type Number2 interface { 15 | Equal(i int) bool 16 | MoreThan(i int) bool 17 | LessThan(i int) bool 18 | Add(i int) 19 | } 20 | 21 | type Number int 22 | 23 | func (n Number) Equal(i int) bool { 24 | return int(n) == i 25 | } 26 | 27 | func (n Number) LessThan(i int) bool { 28 | return int(n) < i 29 | } 30 | 31 | func (n Number) MoreThan(i int) bool { 32 | return int(n) > i 33 | } 34 | 35 | func (n *Number) Add(i int) { 36 | *n = *n + Number(i) 37 | } 38 | 39 | func main() { 40 | var num1 Number = 1 41 | var num2 Number2 = &num1 42 | if num3, ok := num2.(Number1); ok { 43 | fmt.Println(num3.Equal(1)) 44 | fmt.Println(reflect.TypeOf(num3)) 45 | } 46 | } -------------------------------------------------------------------------------- /chapter06/search/binary.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | // 二分查找实现代码 9 | func binarySearch(nums []int, num int, low int, high int) int { 10 | // 递归终止条件 11 | if low > high { 12 | return -1 13 | } 14 | 15 | // 通过中间元素进行二分查找 16 | mid := (low + high) / 2 17 | // 递归查找 18 | if num > nums[mid] { 19 | // 如果待查找数据大于中间元素,则在右区间查找 20 | return binarySearch(nums, num, mid + 1, high) 21 | } else if num < nums[mid] { 22 | // 如果待查找数据小于中间元素,则在左区间查找 23 | return binarySearch(nums, num, low, mid - 1) 24 | } else { 25 | // 找到了,返回索引值 26 | return mid 27 | } 28 | } 29 | 30 | func main() { 31 | nums := []int{4, 6, 5, 3, 1, 8, 2, 7} 32 | sort.Ints(nums) // 先对待排序数据序列进行排序 33 | fmt.Printf("Sorted nums: %v\n", nums) 34 | num := 5 35 | index := binarySearch(nums, num, 0, len(nums)-1) 36 | if index != -1 { 37 | fmt.Printf("Find num %d at index %d\n", num, index) 38 | } else { 39 | fmt.Printf("Num %d not exists in nums\n", num) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /chapter03/07-decorator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | // 为函数类型设置别名提高代码可读性 9 | type MultiPlyFunc func(int, int) int 10 | 11 | // 乘法运算函数1(算术运算) 12 | func multiply1(a, b int) int { 13 | return a * b 14 | } 15 | 16 | // 乘法运算函数2(位运算) 17 | func multiply2(a, b int) int { 18 | return a << b 19 | } 20 | 21 | // 通过高阶函数在不侵入原有函数实现的前提下计算乘法函数执行时间 22 | func execTime(f MultiPlyFunc) MultiPlyFunc { 23 | return func(a, b int) int { 24 | start := time.Now() // 起始时间 25 | c := f(a, b) // 执行乘法运算函数 26 | end := time.Since(start) // 函数执行完毕耗时 27 | fmt.Printf("--- 执行耗时: %v ---\n", end) 28 | return c // 返回计算结果 29 | } 30 | } 31 | 32 | func main() { 33 | a := 2 34 | b := 8 35 | fmt.Println("算术运算:") 36 | decorator1 := execTime(multiply1) 37 | c := decorator1(a, b) 38 | fmt.Printf("%d x %d = %d\n", a, b, c) 39 | 40 | fmt.Println("位运算:") 41 | decorator2 := execTime(multiply2) 42 | a = 1 43 | b = 4 44 | c = decorator2(a, b) 45 | fmt.Printf("%d << %d = %d\n", a, b, c) 46 | } 47 | -------------------------------------------------------------------------------- /chapter06/sort/quick.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // 快速排序入口函数 6 | func quickSort(nums []int, p int, r int) { 7 | // 递归终止条件 8 | if p >= r { 9 | return 10 | } 11 | // 获取分区位置 12 | q := partition(nums, p, r) 13 | // 递归分区(排序是在定位 pivot 的过程中实现的) 14 | quickSort(nums, p, q - 1) 15 | quickSort(nums, q + 1, r) 16 | } 17 | 18 | // 定位 pivot 19 | func partition(nums []int, p int, r int) int { 20 | // 以当前数据序列最后一个元素作为初始 pivot 21 | pivot := nums[r] 22 | // 初始化 i、j 下标 23 | i := p 24 | // 后移 j 下标的遍历过程 25 | for j := p; j < r; j++ { 26 | // 将比 pivot 小的数丢到 [p...i-1] 中,剩下的 [i...j] 区间都是比 pivot 大的 27 | if nums[j] < pivot { 28 | // 互换 i、j 下标对应数据 29 | nums[i], nums[j] = nums[j], nums[i] 30 | // 将 i 下标后移一位 31 | i++ 32 | } 33 | } 34 | 35 | // 最后将 pivot 与 i 下标对应数据值互换 36 | // 这样一来,pivot 就位于当前数据序列中间,i 也就是 pivot 值对应的下标 37 | nums[i], nums[r] = pivot, nums[i] 38 | // 返回 i 作为 pivot 分区位置 39 | return i 40 | } 41 | 42 | func main() { 43 | nums := []int{4, 5, 6, 7, 8, 3, 2, 1} 44 | quickSort(nums, 0, len(nums) - 1) 45 | fmt.Println(nums) 46 | } 47 | -------------------------------------------------------------------------------- /chapter06/string/bf.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // BF 算法实现函数 6 | func bfSearch(s, p string) int { 7 | begin := 0 8 | i, j := 0, 0 9 | n, m := len(s), len(p) // 主串、子串长度 10 | for i = 0; i < n; begin++ { 11 | // 通过 BF 算法暴力匹配子串和主串 12 | for j = 0;j < m; j++ { 13 | if i < n && s[i] == p[j] { 14 | // 如果子串和主串对应字符相等,逐一往后匹配 15 | i++ 16 | } else { 17 | // 否则退出当前循环,从主串下一个字符继续开始匹配 18 | break 19 | } 20 | } 21 | if j == m { 22 | // 子串遍历完,表面已经找到,返回对应下标 23 | return i - j 24 | } 25 | // 从下一个位置继续开始匹配 26 | i = begin 27 | i++ 28 | } 29 | return -1 30 | } 31 | 32 | // 基于 BF 算法实现字符串查找函数 33 | func strStrV1(haystack, needle string) int { 34 | // 子串长度=0 35 | if len(needle) == 0 { 36 | return 0 37 | } 38 | //主串长度=0,或者主串长度小于子串长度 39 | if len(haystack) == 0 || len(haystack) < len(needle) { 40 | return -1 41 | } 42 | // 调用 BF 算法查找子串 43 | return bfSearch(haystack, needle) 44 | } 45 | 46 | func main() { 47 | s := "Hello, 学院君!" 48 | p := "学院君" 49 | pos := strStrV1(s, p) 50 | fmt.Printf("Find \"%s\" at %d in \"%s\"\n", p, pos, s) 51 | } -------------------------------------------------------------------------------- /chapter06/sort/merge.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func mergeSort(nums []int) []int { 8 | if len(nums) <= 1 { 9 | return nums 10 | } 11 | 12 | // 获取分区位置 13 | p := len(nums) / 2 14 | // 通过递归分区 15 | left := mergeSort(nums[0:p]) 16 | right := mergeSort(nums[p:]) 17 | // 排序后合并 18 | return merge(left, right) 19 | } 20 | 21 | func merge(left []int, right []int) []int { 22 | i, j := 0, 0 23 | m, n := len(left), len(right) 24 | // 用于存放结果集 25 | var result []int 26 | for { 27 | // 任何一个区间遍历完,则退出 28 | if i >= m || j >= n { 29 | break 30 | } 31 | // 对所有区间数据进行排序 32 | if left[i] <= right[j] { 33 | result = append(result, left[i]) 34 | i++ 35 | } else { 36 | result = append(result, right[j]) 37 | j++ 38 | } 39 | } 40 | 41 | // 如果左侧区间还没有遍历完,将剩余数据放到结果集 42 | if i != m { 43 | for ; i < m; i++ { 44 | result = append(result, left[i]) 45 | } 46 | } 47 | 48 | // 如果右侧区间还没有遍历完,将剩余数据放到结果集 49 | if j != n { 50 | for ; j < n; j++ { 51 | result = append(result, right[j]) 52 | } 53 | } 54 | 55 | // 返回排序后的结果集 56 | return result 57 | } 58 | 59 | func main() { 60 | nums := []int{4, 5, 6, 7, 8, 3, 2, 1} 61 | sortedNums := mergeSort(nums) 62 | fmt.Println(sortedNums) 63 | } 64 | -------------------------------------------------------------------------------- /chapter04/reflect/sample.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | . "go-tutorial/chapter04/animal" 6 | "reflect" 7 | ) 8 | 9 | func main() { 10 | animal := NewAnimal("中华田园犬") 11 | pet := NewPet("泰迪") 12 | dog := NewDog(&animal, pet) 13 | 14 | // 返回的是 reflect.Type 类型值 15 | dogType := reflect.TypeOf(dog) 16 | fmt.Println("dog type:", dogType) 17 | 18 | // 返回的是 dog 指针对应的 reflect.Value 类型值 19 | dogValue := reflect.ValueOf(&dog).Elem() 20 | // 获取 dogValue 的所有属性 21 | fmt.Println("================ Props ================") 22 | for i := 0; i < dogValue.NumField(); i++ { 23 | // 获取属性名 24 | fmt.Println("name:", dogValue.Type().Field(i).Name) 25 | // 获取属性类型 26 | fmt.Println("type:", dogValue.Type().Field(i).Type) 27 | // 获取属性值 28 | fmt.Println("value:", dogValue.Field(i)) 29 | } 30 | // 获取 dogValue 的所有方法 31 | fmt.Println("================ Methods ================") 32 | for j := 0; j < dogValue.NumMethod(); j++ { 33 | // 获取方法名 34 | fmt.Println("name:", dogValue.Type().Method(j).Name) 35 | // 获取方法类型 36 | fmt.Println("type:", dogValue.Type().Method(j).Type) 37 | // 调用该方法 38 | fmt.Println("exec result:", dogValue.Method(j).Call([]reflect.Value{})) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /chapter01/06-transform.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | func main() { 9 | // 整型 <=> 整型 10 | //v1 := -1 11 | //v2 := uint8(v1) 12 | //fmt.Println(v2) // 255 13 | 14 | // 整型 <=> 浮点型 15 | //v3 := 99 16 | //v4 := float32(v3) 17 | //fmt.Println(v4) // 99 18 | 19 | // 字符串 20 | v1 := "100" 21 | v2, _ := strconv.Atoi(v1) // 将字符串转化为整型,v2 = 100 22 | fmt.Println(v2) 23 | 24 | v3 := 100 25 | v4 := strconv.Itoa(v3) // 将整型转化为字符串, v4 = "100" 26 | fmt.Println(v4) 27 | 28 | v5 := "true" 29 | v6, _ := strconv.ParseBool(v5) // 将字符串转化为布尔型 30 | v5 = strconv.FormatBool(v6) // 将布尔值转化为字符串 31 | fmt.Println(v5) 32 | fmt.Println(v6) 33 | 34 | v7 := "100" 35 | v8, _ := strconv.ParseInt(v7, 10, 64) // 将字符串转化为整型,第二个参数表示进制,第三个参数表示最大位数 36 | v7 = strconv.FormatInt(v8, 10) // 将整型转化为字符串,第二个参数表示进制 37 | fmt.Println(v7) 38 | fmt.Println(v8) 39 | 40 | v9, _ := strconv.ParseUint(v7, 10, 64) // 将字符串转化为无符号整型,参数含义同 ParseInt 41 | v7 = strconv.FormatUint(v9, 10) // 将字符串转化为无符号整型,参数含义同 FormatInt 42 | fmt.Println(v7) 43 | fmt.Println(v9) 44 | 45 | v10 := "99.99" 46 | v11, _ := strconv.ParseFloat(v10, 64) // 将字符串转化为浮点型,第二个参数表示精度 47 | v10 = strconv.FormatFloat(v11, 'E', -1, 64) 48 | fmt.Println(v10) 49 | fmt.Println(v11) 50 | 51 | q := strconv.Quote("Hello, 世界") // 为字符串加引号 52 | q = strconv.QuoteToASCII("Hello, 世界") // 将字符串转化为 ASCII 编码 53 | fmt.Println(q) 54 | } 55 | -------------------------------------------------------------------------------- /chapter03/10-pipeline.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | ) 6 | 7 | type user struct { 8 | name string 9 | age int 10 | } 11 | 12 | func filterAge(users []user) interface{} { 13 | var slice []user 14 | for _, u := range users { 15 | if u.age >= 18 && u.age <= 35 { 16 | slice = append(slice, u) 17 | } 18 | } 19 | return slice 20 | } 21 | 22 | func mapAgeToSlice(users []user) interface{} { 23 | var slice []int 24 | for _, u := range users { 25 | slice = append(slice, u.age) 26 | } 27 | return slice 28 | } 29 | 30 | func sumAge(users []user, pipes ...func([]user) interface{}) int { 31 | var ages []int 32 | var sum int 33 | for _, f := range pipes { 34 | result := f(users) 35 | switch result.(type) { 36 | case []user: 37 | users = result.([]user) 38 | case []int: 39 | ages = result.([]int) 40 | } 41 | } 42 | if len(ages) == 0 { 43 | log.Fatalln("没有在管道中加入 mapAgeToSlice 方法") 44 | } 45 | for _, age := range ages { 46 | sum += age 47 | } 48 | return sum 49 | } 50 | 51 | func main() { 52 | var users = []user{ 53 | { 54 | name: "张三", 55 | age: 18, 56 | }, 57 | { 58 | name: "李四", 59 | age: 22, 60 | }, 61 | { 62 | name: "王五", 63 | age: 20, 64 | }, 65 | { 66 | name: "赵六", 67 | age: -10, 68 | }, 69 | { 70 | name: "孙七", 71 | age: 60, 72 | }, 73 | { 74 | name: "周八", 75 | age: 10, 76 | }, 77 | } 78 | 79 | sum := sumAge(users, filterAge, mapAgeToSlice) 80 | log.Printf("用户年龄累加结果: %d\n", sum) 81 | } 82 | -------------------------------------------------------------------------------- /chapter06/string/kmp.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // 生成 next 数组 6 | func generateNext(p string) []int { 7 | m := len(p) 8 | next := make([]int, m, m) 9 | next[0] = -1 10 | next[1] = 0 11 | i, j := 0, 1 // 前缀子串、后缀子串起始位置 12 | // 因为是通过最长可匹配前缀子串计算,所以 j 的值最大不会超过 m-1 13 | for j < m - 1 { 14 | if i == -1 || p[i] == p[j] { 15 | i++ 16 | j++ 17 | next[j] = i 18 | } else { 19 | // 如果 p[i] != p[j] 20 | i = next[i] 21 | } 22 | } 23 | return next 24 | } 25 | 26 | // KMP 算法实现函数 27 | func kmpSearch(s, p string) int { 28 | n := len(s) // 主串长度 29 | m := len(p) // 模式串长度 30 | next := generateNext(p) // 生成 next 数组 31 | i, j := 0, 0 32 | for i < n && j < m { 33 | // 如果主串字符和模式串字符不相等, 34 | // 更新模式串坏字符下标位置为好前缀最长可匹配前缀子串尾字符下标 35 | // 然后从这个位置重新开始与主串匹配 36 | // 相当于前面提到的把模式串向后移动 j - k 位 37 | if j == -1 || s[i] == p[j] { 38 | i++ 39 | j++ 40 | } else { 41 | j = next[j] 42 | } 43 | } 44 | if j == m { 45 | return i - j 46 | } else { 47 | return -1 48 | } 49 | } 50 | 51 | // 基于 KMP 算法实现字符串查找函数 52 | func strStrV2(haystack, needle string) int { 53 | // 子串长度=0 54 | if len(needle) == 0 { 55 | return 0 56 | } 57 | //主串长度=0,或者主串长度小于子串长度 58 | if len(haystack) == 0 || len(haystack) < len(needle) { 59 | return -1 60 | } 61 | // 子串长度=1时单独判断 62 | if len(needle) == 1 { 63 | i := 0 64 | for ; i < len(haystack); i++ { 65 | if haystack[i] == needle[0] { 66 | return i 67 | } 68 | } 69 | return -1 70 | } 71 | 72 | // 其他情况走 KMP 算法 73 | return kmpSearch(haystack, needle) 74 | } 75 | 76 | func main() { 77 | s := "Hello, 学院君!" 78 | p := "学院君" 79 | pos := strStrV2(s, p) 80 | fmt.Printf("Find \"%s\" at %d in \"%s\"\n", p, pos, s) 81 | } -------------------------------------------------------------------------------- /chapter06/stack/list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // 定义链表节点 8 | type Node struct { 9 | Value int 10 | Next *Node 11 | } 12 | 13 | // 初始化栈结构(空栈) 14 | var size = 0 15 | var stack = new(Node) 16 | 17 | // 进栈 18 | func Push(v int) bool { 19 | // 空栈的话直接将值放入头节点即可 20 | if stack == nil { 21 | stack = &Node{v, nil} 22 | size = 1 23 | return true 24 | } 25 | 26 | // 否则将插入节点作为栈的头节点 27 | temp := &Node{v, nil} 28 | temp.Next = stack 29 | stack = temp 30 | size++ 31 | return true 32 | } 33 | 34 | // 出栈 35 | func Pop(t *Node) (int, bool) { 36 | // 空栈 37 | if size == 0 { 38 | return 0, false 39 | } 40 | 41 | // 只有一个节点 42 | if size == 1 { 43 | size = 0 44 | stack = nil 45 | return t.Value, true 46 | } 47 | 48 | // 将栈的头节点指针指向下一个节点,并返回之前的头节点数据 49 | stack = stack.Next 50 | size-- 51 | return t.Value, true 52 | } 53 | 54 | // 遍历(不删除任何节点,只读取值) 55 | func traverse(t *Node) { 56 | if size == 0 { 57 | fmt.Println("空栈!") 58 | return 59 | } 60 | 61 | for t != nil { 62 | fmt.Printf("%d -> ", t.Value) 63 | t = t.Next 64 | } 65 | fmt.Println() 66 | } 67 | 68 | func main() { 69 | stack = nil 70 | // 读取空栈 71 | v, b := Pop(stack) 72 | if b { 73 | fmt.Print(v, " ") 74 | } else { 75 | fmt.Println("Pop() 失败!") 76 | } 77 | 78 | // 进栈 79 | Push(100) 80 | // 遍历栈 81 | traverse(stack) 82 | // 再次进栈 83 | Push(200) 84 | // 再次遍历栈 85 | traverse(stack) 86 | 87 | // 批量进栈 88 | for i := 0; i < 10; i++ { 89 | Push(i) 90 | } 91 | 92 | // 批量出栈 93 | for i := 0; i < 15; i++ { 94 | v, b := Pop(stack) 95 | if b { 96 | fmt.Print(v, " ") 97 | } else { 98 | // 如果已经是空栈,则退出循环 99 | break 100 | } 101 | } 102 | 103 | fmt.Println() 104 | // 再次遍历栈 105 | traverse(stack) 106 | } -------------------------------------------------------------------------------- /chapter06/string/trie.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Trie 树节点 6 | type trieNode struct { 7 | char string // Unicode 字符 8 | isEnding bool // 是否是单词结尾 9 | children map[rune]*trieNode // 该节点的子节点 10 | } 11 | 12 | // 初始化 Trie 树节点 13 | func NewTrieNode(char string) *trieNode { 14 | return &trieNode{ 15 | char: char, 16 | isEnding: false, 17 | children: make(map[rune]*trieNode), 18 | } 19 | } 20 | 21 | // Trie 树结构 22 | type Trie struct { 23 | root *trieNode // 根节点指针 24 | } 25 | 26 | // 初始化 Trie 树 27 | func NewTrie() *Trie { 28 | // 初始化根节点 29 | trieNode := NewTrieNode("/") 30 | return &Trie{trieNode} 31 | } 32 | 33 | // 往 Trie 树中插入一个单词 34 | func (t *Trie) Insert(word string) { 35 | node := t.root // 获取根节点 36 | for _, code := range word { // 以 Unicode 字符遍历该单词 37 | value, ok := node.children[code] // 获取 code 编码对应子节点 38 | if !ok { 39 | // 不存在则初始化该节点 40 | value = NewTrieNode(string(code)) 41 | // 然后将其添加到子节点字典 42 | node.children[code] = value 43 | } 44 | // 当前节点指针指向当前子节点 45 | node = value 46 | } 47 | node.isEnding = true // 一个单词遍历完所有字符后将结尾字符打上标记 48 | } 49 | 50 | // 在 Trie 树中查找一个单词 51 | func (t *Trie) Find(word string) bool { 52 | node := t.root 53 | for _, code := range word { 54 | value, ok := node.children[code] // 获取对应子节点 55 | if !ok { 56 | // 不存在则直接返回 57 | return false 58 | } 59 | // 否则继续往后遍历 60 | node = value 61 | } 62 | if node.isEnding == false { 63 | return false // 不能完全匹配,只是前缀 64 | } 65 | return true // 找到对应单词 66 | } 67 | 68 | func main() { 69 | trie := NewTrie() 70 | words := []string{"Golang", "学院君", "Language", "Trie", "Go"} 71 | for _, word := range words { 72 | trie.Insert(word) 73 | } 74 | term := "学院君" 75 | if trie.Find(term) { 76 | fmt.Printf("包含单词\"%s\"\n", term) 77 | } else { 78 | fmt.Printf("不包含单词\"%s\"\n", term) 79 | } 80 | } -------------------------------------------------------------------------------- /chapter03/08-recursive.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | type FibonacciFunc func(int) int 9 | 10 | // 通过递归函数实现斐波那契数列 11 | func fibonacci(n int) int { 12 | // 终止条件 13 | if n == 1 { 14 | return 0 15 | } 16 | if n == 2 { 17 | return 1 18 | } 19 | // 递归公式 20 | return fibonacci(n-1) + fibonacci(n-2) 21 | } 22 | 23 | func fibonacciExecTime(f FibonacciFunc) FibonacciFunc { 24 | return func(n int) int { 25 | start := time.Now() // 起始时间 26 | num := f(n) // 执行斐波那契函数 27 | end := time.Since(start) // 函数执行完毕耗时 28 | fmt.Printf("--- 执行耗时: %v ---\n", end) 29 | return num // 返回计算结果 30 | } 31 | } 32 | 33 | const MAX = 50 34 | 35 | var fibs [MAX]int 36 | 37 | // 缓存中间结果的递归函数优化版 38 | func fibonacci2(n int) int { 39 | if n == 1 { 40 | return 0 41 | } 42 | 43 | if n == 2 { 44 | return 1 45 | } 46 | 47 | index := n - 1 48 | if fibs[index] != 0 { 49 | return fibs[index] 50 | } 51 | 52 | num := fibonacci2(n-1) + fibonacci2(n-2) 53 | fibs[index] = num 54 | return num 55 | } 56 | 57 | // 尾递归版本的斐波那契函数 58 | func fibonacci3(n int) int { 59 | return fibonacciTail(n, 0, 1) 60 | } 61 | 62 | func fibonacciTail(n, first, second int) int { 63 | if n < 2 { 64 | return first 65 | } 66 | return fibonacciTail(n-1, second, first+second) 67 | } 68 | 69 | func main() { 70 | n1 := 5 71 | f1 := fibonacciExecTime(fibonacci) 72 | r1 := f1(n1) 73 | fmt.Printf("The %dth number of fibonacci sequence is %d\n", n1, r1) 74 | 75 | n2 := 50 76 | r2 := f1(n2) 77 | fmt.Printf("The %dth number of fibonacci sequence is %d\n", n2, r2) 78 | 79 | f2 := fibonacciExecTime(fibonacci2) 80 | r3 := f2(n2) 81 | fmt.Printf("The %dth number of fibonacci sequence is %d\n", n2, r3) 82 | 83 | f3 := fibonacciExecTime(fibonacci3) 84 | r4 := f3(n2) 85 | fmt.Printf("The %dth number of fibonacci sequence is %d\n", n2, r4) 86 | } 87 | -------------------------------------------------------------------------------- /chapter06/queue/list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // 定义链表节点 8 | type Node struct { 9 | Value int 10 | Next *Node 11 | } 12 | 13 | // 初始化队列 14 | var size = 0 15 | var queue = new(Node) 16 | 17 | // 入队(从队头插入) 18 | func Push(t *Node, v int) bool { 19 | if queue == nil { 20 | queue = &Node{v, nil} 21 | size++ 22 | return true 23 | } 24 | 25 | t = &Node{v, nil} 26 | t.Next = queue 27 | queue = t 28 | size++ 29 | 30 | return true 31 | } 32 | 33 | // 出队(从队尾删除) 34 | func Pop(t *Node) (int, bool) { 35 | if size == 0 { 36 | return 0, false 37 | } 38 | 39 | if size == 1 { 40 | queue = nil 41 | size-- 42 | return t.Value, true 43 | } 44 | 45 | // 迭代队列,直到队尾 46 | temp := t 47 | for (t.Next) != nil { 48 | temp = t 49 | t = t.Next 50 | } 51 | 52 | v := (temp.Next).Value 53 | temp.Next = nil 54 | 55 | size-- 56 | return v, true 57 | } 58 | 59 | // 遍历队列所有节点 60 | func traverse(t *Node) { 61 | if size == 0 { 62 | fmt.Println("空队列!") 63 | return 64 | } 65 | for t != nil { 66 | fmt.Printf("%d -> ", t.Value) 67 | t = t.Next 68 | } 69 | fmt.Println() 70 | } 71 | 72 | func main() { 73 | queue = nil 74 | // 入队 75 | Push(queue, 10) 76 | fmt.Println("Size:", size) 77 | // 遍历 78 | traverse(queue) 79 | 80 | // 出队 81 | v, b := Pop(queue) 82 | if b { 83 | fmt.Println("Pop:", v) 84 | } 85 | fmt.Println("Size:", size) 86 | 87 | // 批量入队 88 | for i := 0; i < 5; i++ { 89 | Push(queue, i) 90 | } 91 | // 再次遍历 92 | traverse(queue) 93 | fmt.Println("Size:", size) 94 | 95 | // 出队 96 | v, b = Pop(queue) 97 | if b { 98 | fmt.Println("Pop:", v) 99 | } 100 | fmt.Println("Size:", size) 101 | 102 | // 再次出队 103 | v, b = Pop(queue) 104 | if b { 105 | fmt.Println("Pop:", v) 106 | } 107 | fmt.Println("Size:", size) 108 | // 再次遍历 109 | traverse(queue) 110 | } -------------------------------------------------------------------------------- /chapter06/linkedlist/single.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // 定义节点 8 | type Node struct { 9 | Value int 10 | Next *Node 11 | } 12 | 13 | // 初始化头节点 14 | var head = new(Node) 15 | 16 | // 添加节点 17 | func addNode(t *Node, v int) int { 18 | if head == nil { 19 | t = &Node{v, nil} 20 | head = t 21 | return 0 22 | } 23 | 24 | if v == t.Value { 25 | fmt.Println("节点已存在:", v) 26 | return -1 27 | } 28 | 29 | // 如果当前节点下一个节点为空 30 | if t.Next == nil { 31 | t.Next = &Node{v, nil} 32 | return -2 33 | } 34 | 35 | // 如果当前节点下一个节点不为空 36 | return addNode(t.Next, v) 37 | } 38 | 39 | // 遍历链表 40 | func traverse(t *Node) { 41 | if t == nil { 42 | fmt.Println("-> 空链表!") 43 | return 44 | } 45 | 46 | for t != nil { 47 | fmt.Printf("%d -> ", t.Value) 48 | t = t.Next 49 | } 50 | 51 | fmt.Println() 52 | } 53 | 54 | // 查找节点 55 | func lookupNode(t *Node, v int) bool { 56 | if head == nil { 57 | t = &Node{v, nil} 58 | head = t 59 | return false 60 | } 61 | 62 | if v == t.Value { 63 | return true 64 | } 65 | 66 | if t.Next == nil { 67 | return false 68 | } 69 | 70 | return lookupNode(t.Next, v) 71 | } 72 | 73 | // 获取链表长度 74 | func size(t *Node) int { 75 | if t == nil { 76 | fmt.Println("-> 空链表!") 77 | return 0 78 | } 79 | 80 | i := 0 81 | for t != nil { 82 | i++ 83 | t = t.Next 84 | } 85 | 86 | return i 87 | } 88 | 89 | // 入口函数 90 | func main() { 91 | fmt.Println(head) 92 | head = nil 93 | // 遍历链表 94 | traverse(head) 95 | // 添加节点 96 | addNode(head, 1) 97 | addNode(head, -1) 98 | // 再次遍历 99 | traverse(head) 100 | // 添加更多节点 101 | addNode(head, 10) 102 | addNode(head, 5) 103 | addNode(head, 45) 104 | // 添加已存在节点 105 | addNode(head, 5) 106 | // 再次遍历 107 | traverse(head) 108 | 109 | // 查找已存在节点 110 | if lookupNode(head, 5) { 111 | fmt.Println("该节点已存在!") 112 | } else { 113 | fmt.Println("该节点不存在!") 114 | } 115 | 116 | // 查找不存在节点 117 | if lookupNode(head, -100) { 118 | fmt.Println("该节点已存在!") 119 | } else { 120 | fmt.Println("该节点不存在!") 121 | } 122 | } -------------------------------------------------------------------------------- /chapter03/09-map_reduce.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | func ageSum(users []map[string]string) int { 9 | var sum int 10 | for _, user := range users { 11 | num, _ := strconv.Atoi(user["age"]) 12 | sum += num 13 | } 14 | return sum 15 | } 16 | 17 | // Map 函数 18 | func mapToString(items []map[string]string, f func(map[string]string) string) []string { 19 | newSlice := make([]string, len(items)) 20 | for _, item := range items { 21 | newSlice = append(newSlice, f(item)) 22 | } 23 | return newSlice 24 | } 25 | 26 | // Reduce 函数 27 | func fieldSum(items []string, f func(string) int) int { 28 | var sum int 29 | for _, item := range items{ 30 | sum += f(item) 31 | } 32 | return sum 33 | } 34 | 35 | // Filter 函数 36 | func itemsFilter(items []map[string]string, f func(map[string]string) bool) []map[string]string { 37 | newSlice := make([]map[string]string, len(items)) 38 | for _, item := range items { 39 | if f(item) { 40 | newSlice = append(newSlice, item) 41 | } 42 | } 43 | return newSlice 44 | } 45 | 46 | func main() { 47 | var users = []map[string]string{ 48 | { 49 | "name": "张三", 50 | "age": "18", 51 | }, 52 | { 53 | "name": "李四", 54 | "age": "22", 55 | }, 56 | { 57 | "name": "王五", 58 | "age": "20", 59 | }, 60 | { 61 | "name": "赵六", 62 | "age": "-10", 63 | }, 64 | { 65 | "name": "孙七", 66 | "age": "60", 67 | }, 68 | { 69 | "name": "周八", 70 | "age": "10", 71 | }, 72 | } 73 | //fmt.Printf("用户年龄累加结果: %d\n", ageSum(users)) 74 | 75 | validUsers := itemsFilter(users, func(user map[string]string) bool { 76 | age, ok := user["age"] 77 | if !ok { 78 | return false 79 | } 80 | intAge, err := strconv.Atoi(age) 81 | if err != nil { 82 | return false 83 | } 84 | if intAge < 18 || intAge > 35 { 85 | return false 86 | } 87 | return true 88 | }) 89 | ageSlice := mapToString(validUsers, func(user map[string]string) string { 90 | return user["age"] 91 | }) 92 | sum := fieldSum(ageSlice, func(age string) int { 93 | intAge, _ := strconv.Atoi(age) 94 | return intAge 95 | }) 96 | fmt.Printf("用户年龄累加结果: %d\n", sum) 97 | } 98 | -------------------------------------------------------------------------------- /chapter04/reflect/generic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | type Container struct { 9 | s reflect.Value 10 | } 11 | 12 | // 通过传入存储元素类型和容量来初始化容器 13 | func NewContainer(t reflect.Type, size int) *Container { 14 | if size <= 0 { 15 | size = 64 16 | } 17 | // 基于切片类型实现这个容器,这里通过反射动态初始化这个底层切片 18 | return &Container{ 19 | s: reflect.MakeSlice(reflect.SliceOf(t), 0, size), 20 | } 21 | } 22 | 23 | // 添加元素到容器,通过空接口声明传递的元素类型,表明支持任何类型 24 | func (c *Container) Put(val interface{}) error { 25 | // 通过反射对实际传递进来的元素类型进行运行时检查, 26 | // 如果与容器初始化时设置的元素类型不同,则返回错误信息 27 | // c.s.Type() 对应的是切片类型,c.s.Type().Elem() 应的才是切片元素类型 28 | if reflect.ValueOf(val).Type() != c.s.Type().Elem() { 29 | return fmt.Errorf("put error: cannot put a %T into a slice of %s", 30 | val, c.s.Type().Elem()) 31 | } 32 | // 如果类型检查通过则将其添加到容器中 33 | c.s = reflect.Append(c.s, reflect.ValueOf(val)) 34 | return nil 35 | } 36 | 37 | // 从容器中读取元素,将返回结果赋值给 val,同样通过空接口指定元素类型 38 | func (c *Container) Get(val interface{}) error { 39 | // 还是通过反射对元素类型进行检查,如果不通过则返回错误信息 40 | // Kind 与 Type 相比范围更大,表示类别,如指针,而 Type 则对应具体类型,如 *int 41 | // 由于 val 是指针类型,所以需要通过 reflect.ValueOf(val).Elem() 获取指针指向的类型 42 | if reflect.ValueOf(val).Kind() != reflect.Ptr || 43 | reflect.ValueOf(val).Elem().Type() != c.s.Type().Elem() { 44 | return fmt.Errorf("get error: needs *%s but got %T", c.s.Type().Elem(), val) 45 | } 46 | // 将容器第一个索引位置值赋值给 val 47 | reflect.ValueOf(val).Elem().Set( c.s.Index(0) ) 48 | // 然后删除容器第一个索引位置值 49 | c.s = c.s.Slice(1, c.s.Len()) 50 | return nil 51 | } 52 | 53 | func main() { 54 | nums := []int{1, 2, 3, 4, 5} 55 | 56 | // 初始化容器,元素类型和 nums 中的元素类型相同 57 | c := NewContainer(reflect.TypeOf(nums[0]), 16) 58 | 59 | // 添加元素到容器 60 | for _, n := range nums { 61 | if err := c.Put(n); err != nil { 62 | panic(err) 63 | } 64 | } 65 | 66 | // 从容器读取元素,将返回结果初始化为 0 67 | num := 0 68 | if err := c.Get(&num); err != nil { 69 | panic(err) 70 | } 71 | 72 | // 打印返回结果值 73 | fmt.Printf("%v (%T)\n", num, num) 74 | } -------------------------------------------------------------------------------- /chapter06/double.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // 定义节点 8 | type Node struct { 9 | Value int 10 | Previous *Node 11 | Next *Node 12 | } 13 | 14 | // 添加节点 15 | func addNode(t *Node, v int) int { 16 | if head == nil { 17 | t = &Node{v, nil, nil} 18 | head = t 19 | return 0 20 | } 21 | 22 | if v == t.Value { 23 | fmt.Println("节点已存在:", v) 24 | return -1 25 | } 26 | 27 | // 如果当前节点下一个节点为空 28 | if t.Next == nil { 29 | // 与单链表不同的是每个节点还要维护前驱节点指针 30 | temp := t 31 | t.Next = &Node{v, temp, nil} 32 | return -2 33 | } 34 | 35 | // 如果当前节点下一个节点不为空 36 | return addNode(t.Next, v) 37 | } 38 | 39 | // 遍历链表 40 | func traverse(t *Node) { 41 | if t == nil { 42 | fmt.Println("-> 空链表!") 43 | return 44 | } 45 | 46 | for t != nil { 47 | fmt.Printf("%d -> ", t.Value) 48 | t = t.Next 49 | } 50 | 51 | fmt.Println() 52 | } 53 | 54 | // 反向遍历链表 55 | func reverse(t *Node) { 56 | if t == nil { 57 | fmt.Println("-> 空链表!") 58 | return 59 | } 60 | 61 | temp := t 62 | for t != nil { 63 | temp = t 64 | t = t.Next 65 | } 66 | 67 | for temp.Previous != nil { 68 | fmt.Printf("%d -> ", temp.Value) 69 | temp = temp.Previous 70 | } 71 | 72 | fmt.Printf("%d -> ", temp.Value) 73 | fmt.Println() 74 | } 75 | 76 | // 获取链表长度 77 | func size(t *Node) int { 78 | if t == nil { 79 | fmt.Println("-> 空链表!") 80 | return 0 81 | } 82 | 83 | n := 0 84 | for t != nil { 85 | n++ 86 | t = t.Next 87 | } 88 | 89 | return n 90 | } 91 | 92 | // 查找节点 93 | func lookupNode(t *Node, v int) bool { 94 | if head == nil { 95 | return false 96 | } 97 | 98 | if v == t.Value { 99 | return true 100 | } 101 | 102 | if t.Next == nil { 103 | return false 104 | } 105 | 106 | return lookupNode(t.Next, v) 107 | } 108 | 109 | // 初始化头节点 110 | var head = new(Node) 111 | 112 | func main() { 113 | fmt.Println(head) 114 | head = nil 115 | // 遍历链表 116 | traverse(head) 117 | // 新增节点 118 | addNode(head, 1) 119 | // 再次遍历 120 | traverse(head) 121 | // 继续添加节点 122 | addNode(head, 10) 123 | addNode(head, 5) 124 | addNode(head, 100) 125 | // 再次遍历 126 | traverse(head) 127 | // 添加已存在节点 128 | addNode(head, 100) 129 | fmt.Println("链表长度:", size(head)) 130 | // 再次遍历 131 | traverse(head) 132 | // 反向遍历 133 | reverse(head) 134 | 135 | // 查找已存在节点 136 | if lookupNode(head, 5) { 137 | fmt.Println("该节点已存在!") 138 | } else { 139 | fmt.Println("该节点不存在!") 140 | } 141 | } --------------------------------------------------------------------------------