阶段1 Go语言基础Day03 函数错误处理
Posted 澐湮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阶段1 Go语言基础Day03 函数错误处理相关的知识,希望对你有一定的参考价值。
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 := []int1, 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
[]stringip,url
[2]stringip,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.errorStrings:"自定义错误"
*errors.errorString &errors.errorStrings:"自定义错误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
*/
注意 包内和包外 函数名大小写问题
Go语言开发Go语言错误处理
Go语言开发(七)、Go语言错误处理
一、defer延迟函数
1、defer延迟函数简介
defer在声明时不会立即执行,而是在函数return后,再按照FILO(先进后出)的原则依次执行每一个defer,一般用于异常处理、释放资源、清理数据、记录日志等。
每次defer语句执行时,defer修饰的函数的返回值和参数取值会照常进行计算和保存,但是defer修饰的函数不会执行。等到上一级函数返回前,会按照defer的声明顺序倒序执行全部defer的函数。defer所修饰函数的任何返回值都会被丢弃。
如果一个defer所修饰函数的值为nil,则defer的函数会在函数执行时panic(异常),而不会在defer语句执行时panic。defer所修饰函数的上一级函数即使抛出异常,defer所修饰函数也会被执行的,确保资源被合法释放。
defer延迟函数使用示例如下:
package main
import "fmt"
func deferTest(){
defer fmt.Println(1)
defer fmt.Println(2)
fmt.Println(3)
}
func main() {
deferTest()//3,2,1
}
2、defer延迟函数应用
A、简化资源回收
mu.Lock()
defer mu.Unlock()
defer?有一定的开销, 为了节省性能可以避免使用的defer?
B、捕获panic异常
Go语言中,panic用于抛出异常,,recover用于捕获异常。
recover只能在defer语句中使用,直接调用recover是无效的。
package main
import "fmt"
func deferRecover(){
defer func () {
if r := recover(); r != nil {
fmt.Println("recover")
}
}()
fmt.Println("exception will be happen")
panic("exception has happped.")
fmt.Println("return normally")
}
func main() {
deferRecover()
}
C、修改返回值
defer可以用于在?return?后修改函数的返回值。
package main
import "fmt"
func deferReturn(a,b int)(sum int){
defer func(){
sum += 100
}()
sum = a + b
return sum
}
func main() {
sum := deferReturn(1,6)
fmt.Println(sum)//107
}
D、安全回收资源
func set(mu *sync.Mutex, arr []int, i, v int) {
mu.Lock()
defer mu.Unlock()
arr[i] = v
}
如果运行时抛出切片越界异常,可以保证mu.Unlock()被调用。
二、错误处理
1、错误处理简介
Go语言通过内置的错误接口提供了简单的错误处理机制。
error类型是一个接口类型,定义如下:
type error interface {
Error() string}
Golang中引入error接口类型作为错误处理的标准模式,如果函数要返回错误,则返回值类型列表中肯定包含error。
2、错误处理使用
package main
import (
"fmt"
"errors"
)
//定义一个DivideError类型
type DivideError struct {
dividee int
divider int
}
//实现error接口
func (err *DivideError) Error() error{
strFormat := `Cannot proceed, the divider is zero.
dividee: %d
divider: 0`
return errors.New(fmt.Sprintf(strFormat, err.dividee))
}
//定义除法运算
func divide(vardividee int, vardivider int)(result int, errmsg error){
if vardivider == 0{
divideErr := DivideError{
dividee:vardividee,
divider:vardivider,
}
errmsg = divideErr.Error()
return 0,errmsg
}else{
return vardividee/vardivider,nil
}
}
func main() {
//正常情况
if result, err := divide(100, 10); err != nil{
fmt.Println(err)
}else{
fmt.Println("100/10 = ", result)
}
//当被除数为零的时候会返回错误信息
if _, errorMsg := divide(100, 0); errorMsg != nil{
fmt.Println(errorMsg)
}
}
三、异常处理
1、异常处理简介
Go使用panic()函数抛出异常,在defer语句中调用recover()函数捕获异常。
func panic(interface{})//接受任意类型参数 无返回值
func recover() interface{}//可以返回任意类型 无参数
panic()是一个内置函数,可以中断原有的控制流程,进入一个panic流程中。当函数F调用panic,函数F的执行被中断,但F中的延迟函数(必须是在panic前的已加载的defer)会正常执行,然后F函数逐层向上返回,直到发生panic的goroutine中所有调用的函数返回,此时程序退出。异常可以直接调用panic产生,也可以由运行时错误产生,例如访问越界的数组。
recover()是一个内置函数,可以让进入panic流程中的goroutine恢复过来。recover仅在延迟函数中有效。在正常的执行过程中,调用recover会返回nil,并且没有其它任何效果。如果当前的goroutine陷入panic,调用recover可以捕获到panic的输入值,并且恢复正常的执行。
一般情况下,recover()应该在一个使用defer关键字的函数中执行以有效截取错误处理流程。如果没有在发生异常的goroutine中明确调用恢复过程(使用recover关键字),会导致goroutine所属的进程打印异常信息后直接退出。
2、异常处理使用示例
package main
import (
"errors"
"fmt"
)
//定义一个DivideError类型
type DivideError struct {
dividee int
divider int
}
//实现error接口
func (err *DivideError) Error() error{
strFormat := `Cannot proceed, the divider is zero.
dividee: %d
divider: 0`
return errors.New(fmt.Sprintf(strFormat, err.dividee))
}
//定义除法运算
func divide(dividee int, divider int)(result int){
defer func() {
if r := recover();r != nil{
divideErr := DivideError{
dividee:dividee,
divider:divider,
}
fmt.Println(divideErr.Error())
}
}()
result = dividee/divider
return result
}
func main() {
a := divide(100,0)
fmt.Println(a)
}
以上是关于阶段1 Go语言基础Day03 函数错误处理的主要内容,如果未能解决你的问题,请参考以下文章