├── 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 | }
--------------------------------------------------------------------------------