【阶段1 Go语言基础】Day03 函数、错误处理

发布时间 2023-05-30 00:54:50作者: 澐湮

day03

函数

package main

import "fmt"

//导入包(标准包,自定义包,第三方包)

//包级别的变量,常量,函数

//无参 无返回值
func sayHello() {
	fmt.Println("Hello World")
}

//有参 无返回值
func sayHi(name string, name2 string) {
	fmt.Println("Hi", name, name2)
}

//有参 有返回值
func add(n1 int, n2 int) int {
	return n1 + n2
}

func test(a int, b string) {
	fmt.Println(a, b)
}

func main() {
	//sayHello

	//调用 方法名()
	sayHello()
	sayHi("aa", "bb")
	n := add(1, 2)
	fmt.Println(n)

	test(1, "cc")
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run func.go
Hello World
Hi aa bb
3
1 cc
*/

参数

参数合并
package main

import "fmt"

//参数类型合并
//连续多个变量类型相同
// 保留最后一个元素类型,前面的类型都可以省略

func add(n1, n2 int) int {
	return n1 + n2
}

func test(p1, p2 string, p3, p4 int, p5, p6 bool) {
	fmt.Printf("%T,%T,%T,%T,%T,%T\n", p1, p2, p3, p4, p5, p6)
	fmt.Println(p1, p2, p3, p4, p5, p6)
}

func main() {
	fmt.Println(add(1, 2))
	test("", "", 0, 0, false, false)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run params.go
3
string,string,int,int,bool,bool
  0 0 false false
*/
可变参数
package main

import "fmt"

//可变参数的函数

func test(args ...string) {
	fmt.Printf("%T,%#v\n", args, args)
}

//1.可变参数 在一个方法中只能有一个
//2.并且可变参数必须放在函数声明参数列表最后

//举例(函数至少有n个参数)
//add(n1,n2,...)
func add(n1, n2 int, args ...int) int {
	total := n1 + n2

	for _, v := range args {
		total += v
	}
	return total

}

func main() {
	test()
	test("1")
	test("1", "2", "3")

	fmt.Println(1, 2)
	fmt.Println(1, 2, 3)
	fmt.Println(1, 2, 3, 4)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run args.go
[]string,[]string(nil)
[]string,[]string{"1"}
[]string,[]string{"1", "2", "3"}
1 2
1 2 3
1 2 3 4
*/
解切片
package main

import "fmt"

//可变参数的函数

func test(args ...string) {
	fmt.Printf("%T,%#v\n", args, args)
}

//1.可变参数 在一个方法中只能有一个
//2.并且可变参数必须放在函数声明参数列表最后

//举例(函数至少有n个参数)
//add(n1,n2,...)
func add(n1, n2 int, args ...int) int {
	total := n1 + n2

	for _, v := range args {
		total += v
	}
	return total
}

func calc(n1, n2 int, args ...int) int {
	//直接调用add把add方法结果进行返回
	//args切片
	// switch(len(args))
	//add(n1,n2,args[0],args[1]...)
	return add(n1, n2, args...) //解操作
}

func main() {
	// test()
	// test("1")
	// test("1", "2", "3")

	// fmt.Println(1, 2)
	// fmt.Println(1, 2, 3)
	// fmt.Println(1, 2, 3, 4)
	params := []int{1, 2, 3, 4, 5, 6, 7}
	fmt.Println(add(1, 2, params...))
}


/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run args.go
31
*/

返回值

多返回值&命名返回值&合并返回值类型
package main

import "fmt"

func add(n1, n2 int) int {
	return n1 + n2
}

func mult(n1, n2 int) int {
	return n1 * n2
}

//多返回值
func calc(n1, n2 int) (int, int) {
	//a,b:=1,2
	r1 := add(n1, n2)
	r2 := mult(n1, n2)
	return r1, r2
}

//命名返回值
func calc2(n1, n2 int) (r1 int, r2 int) {
	//a,b:=1,2
	r1 = add(n1, n2)
	r2 = mult(n1, n2)
	return
}

//合并返回值类型
func calc3(n1, n2 int) (r1, r2 int) {
	//a,b:=1,2
	r1 = add(n1, n2)
	r2 = mult(n1, n2)
	return
}

func main() {
	fmt.Println(calc(1, 2))
	fmt.Println(calc2(1, 2))
	fmt.Println(calc3(1, 2))
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run return.go
3 2
3 2
3 2
*/
值类型和引用类型
package main

import "fmt"

func main() {
	//值类型 b=a
	age := 30
	tmpAge := age
	tmpAge = 31
	fmt.Println(age, tmpAge)
	fmt.Printf("%p,%p\n", &age, &tmpAge)

	//引用类型 b=a (地址)
	users := make([]string, 10)
	tmpUsers := users
	tmpUsers[0] = "xx"
	fmt.Printf("%#v,%#v\n", users, tmpUsers)
	fmt.Printf("%p,%p\n", users, tmpUsers)

}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run quote.go
30 31
0xc0000aa058,0xc0000aa070
[]string{"xx", "", "", "", "", "", "", "", "", ""},[]string{"xx", "", "", "", "", "", "", "", "", ""}
0xc0000a2140,0xc0000a2140
*/
函数使用值类型和引用类型
package main

import "fmt"

func test1(n int) {
	n = 1
}

func test2(s []int) {
	fmt.Printf("test2:%p\n", s)
	s[0] = 1
}

func main() {
	a := 0
	b := make([]int, 10)
	test1(a)
	test2(b)
	fmt.Println(a)
	fmt.Println(b)
	fmt.Printf("main:%p\n", b)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run quote.go
test2:0xc0000b00f0
0
[1 0 0 0 0 0 0 0 0 0]
main:0xc0000b00f0
*/
根据条件,返回不同的返回值
package main

import "fmt"

func test(flag bool) int {
	if flag {
		return 1
	}
	fmt.Println("return before")
	return 2
}

func main() {
	fmt.Println(test(true))
	fmt.Println(test(false))
}

递归

阶乘
package main

import "fmt"

//阶乘
//n!=
// n=0 n!=1
// n>=1 n!=n*(n-1)!=n*(n-1)*...*1
// f(n) = n!
// f(n) = n*f(n-1)
// 分治=> 大问题分解为多个相同的小问题(小问题可以继续拆分,直到某一个可以解决的子问题)
// 递归调用=>函数直接或间接调用自己(总有一个停止的条件,)
func f(n int64) int64 {
	if n == 0 {
		return 1
	}
	return n * f(n-1)
}

func main() {
	//f(3)=3*f(2)=3*2*f(1)
	fmt.Println(f(3))
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run fact.go
6
*/

汉诺塔

从start挪到end 接着temp

package main

import (
	"fmt"
)

// n个盘子 start(开始) end(终点) temp(借助)
// n start -> temp ->end
// n -1 start ->end =>temp
// start ->end
// n-1 temp -> start ->end
// 终止条件 start -> end
func tower(start string, end string, temp string, layer int) {
	if layer == 1 {
		fmt.Println(start, "->", end)
		return
	}
	tower(start, temp, end, layer-1)
	fmt.Println(start, "->", end)
	tower(temp, end, start, layer-1)
}

func main() {
	tower("塔1", "塔3", "塔2", 3)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run tower.go
塔1 -> 塔3
塔1 -> 塔2
塔3 -> 塔2
塔1 -> 塔3
塔2 -> 塔1
塔2 -> 塔3
塔1 -> 塔3
*/

函数指针传递

package main

import "fmt"

//值类型 在函数内修改实参的值
//fmt.Scan(&age)

func change(value int) {
	value += 1
}

func changePoint(pointer *int) {
	*pointer = *pointer + 1
}

func main() {
	value := 1
	change(value)
	fmt.Println(value)

	changePoint(&value)
	fmt.Println(value)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run pointer.go
1
2
*/

函数类型

package main

import "fmt"

// //无参 无返回值
// func sayHell() {
// 	fmt.Println("Hello World")
// }

// //有参 无返回值
// func sayHi(name string, name2 string) {
// 	fmt.Println("Hi:", name, name2)
// }

// //有参 有返回值
// func add(n1 int, n2 int) int {
// 	return n1 + n2
// }

func test(a int, b string) int {
	fmt.Println(a, b)
	return 1
}

func main() {
	//test() //函数调用
	a := test
	b := test(1, "") //执行test函数 打印 1 "" //空字符省略了
	fmt.Printf("%T\n", test)
	fmt.Printf("%T\n", a)
	fmt.Printf("%T\n", b)
	a(1, "xx")

	// callback的值是nil
	var callback func(int, int) int
	fmt.Printf("%T,%#v\n", callback, callback)

}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run type.go
1 
func(int, string) int
func(int, string) int
int
1 xx
*/

声明函数类型&类型一致赋值
package main

import "fmt"

//有参 有返回值
func add(n1 int, n2 int) int {
	return n1 + n2
}

func main() {
    
	// callback的值是nil
	var callback func(int, int) int
	fmt.Printf("%T,%#v\n", callback, callback)

	callback = add
	fmt.Printf("%#v\n", callback)
	rt := callback(1, 4)
	fmt.Println(rt)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run type.go
func(int, int) int,(func(int, int) int)(nil)
(func(int, int) int)(0x76dd40)
5
*/

类型不一致不能赋值

必须一致才能赋值

//有参 有返回值
func add(n1 int, n2 int) int {
	return n1 + n2
}

func test(a int, b string) int {
	fmt.Println(a, b)
	return 1
}


高阶函数

函数作为参数 funcparams.go
package main

import "fmt"

func calc(n1 int, n2 int, callback func(int, int) int) int {
	//不定义什么运算
	//通过函数参数传递要进行的运算
	rt := callback(n1, n2)
	//检查结果在0,100范围内,超过-1
	if rt >= 0 && rt <= 100 {
		return rt
	}
	return -1
}

func add(n1, n2 int) int {
	return n1 + n2
}

func mult(n1, n2 int) int {
	return n1 * n2
}

func main() {
	rt := calc(1, 2, add)
	fmt.Println(rt)

	rt = calc(1, 2, mult)
	fmt.Println(rt)

	rt = calc(50, 30, add)
	fmt.Println(rt)

	rt = calc(50, 30, mult)
	fmt.Println(rt)

}
/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run funcparams.go
3
2
80
-1
*/

匿名函数

匿名函数示例 lambda.go
示例1
package main

import "fmt"

func calc(n1 int, n2 int, callback func(int, int) int) int {
	//不定义什么运算
	//通过函数参数传递我要进行运算
	rt := callback(n1, n2)
	if rt >= 0 && rt <= 100 {
		return rt
	}
	return -1
}

func main() {
	add := func(n1, n2 int) int {
		return n1 + n2
	}
	mult := func(n1, n2 int) int {
		return n1 * n2
	}
	rt := calc(1, 2, add)
	fmt.Println(rt)
	rt = calc(1, 2, mult)
	fmt.Println(rt)
	rt = calc(50, 30, add)
	fmt.Println(rt)
}


示例2 直接引入
package main

import "fmt"

func calc(n1 int, n2 int, callback func(int, int) int) int {
	//不定义什么运算
	//通过函数参数传递我要进行运算
	rt := callback(n1, n2)
	if rt >= 0 && rt <= 100 {
		return rt
	}
	return -1
}

func main() {
	// add := func(n1, n2 int) int {
	// 	return n1 + n2
	// }
	// mult := func(n1, n2 int) int {
	// 	return n1 * n2
	// }
	// rt := calc(1, 2, add)
	// fmt.Println(rt)
	// rt = calc(1, 2, mult)
	// fmt.Println(rt)
	// rt = calc(50, 30, add)
	// fmt.Println(rt)

	rt := calc(50, 30, func(n1, n2 int) int {
		return n1 + n2
	})
	fmt.Println(rt)
	rt = calc(50, 30, func(n1, n2 int) int {
		return n1 * n2
	})
	fmt.Println(rt)
}
/*
D:\GoWork\src\go_course\day03-20230306>go run lambda.go
80
-1
*/

示例3 局部初始化
package main

import "fmt"

func main() {
	func() {
		fmt.Println("call")
	}()
	fmt.Println("1")
}
/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run lambda2.go
call
1
*/

匿名函数中作用域

函数fun(name string) 内没有声明desc 使用外部的,做修改了

示例1
package main

import "fmt"

func main() {
	name, desc := "xx", "i'm xx"
	func(name string) {
		fmt.Println(name, desc)
	}("aa")
	fmt.Println(name)
}
/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run block.go
aa i'm xx
xx
*/

示例2
package main

import "fmt"

func main() {
	name, desc := "xx", "i'm xx"
	func(name string) {
		fmt.Println(name, desc)
		name, desc = "bb", "cc"
		fmt.Println(name, desc)
	}("aa")
	fmt.Println(name, desc)
}

示例3 作用域 中声明
package main

import "fmt"

func main() {
	name, desc := "xx", "i'm xx"
	func(name string) {
		fmt.Println(name, desc)
		name, desc := "bb", "cc"
		fmt.Println(name, desc)
	}("aa")
	fmt.Println(name, desc)
}
/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run block.go
aa i'm xx
bb cc
xx i'm xx
*/

高阶函数
函数作为返回值 - 闭包 close.go
示例1
package main

import "fmt"

func addBase(base int) func(int) int {
	fmt.Println(base)
	return func(n int) int {
		return n
	}
}

func main() {
	addBase(1)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run close.go
1
*/

示例2
package main

import "fmt"

func addBase(base int) func(int) int {
	fmt.Println(base)
	return func(n int) int {
		return n + base
	}
}

func main() {
	add1 := addBase(1)
	fmt.Println(add1(5))

	add10 := addBase(10)
	fmt.Println(add10(3))
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run close.go
1
6
10
13
*/

匿名函数应用

sort.Slice
package main

import (
	"fmt"
	"sort"
)

func main() {
	// char => counter
	// A=>65
	// B=>66
	// C=>67
	// D=>68
	stats := [][]int{{'A', 3}, {'B', 2}, {'c', 1}, {'D', 2}}
	//使用出现的次数进行排序
	sort.Slice(stats, func(i, j int) bool {
		return stats[i][1] > stats[j][1]
	})
	fmt.Println(stats)
}


sort.SliceStable
package main

import (
	"fmt"
	"sort"
)

func main() {
	// char => counter
	// A=>65
	// B=>66
	// C=>67
	// D=>68
	stats := [][]int{{'A', 3}, {'B', 2}, {'c', 1}, {'D', 2}}
	//使用出现的次数进行排序
    // {B,2},{D,2}=> 稳定的
    // {D,2},{B,2}=> 不稳定的
	sort.Slice(stats, func(i, j int) bool {
		return stats[i][1] > stats[j][1]
	})
	// sort.SliceStable(stats, func(i, j int) bool {
	// 	return stats[i][1] > stats[j][1]
	// })
	fmt.Println(stats)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run sort.go
[[65 3] [66 2] [68 2] [99 1]]
*/

sort.Search
package main

import (
	"fmt"
	"sort"
)

func main() {
	// char => counter
	// A=>65
	// B=>66
	// C=>67
	// D=>68
	stats := [][]int{{'A', 3}, {'B', 2}, {'c', 1}, {'D', 2}}
	//使用出现的次数进行排序
	sort.Slice(stats, func(i, j int) bool {
		return stats[i][1] > stats[j][1]
	})
	// sort.SliceStable(stats, func(i, j int) bool {
	// 	return stats[i][1] > stats[j][1]
	// })
	fmt.Println(stats)

	//升序 <=
	//降序 >=
	// 对stats升序排序<=,查询stats[i][1]是1的元素的索引 是3
	index := sort.Search(len(stats), func(i int) bool {
		return stats[i][1] <= 1
	})
	fmt.Println(index)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run sort.go
[[65 3] [66 2] [68 2] [99 1]]
3
*/


练习 todolist

// 做一个命令行的任务管理
// 用户管理

// 1 函数,输入&输出,符合数据结构
// 2 了解流程(对数据的操作流程,增、删、改、查)


// 1 任务的输入(添加任务)
// 2 任务列表(任务查询)
// 3 任务修改
// 4 任务删除
// 5 详情

// 任务
// ID,任务名称,开始时间,结束时间,状态,负责人
// ID,name,start_time,end_time,status,user
// []map[string][string]

示例1-新增功能

1 创建todos map切片
2 添加常量(任务名 ...)

任务名 开始、结束时间 状态 用户名 等

3 添加newTask函数
4 通过scan获取,append加入切片
package main

import "fmt"

var todos = make([]map[string]string, 0)

const (
	name      = "name"
	startTime = "start_time"
	endTime   = "end_time"
	status    = "status"
	user      = "user"
)

func newTask() map[string]string {
	task := make(map[string]string)
	task[name] = ""
	task[startTime] = ""
	task[endTime] = ""
	task[status] = "新创建"
	task[user] = ""
	return task
}

func main() {
	var text string
	task := newTask()
	task[endTime] = ""
	task[status] = "新创建"

	fmt.Println("请输入任务信息:")
	fmt.Print("任务名:")
	fmt.Scan(&text)
	task[name] = text

	fmt.Print("开始时间:")
	fmt.Scan(&text)
	task[startTime] = text

	fmt.Print("负责人:")
	fmt.Scan(&text)
	task[user] = text

	todos = append(todos, task)
	fmt.Println(todos)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306\todolist>go run add.go
请输入任务信息:
任务名:todo01
开始时间:19:00
负责人:tt
[map[end_time: name:todo01 start_time:19:00 status:新创建 user:tt]]
*/

示例1-新增扩展

1 添加数据到todos map切片
package main

import (
	"fmt"
	"strconv"
)

// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}


2 添加常量(id 完成 ...)

​ 完成、未完成、id等字段

package main

import (
	"fmt"
	"strconv"
)

// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}

const (
	statusNew      = "未完成"
	statusComplete = "完成"
)

const (
	id        = "id"
	name      = "name"
	startTime = "start_time"
	endTime   = "end_time"
	status    = "status"
	user      = "user"
)

3 添加genId函数

字符串转换为int

todoId, _ := strconv.Atoi(todo["id"])

func genId() int {
	var rt int
	for _, todo := range todos {
		todoId, _ := strconv.Atoi(todo["id"])
		if rt < todoId {
			rt = todoId
		}
	}
	return rt + 1
}

4 函数newTask添加task[id]
func newTask() map[string]string {
	//id生成(用todos中最大的ID+1)
	task := make(map[string]string)
	task[id] = strconv.Itoa(genId())
	task[name] = ""
	task[startTime] = ""
	task[endTime] = ""
	task[status] = "新创建"
	task[user] = ""
	return task
}

5 新增功能测试
package main

import (
	"fmt"
	"strconv"
)

// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}

const (
	statusNew      = "未完成"
	statusComplete = "完成"
)

const (
	id        = "id"
	name      = "name"
	startTime = "start_time"
	endTime   = "end_time"
	status    = "status"
	user      = "user"
)

func genId() int {
	var rt int
	for _, todo := range todos {
		todoId, _ := strconv.Atoi(todo["id"])
		if rt < todoId {
			rt = todoId
		}
	}
	return rt + 1
}

func newTask() map[string]string {
	//id生成(用todos中最大的ID+1)
	task := make(map[string]string)
	task[id] = strconv.Itoa(genId())
	task[name] = ""
	task[startTime] = ""
	task[endTime] = ""
	task[status] = "新创建"
	task[user] = ""
	return task
}

func main() {
	var text string
	task := newTask()
	task[endTime] = ""
	task[status] = "新创建"

	fmt.Println("请输入任务信息:")
	fmt.Print("任务名:")
	fmt.Scan(&text)
	task[name] = text

	fmt.Print("开始时间:")
	fmt.Scan(&text)
	task[startTime] = text

	fmt.Print("负责人:")
	fmt.Scan(&text)
	task[user] = text

	todos = append(todos, task)
	fmt.Println(todos)
}


/*打印结果
D:\GoWork\src\go_course\day03-20230306\todolist>go run add.go
请输入任务信息:
任务名:做饭
开始时间:19:00
负责人:xx
[map[end_time: id:1 name:陪孩子散步 start_time:18:00 status:未完成 user:xx] map[end_time: id:2 name:备课 start_time:21:00 status:未完成 user:xx] map[end_time: id:4 name:复习 start_time:09:00 status:未完成 user:xx] map[end_time: id:5 name:做饭 start_time:19:00 status:新创建 user:xx]]
*/


示例2 查询功能 query.go

1 补充数据到todos map切片
// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "5", "name": "准备上课", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "6", "name": "课堂笔记", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}

2 添加打印函数(分割符strings.Repeat)
func printTask(task map[string]string) {
	fmt.Println(strings.Repeat("-", 20))
	fmt.Println("ID", task[id])
	fmt.Println("任务名:", task[name])
	fmt.Println("开始时间:", task[startTime])
	fmt.Println("完成时间:", task[endTime])
}

3 查询todo[name]字段,包含某个字符串
func main() {
	var text string
	fmt.Print("请输入查询信息:")
	fmt.Scan(&text)
	for _, todo := range todos {
		if strings.Contains(todo[name], text) {
			printTask(todo)
		}
	}
}

4 查询功能测试
package main

import (
	"fmt"
	"strings"
)

// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "5", "name": "准备上课", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "6", "name": "课堂笔记", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}

const (
	statusNew      = "未完成"
	statusComplete = "完成"
)

const (
	id        = "id"
	name      = "name"
	startTime = "start_time"
	endTime   = "end_time"
	status    = "status"
	user      = "user"
)

func printTask(task map[string]string) {
	fmt.Println(strings.Repeat("-", 20))
	fmt.Println("ID", task[id])
	fmt.Println("任务名:", task[name])
	fmt.Println("开始时间:", task[startTime])
	fmt.Println("完成时间:", task[endTime])
}

func main() {
	var text string
	fmt.Print("请输入查询信息:")
	fmt.Scan(&text)
	for _, todo := range todos {
		if strings.Contains(todo[name], text) {
			printTask(todo)
		}
	}
}


/*打印结果
D:\GoWork\src\go_course\day03-20230306\todolist>go run query.go
请输入查询信息:课
--------------------
ID 2
任务名: 备课
开始时间: 21:00
完成时间:
--------------------
ID 5
任务名: 准备上课
开始时间: 09:00
完成时间:
--------------------
ID 6
任务名: 课堂笔记
开始时间: 09:00
完成时间:
*/

示例3 todolist.go

1 复制代码到todolist.go
共有部分:
	复制todos变量,复制常量,
add.go部分:
	复制genId函数,复制newTask函数 
query.go部分:
	复制printTask函数

// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "5", "name": "准备上课", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "6", "name": "课堂笔记", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}

const (
	statusNew      = "未完成"
	statusComplete = "完成"
)

const (
	id        = "id"
	name      = "name"
	startTime = "start_time"
	endTime   = "end_time"
	status    = "status"
	user      = "user"
)

func genId() int {
	var rt int
	for _, todo := range todos {
		todoId, _ := strconv.Atoi(todo["id"])
		if rt < todoId {
			rt = todoId
		}
	}
	return rt + 1
}

func newTask() map[string]string {
	//id生成(用todos中最大的ID+1)
	task := make(map[string]string)
	task[id] = strconv.Itoa(genId())
	task[name] = ""
	task[startTime] = ""
	task[endTime] = ""
	task[status] = "新创建"
	task[user] = ""
	return task
}

func printTask(task map[string]string) {
	fmt.Println(strings.Repeat("-", 20))
	fmt.Println("ID", task[id])
	fmt.Println("任务名:", task[name])
	fmt.Println("开始时间:", task[startTime])
	fmt.Println("完成时间:", task[endTime])
}

2 新增for循环
选择功能 if else
func main() {
	for {
		fmt.Print("请输入操作(add/query/..../):")
		var text string
		fmt.Scan(&text)

		if text == "add" {
		} else if text == "query" {
		} else if text == "modify" {
		} else if text == "delete" {
		} else {
			fmt.Println("输入指令不正确")
		}
	}
}

改为switch case
func main() {
	for {
		fmt.Print("请输入操作(add/query/..../):")
		var text string
		fmt.Scan(&text)

		// if text == "add" {
		// } else if text == "query" {
		// } else if text == "modify" {
		// } else if text == "delete" {
		// } else {
		// 	fmt.Println("输入指令不正确")
		// }
		switch text {
		case "add":
		case "query":
		case "modify":
		case "delete":
		default:
			fmt.Println("输入指令错误")
		}
	}
}

3 完善for循环
添加任务代码
		case "add":
			var text string
			task := newTask()
			fmt.Println("请输入任务信息:")
			fmt.Print("任务名:")
			fmt.Scan(&text)
			task[name] = text

			fmt.Print("开始时间:")
			fmt.Scan(&text)
			task[startTime] = text

			fmt.Print("负责人:")
			fmt.Scan(&text)
			task[user] = text

			todos = append(todos, task)
			fmt.Println("创建任务成功")
		case "query":

查询任务代码
		case "query":
			var text string
			fmt.Print("请输入查询信息:")
			fmt.Scan(&text)
			for _, todo := range todos {
				if strings.Contains(todo[name], text) {
					printTask(todo)
				}
			}
		case "modify":

测试添加和查询
/*打印结果
D:\GoWork\src\go_course\day03-20230306\todolist>go run todolist.go
请输入操作(add/query/..../):add
请输入任务信息:
任务名:做饭
开始时间:15:00
负责人:xx
创建任务成功
请输入操作(add/query/..../):query
请输入查询信息:饭
--------------------
ID 7
任务名: 做饭
开始时间: 15:00
完成时间:
请输入操作(add/query/..../):
*/

添加退出功能

break跳出switch层,没有跳出for层,使用label退出。或者打印exit后return

func main() {
EXIT:
	for {
		fmt.Print("请输入操作(add/query/..../exit/):")
		var text string
		fmt.Scan(&text)

		switch text {
		case "add":
			/*......*/
		case "query":
			/*......*/
		case "modify":
		case "delete":
		case "exit":
			fmt.Println("exit")
			break EXIT
		default:
			fmt.Println("输入指令错误")
		}
	}
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306\todolist>go run todolist.go
请输入操作(add/query/..../):exit
exit

*/

第一阶段 完整代码

package main

import (
	"fmt"
	"strconv"
	"strings"
)

// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "5", "name": "准备上课", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "6", "name": "课堂笔记", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}

const (
	statusNew      = "未完成"
	statusComplete = "完成"
)

const (
	id        = "id"
	name      = "name"
	startTime = "start_time"
	endTime   = "end_time"
	status    = "status"
	user      = "user"
)

func genId() int {
	var rt int
	for _, todo := range todos {
		todoId, _ := strconv.Atoi(todo["id"])
		if rt < todoId {
			rt = todoId
		}
	}
	return rt + 1
}

func newTask() map[string]string {
	//id生成(用todos中最大的ID+1)
	task := make(map[string]string)
	task[id] = strconv.Itoa(genId())
	task[name] = ""
	task[startTime] = ""
	task[endTime] = ""
	task[status] = "新创建"
	task[user] = ""
	return task
}

func printTask(task map[string]string) {
	fmt.Println(strings.Repeat("-", 20))
	fmt.Println("ID", task[id])
	fmt.Println("任务名:", task[name])
	fmt.Println("开始时间:", task[startTime])
	fmt.Println("完成时间:", task[endTime])
}

func main() {

	for {
		fmt.Print("请输入操作(add/query/..../exit/):")
		var text string
		fmt.Scan(&text)

		// if text == "add" {
		// } else if text == "query" {
		// } else if text == "modify" {
		// } else if text == "delete" {
		// } else {
		// 	fmt.Println("输入指令不正确")
		// }
		switch text {
		case "add":
			var text string
			task := newTask()
			fmt.Println("请输入任务信息:")
			fmt.Print("任务名:")
			fmt.Scan(&text)
			task[name] = text

			fmt.Print("开始时间:")
			fmt.Scan(&text)
			task[startTime] = text

			fmt.Print("负责人:")
			fmt.Scan(&text)
			task[user] = text

			todos = append(todos, task)
			fmt.Println("创建任务成功")
		case "query":
			var text string
			fmt.Print("请输入查询信息:")
			fmt.Scan(&text)
			for _, todo := range todos {
				if strings.Contains(todo[name], text) {
					printTask(todo)
				}
			}
		case "modify":
		case "delete":
		case "exit":
			fmt.Println("exit")
			// break EXIT
			return
		default:
			fmt.Println("输入指令错误")
		}
	}
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306\todolist>go run todolist.go
请输入操作(add/query/..../exit/):add 
请输入任务信息:
任务名:上课
开始时间:09:00
负责人:xx
创建任务成功
请输入操作(add/query/..../exit/):query
请输入查询信息:课
--------------------
ID 2
任务名: 备课
开始时间: 21:00
完成时间:
--------------------
ID 5
任务名: 准备上课
开始时间: 09:00
完成时间:
--------------------
ID 6
任务名: 课堂笔记
开始时间: 09:00
完成时间:
--------------------
ID 7
任务名: 上课
开始时间: 09:00
完成时间:
请输入操作(add/query/..../exit/):exit
exit
*/

代码抽象为函数
func add() {
	var text string
	task := newTask()
	fmt.Println("请输入任务信息:")
	fmt.Print("任务名:")
	fmt.Scan(&text)
	task[name] = text

	fmt.Print("开始时间:")
	fmt.Scan(&text)
	task[startTime] = text

	fmt.Print("负责人:")
	fmt.Scan(&text)
	task[user] = text

	todos = append(todos, task)
	fmt.Println("创建任务成功")
}

func query() {
	var text string
	fmt.Print("请输入查询信息:")
	fmt.Scan(&text)
	for _, todo := range todos {
		if strings.Contains(todo[name], text) {
			printTask(todo)
		}
	}
}

//调用
...
		switch text {
		case "add":
			add()
		case "query":
			query()
		case "modify":
...

重复代码再提取input

重复部分:声明text 打印操作信息,scan接收变量指针,返回text内容赋值

func input(prompt string) string {
	var text string
	fmt.Print(prompt)
	fmt.Scan(&text)
	return strings.TrimSpace(text)
}

package main

import (
	"fmt"
	"strconv"
	"strings"
)

// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "5", "name": "准备上课", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "6", "name": "课堂笔记", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}

const (
	statusNew      = "未完成"
	statusComplete = "完成"
)

const (
	id        = "id"
	name      = "name"
	startTime = "start_time"
	endTime   = "end_time"
	status    = "status"
	user      = "user"
)

func input(prompt string) string {
	var text string
	fmt.Print(prompt)
	fmt.Scan(&text)
	return strings.TrimSpace(text)
}

func genId() int {
	var rt int
	for _, todo := range todos {
		todoId, _ := strconv.Atoi(todo["id"])
		if rt < todoId {
			rt = todoId
		}
	}
	return rt + 1
}

func newTask() map[string]string {
	//id生成(用todos中最大的ID+1)
	task := make(map[string]string)
	task[id] = strconv.Itoa(genId())
	task[name] = ""
	task[startTime] = ""
	task[endTime] = ""
	task[status] = "新创建"
	task[user] = ""
	return task
}

func printTask(task map[string]string) {
	fmt.Println(strings.Repeat("-", 20))
	fmt.Println("ID", task[id])
	fmt.Println("任务名:", task[name])
	fmt.Println("开始时间:", task[startTime])
	fmt.Println("完成时间:", task[endTime])
}

func add() {
	//var text string
	task := newTask()
	fmt.Println("请输入任务信息:")
	// fmt.Print("任务名:")
	// fmt.Scan(&text)
	// task[name] = text
	task[name] = input("任务名:")

	// fmt.Print("开始时间:")
	// fmt.Scan(&text)
	// task[startTime] = text
	task[startTime] = input("开始时间:")

	// fmt.Print("负责人:")
	// fmt.Scan(&text)
	// task[user] = text
	task[user] = input("负责人:")

	todos = append(todos, task)
	fmt.Println("创建任务成功")
}

func query() {
	// var text string
	// fmt.Print("请输入查询信息:")
	// fmt.Scan(&text)
	q := input("请输入查询信息:")

	for _, todo := range todos {
		// if strings.Contains(todo[name], text) {
		if strings.Contains(todo[name], q) {
			printTask(todo)
		}
	}
}

func main() {

	for {
		// fmt.Print("请输入操作(add/query/..../exit/):")
		// var text string
		// fmt.Scan(&text)
		text := input("请输入操作(add/query/..../exit/):")

		// if text == "add" {
		// } else if text == "query" {
		// } else if text == "modify" {
		// } else if text == "delete" {
		// } else {
		// 	fmt.Println("输入指令不正确")
		// }
		switch text {
		case "add":
			add()
		case "query":
			query()
		case "modify":
		case "delete":
		case "exit":
			fmt.Println("exit")
			// break EXIT
			return
		default:
			fmt.Println("输入指令错误")
		}
	}
}

省略变量,再提取
package main

import (
	"fmt"
	"strconv"
	"strings"
)

// var todos = make([]map[string]string, 0)
var todos = []map[string]string{
	{"id": "1", "name": "陪孩子散步", "start_time": "18:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "2", "name": "备课", "start_time": "21:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "4", "name": "复习", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "5", "name": "准备上课", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
	{"id": "6", "name": "课堂笔记", "start_time": "09:00", "end_time": "", "status": statusNew, "user": "xx"},
}

const (
	statusNew      = "未完成"
	statusComplete = "完成"
)

const (
	id        = "id"
	name      = "name"
	startTime = "start_time"
	endTime   = "end_time"
	status    = "status"
	user      = "user"
)

func input(prompt string) string {
	var text string
	fmt.Print(prompt)
	fmt.Scan(&text)
	return strings.TrimSpace(text)
}

func genId() int {
	var rt int
	for _, todo := range todos {
		todoId, _ := strconv.Atoi(todo["id"])
		if rt < todoId {
			rt = todoId
		}
	}
	return rt + 1
}

func newTask() map[string]string {
	//id生成(用todos中最大的ID+1)
	task := make(map[string]string)
	task[id] = strconv.Itoa(genId())
	task[name] = ""
	task[startTime] = ""
	task[endTime] = ""
	task[status] = "新创建"
	task[user] = ""
	return task
}

func printTask(task map[string]string) {
	fmt.Println(strings.Repeat("-", 20))
	fmt.Println("ID", task[id])
	fmt.Println("任务名:", task[name])
	fmt.Println("开始时间:", task[startTime])
	fmt.Println("完成时间:", task[endTime])
}

func add() {
	task := newTask()
	fmt.Println("请输入任务信息:")
	task[name] = input("任务名:")
	task[startTime] = input("开始时间:")
	task[user] = input("负责人:")

	todos = append(todos, task)
	fmt.Println("创建任务成功")
}

func query() {
	//q := input("请输入查询信息:")

	for _, todo := range todos {
        //if strings.Contains(todo[name], q) {
		if strings.Contains(todo[name], input("请输入查询信息:")) {
			printTask(todo)
		}
	}
}

func main() {

	for {
		//text := input("请输入操作(add/query/..../exit/):")

		//switch text {
   		switch input("请输入操作(add/query/..../exit/):") {
		case "add":
			add()
		case "query":
			query()
		case "modify":
		case "delete":
		case "exit":
			fmt.Println("exit")
			return
		default:
			fmt.Println("输入指令错误")
		}
	}
}

第二阶段 重构v2

func main() {

	methods := map[string]func(){
		"add":   add,
		"query": query,
	}

	for {
		text := input("请输入操作(add/query/..../exit/):")

		// switch text {
		// case "add":
		// 	add()
		// case "query":
		// 	query()
		// case "modify":
		// case "delete":
		// case "exit":
		// 	fmt.Println("exit")
		// 	return
		// default:
		// 	fmt.Println("输入指令错误")
		// }
		if text == "exit" {
			break
		}
		method, ok := methods[text]
		if ok {
			method()
		} else {
			fmt.Println("输入指令不正确")
		}
	}
}

改写为1行
func main() {

	methods := map[string]func(){
		"add":   add,
		"query": query,
	}

	for {
		text := input("请输入操作(add/query/..../exit/):")

		if text == "exit" {
			break
		}

		if method, ok := methods[text]; ok {
			method()
		} else {
			fmt.Println("输入指令不正确")
		}
	}
}

作业

1 知识整理
2 我有一个梦想 中出现次数最多的top 10 字符集出现次数
3 统计
	a 每个IP出现次数
	b 每个状态码出现次数
	c 每个IP在每个URL上产生的流量
	
int[][4]string{
   // ip url 状态码 字节大小
   {"1.1.1.1","/index.html","200","1000"},
   {"1.1.1.2","/index.html","200","10000"},
   {"1.1.1.1","/index.html","200","10000"}
}

key:map 必须是可以使用==进行比较的数据类型
key 数据类型,ip+url =>string key
	[]string{ip,url}
	[2]string{ip,url}
4 todo管理
	a 编辑
		请输入编辑的ID
		通过ID查找=>Task =>显示
		用户确认是否进行编辑(y/yes):编辑
		用户输入:任务名称,开始时间,状态
		//状态如果是已完成,初始化完成时间
		//time.Now().Format("2006-01-02 15:04:05")
	b删除
		请输入编辑的ID
		通过ID查找 =>Task =>显示
		用户确认是否进行删除(y/yes):删除
	c数据验证(用户输入数据检查)
		任务名称:不能重复(新增,编辑)
		编辑:
			a,任务名称不变
			b. 任务名称改成其他已存在的
		任务状态:
			新创建,开始执行,已完成,暂停
			

错误处理

package main

import (
	"errors"
	"fmt"
	"strconv"
)

func div(n1, n2 int) (int, error) {
	if n2 == 0 {
		return -1, errors.New("除数为0")
	}
	return n1 / n2, nil
}

func main() {
	value, err := strconv.Atoi("xxx")
	fmt.Printf("%T\n", err)
	fmt.Println(err)
	fmt.Println(value)

	e := fmt.Errorf("自定义错误")
	fmt.Printf("%T %#v\n", e, e)

	e2 := errors.New("自定义错误2")
	fmt.Printf("%T %#v\n", e2, e2)

	//go语言
	//希望程序内部如果有错误
	//通过最后一个返回值显示返回给调用者
	//由调用者决定如何处理
	if rt, err := div(1, 0); err == nil {
		fmt.Println(rt)
	} else {
		fmt.Println(err)
	}
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run error.go
*strconv.NumError
strconv.Atoi: parsing "xxx": invalid syntax
0
*errors.errorString &errors.errorString{s:"自定义错误"}
*errors.errorString &errors.errorString{s:"自定义错误2"}
除数为0
*/

延迟声明main()函数中 defer

package main

import "fmt"

func main() {
	//defer 函数调用
	// 延迟执行,在函数退出之前
	defer func() {
		fmt.Println("defer")
	}()
	defer func() {
		fmt.Println("defer A")
	}()
	defer func() {
		fmt.Println("defer B")
	}()
	fmt.Println("main")
}


延迟声明test()函数中 defer

package main

import "fmt"

func test() string {
	//defer 函数调用
	// 延迟执行,在函数退出之前
	defer func() {
		fmt.Println("defer")
	}()
	defer func() {
		fmt.Println("defer A")
	}()
	defer func() {
		fmt.Println("defer B")
	}()
	fmt.Println("test")
	return "test--"
}

func main() {
	fmt.Println(test())
}
/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run defer.go
test
defer B
defer A
defer
test--
*/

延迟声明defer中不要修改返回值

package main

import "fmt"

func test() (rt string) {
	//defer 函数调用
	// 延迟执行,在函数退出之前
	defer func() {
		fmt.Println("defer")
		rt = "defer"
	}()
	defer func() {
		fmt.Println("defer A")
	}()
	defer func() {
		fmt.Println("defer B")
	}()
	fmt.Println("test")
	rt = "test--"
	return
}

func main() {
	fmt.Println(test())
}
/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run defer.go
test
defer B
defer A
defer
defer
*/

defer使用

package main

import "fmt"

func test() (rt string) {
	//defer 函数调用
	// 延迟执行,在函数退出之前
	defer func() {
		fmt.Println("defer")
		rt = "defer"
	}()
	defer func() {
		fmt.Println("defer A")
	}()
	defer func() {
		fmt.Println("defer B")
	}()
	fmt.Println("test")
	rt = "test--"
	return
}

func test2(n1, n2 int) {
	defer func() {
		//函数体内不管是否发生错误,都会执行
		fmt.Println("test2 defer")
	}()
	fmt.Println("before")
	fmt.Println(n1 / n2)
	fmt.Println("after")
}

func main() {
	fmt.Println(test())
	test2(1, 0)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run defer.go
test
defer B
defer A
defer
defer
before
test2 defer
panic: runtime error: integer divide by zero

goroutine 1 [running]:
main.test2(0x1, 0x0)
        D:/GoWork/src/go_course/day03-20230306/defer.go:29 +0x146
main.main()
        D:/GoWork/src/go_course/day03-20230306/defer.go:35 +0x65
exit status 2
*/

defer在for循环中使用 forerror.go
package main

import "fmt"

func main() {
	for i := 0; i < 3; i++ {
		fmt.Println("for before", i)
		//打开文件
		//延迟关闭
		//处理(处理出现错误)
		defer func() {
			fmt.Println("defer", i)
		}()
		fmt.Println("for after", i)
	}
	fmt.Println("main")
}

D:\GoWork\src\go_course\day03-20230306>go run forerror.go
for before 0
for after 0
for before 1
for after 1
for before 2
for after 2
main
defer 3
defer 3
defer 3

处理

在for循环中defer ,导致for循环一直使用defer 函数没有退出,一直没有释放defer

处理:单独添加一个func函数,在函数中defer

package main

import "fmt"

func main() {
	for i := 0; i < 3; i++ {
		func (){
			//打开文件
			//延迟关闭
         	 //   defer 
			//处理
		}()
		fmt.Println("for before", i)
		defer func() {
			fmt.Println("defer", i)
		}()
		fmt.Println("for after", i)
	}
	fmt.Println("main")
}


使用赋值1
package main

import "fmt"

func main() {
	for i := 0; i < 3; i++ {
		a := i
		fmt.Println("for before", i)
		defer func() {
			fmt.Println("defer", a)
		}()
		fmt.Println("for after", i)
	}
	fmt.Println("main")
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run forerror.go
for before 0
for after 0
for before 1
for after 1
for before 2
for after 2
main
defer 2
defer 1
defer 0
*/

使用局部定义的i
package main

import "fmt"

func main() {
	for i := 0; i < 3; i++ {

		fmt.Println("for before", i)
		defer func(i int) {
			fmt.Println("defer", i)
		}(i)
		fmt.Println("for after", i)
	}
	fmt.Println("main")
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run forerror.go
for before 0
for after 0
for before 1
for after 1
for before 2
for after 2
main
defer 2
defer 1
defer 0
*/

panic

package main

import "fmt"

func test() {
	fmt.Println("before")
	panic("自定义panic")
	fmt.Println("after")
}

func main() {
	test()
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run panic.go
before
panic: 自定义panic

goroutine 1 [running]:
main.test()
        D:/GoWork/src/go_course/day03-20230306/panic.go:7 +0x65
main.main()
        D:/GoWork/src/go_course/day03-20230306/panic.go:12 +0x17
exit status 2
*/

defer在panic前
package main

import "fmt"

func test() {
	defer func() {
		fmt.Println("defer")
	}()
	fmt.Println("before")
	panic("自定义panic")
	fmt.Println("after")
}

func main() {
	test()
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run panic.go
before
defer
panic: 自定义panic

goroutine 1 [running]:
main.test()
        D:/GoWork/src/go_course/day03-20230306/panic.go:10 +0x8b
main.main()
        D:/GoWork/src/go_course/day03-20230306/panic.go:15 +0x17
exit status 2
*/

使用recover并打印类型

package main

import "fmt"

func test() {
	// recover 必须在延迟执行函数内
	defer func() {
		fmt.Println("defer")
		err := recover()
		//打印类型
		fmt.Printf("%T,%#v\n", err, err)
	}()
	fmt.Println("before")
	panic("自定义panic")
	fmt.Println("after")
}

func main() {
	fmt.Println("before main")
	test()
	fmt.Println("after main")
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run panic.go
before main
before
defer
string,"自定义panic"
after main
*/

没有发生panic,仍然执行recover
package main

import "fmt"

func test() {
	// recover 必须在延迟执行函数内
	defer func() {
		fmt.Println("defer")
		err := recover()
		//打印类型
		fmt.Printf("%T,%#v\n", err, err)
	}()
	fmt.Println("before")
	// panic("自定义panic")
	fmt.Println("after")
}

func main() {
	fmt.Println("before main")
	test()
	fmt.Println("after main")
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run panic.go
before main
before
after
defer
<nil>,<nil>
after main
*/

修改增加判断
package main

import "fmt"

func test() {
	// recover 必须在延迟执行函数内
	defer func() {
		fmt.Println("defer")
		//打印类型
		if err := recover(); err != nil {
			fmt.Printf("%T,%#v\n", err, err)
		}
	}()
	fmt.Println("before")
	// panic("自定义panic")
	fmt.Println("after")
}

func main() {
	fmt.Println("before main")
	test()
	fmt.Println("after main")
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run panic.go
before main
before
after
defer
after main
*/

返回值,接收err返回
package main

import "fmt"

func test() (err error) {
	// recover 必须在延迟执行函数内
	defer func() {
		fmt.Println("defer")
		//打印类型
		if panicErr := recover(); panicErr != nil {
			err = fmt.Errorf("%s", panicErr)
		}
	}()
	fmt.Println("before")
	panic("自定义panic")
	fmt.Println("after")
	return err
}

func main() {
	fmt.Println("before main")
	err := test()
	fmt.Println("after main", err)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run panic.go
before main
before
defer
after main 自定义panic
*/

errors.New()
package main

import (
	"errors"
	"fmt"
)

func test() (err error) {
	// recover 必须在延迟执行函数内
	defer func() {
		fmt.Println("defer")
		//打印类型
		if panicErr := recover(); panicErr != nil {
			err = fmt.Errorf("%s", panicErr)
		}
	}()
	fmt.Println("before")
	// panic("自定义panic")
	err = errors.New("xxx")
    //检查所有的数据,连接,资源。。。
    //用别人的库的时候,panic
	fmt.Println("after")
	return err
}

func main() {
	fmt.Println("before main")
	err := test()
	fmt.Println("after main", err)
}

/*打印结果
D:\GoWork\src\go_course\day03-20230306>go run panic.go
before main
before
after
defer
after main xxx
*/

了解gopath

//D:\GoWork\src\go_course\day03-20230306\main\main.go
package main

import "fmt"

var mainVar = "man Var"

func mainFunc() {
	fmt.Println("main func")
}

func main() {
	mainFunc()
	utilsFunc()
	fmt.Println(mainVar)
	fmt.Println(utilsVar)
}
//D:\GoWork\src\go_course\day03-20230306\main\utils.go
package main

import "fmt"

var utilsVar = "utils Var"

func utilsFunc() {
	fmt.Println("utils Func")
}


/*打印结果
1 关闭set GO111MODULE=off
2 D:\GoWork\src\go_course\day03-20230306\main>go build 
3 D:\GoWork\src\go_course\day03-20230306\main>main.exe
main func
utils Func
man Var
utils Var
*/

// GO PATH项目
// GOPATH GOMODULE
// GO包
// 1.同一个文件夹下所有go文件的包名,必须一致
// 2. 关闭了 GOMODULE
// GOPATH在项目目录直接运行go build无文件名
// 将当前文件夹下的所有go文件进行编译
// 3. main包编译为可执行程序
// 4. main包中只能有一个main函数

// GOPATH 环境变量信息,定义多个目录
// src ==> 源文件
// pkg ==> 程序编译的包文件
// bin ==> 程序编译的可执行文件

测试使用
go build test
go install test
/*路径结构
D:\GoWork\src\go_course\day03-20230306\main\bin\
D:\GoWork\src\go_course\day03-20230306\main\pkg\
D:\GoWork\src\go_course\day03-20230306\main\src\test\main.go
D:\GoWork\src\go_course\day03-20230306\main\src\test\test.go
*/

/*执行结果
D:\GoWork\src\go_course\day03-20230306\main>set GOPATH=D:\GoWork\src\go_course\day03-20230306\main;%GOPATH%  
D:\GoWork\src\go_course\day03-20230306\main>echo %GOPATH%
D:\GoWork\src\go_course\day03-20230306\main;D:\GoWork
D:\GoWork\src\go_course\day03-20230306\main>cd src
D:\GoWork\src\go_course\day03-20230306\main\src>ls -la
total 0
drwxr-xr-x 1 zhu 197121 0  3月 12 16:25 .
drwxr-xr-x 1 zhu 197121 0  3月 12 16:25 ..
drwxr-xr-x 1 zhu 197121 0  3月 12 16:25 test
D:\GoWork\src\go_course\day03-20230306\main\src>go build test
D:\GoWork\src\go_course\day03-20230306\main\src>test.exe
main func
utils Func
man Var
utils Var
*/

/*执行 go install test 相当于生成test.go 后拷贝到bin目录下
D:\GoWork\src\go_course\day03-20230306\main\src>go install test
*/


go install pkg
package pkg

var utilsVar = "utils Var"

/*打印结果
文件及目录:
D:\GoWork\src\go_course\day03-20230306\main\src\pkg\utils.go
执行:
D:\GoWork\src\go_course\day03-20230306\main\src>go install pkg
D:\GoWork\src\go_course\day03-20230306\main\src>

使用 go install pkg 会在pkg下生成pkg.a文件
D:\GoWork\src\go_course\day03-20230306\main\pkg\windows_amd64\pkg.a
*/

注意 包内和包外 函数名大小写问题