记录一下之前的Go学习笔记。
1. switch
1package main
2
3import (
4 "fmt"
5 "os"
6)
7
8//从命令输入参数,在switch中进行处理
9
10func main() {
11 //C: argc , **argv
12 //Go: os.Args ==> 直接可以获取命令输入,是一个字符串切片 []string
13 cmds := os.Args
14
15 //os.Args[0] ==> 程序名字
16 //os.Args[1] ==> 第一个参数 ,以此类推
17 for key, cmd := range cmds {
18 fmt.Println("key:", key, ", cmd:", cmd, ", cmds len:", len(cmds))
19 }
20
21 if len(cmds) < 2 {
22 fmt.Println("请正确输入参数!")
23 return
24 }
25
26 switch cmds[1] {
27 case "hello":
28 fmt.Println("hello")
29 //go 的switch, 默认加上break了,不需要手动处理
30 //如果想向下穿透的话,那么需要加上关键字: fallthrough
31 fallthrough
32 case "world":
33 fmt.Println("world")
34 default:
35 fmt.Println("default called!")
36 }
37}
运行结果:
1key: 0 , cmd: C:\Users\Admin\AppData\Local\JetBrains\GoLand2025.1\tmp\GoLand\___go_build_main_go.exe , cmds len: 1
2请正确输入参数!
3
4Process finished with the exit code 0
2. 标签
1package main
2
3import "fmt"
4
5func main() {
6 //标签 LABEL1
7 //goto LABEL ===> 下次进入循环时,i不会保存之前的状态,重新从0开始计算,重新来过
8 //continue LABEL1 ===> continue会跳到指定的位置,但是会记录之前的状态,i变成1
9 //break LABEL1 ==> 直接跳出指定位置的循环
10
11 //标签的名字是自定义的,后面加上冒号
12LABEL121:
13 for i := 0; i < 5; i++ {
14 for j := 0; j < 5; j++ {
15 if j == 3 {
16 //goto LABEL1
17 //continue LABEL1
18 break LABEL121
19 //break
20 }
21
22 fmt.Println("i:", i, ",j:", j)
23 }
24 }
25
26 fmt.Println("over!")
27}
运行结果:
1i: 0 ,j: 0
2i: 0 ,j: 1
3i: 0 ,j: 2
4over!
3. 枚举const+iota
1package main
2
3import "fmt"
4
5//在go语言中没有枚举类型,但是我们可以使用const + iota(常量累加器)来进行模拟
6//模拟一个一周的枚举
7const (
8 MONDAY = iota //0
9 TUESDAY = iota //1
10 WEDNESDAY = iota //2
11 THURSDAY //3 ==> 没有赋值,默认与上一行相同iota ==> 3
12 FRIDAY //4
13 SATURDAY //5
14 SUNDAY //6
15 M, N = iota, iota //const属于预编译期赋值,所以不需要:=进行自动推导
16)
17
18const (
19 JANU = iota + 1 //1
20 FER //2
21 MAR //3
22 APRI //4
23)
24
25//1. iota是常量组计数器
26//2.iota从0开始,每换行递增1
27//3. 常量组有个特点如果不赋值,默认与上一行表达式相同
28//4.如果同一行出现两个iota,那么两个iota的值是相同的
29//5.每个常量组的iota是独立的,如果遇到const iota会重新清零
30
31func main() {
32
33 fmt.Println("打印周:")
34 fmt.Println(MONDAY)
35 fmt.Println(TUESDAY)
36 fmt.Println(WEDNESDAY)
37 fmt.Println(THURSDAY)
38 fmt.Println(FRIDAY)
39 fmt.Println("M:", M, ",N:", N)
40
41 fmt.Println("打印月份:")
42 fmt.Println(JANU) //1
43 fmt.Println(FER) //2
44 fmt.Println(MAR) //3
45
46 //var number int
47 //var name string
48 //var flag bool
49 //
50 //
51 ////可以使用变量组来将统一定义变量
52 //var (
53 // number int
54 // name string
55 // flag bool
56 //)
57
58}
运行结果:
1打印周:
20
31
42
53
64
7M: 7 ,N: 7
8打印月份:
91
102
113
12
13Process finished with the exit code 0
在goland中配置git shell,并且显示中文:
https://www.bbsmax.com/A/n2d9YvN6dD/
1我的安装路径D:\Program Files (x86)\Tools\Git\Git\etc)下bash.bashrc文件
2
3export LANG="zh_CN.UTF-8"
4export LC_ALL="zh_CN.UTF-8"
4. 结构体
在go语言中,使用结构体来模拟类
1package main
2
3import "fmt"
4
5//c语言里面,我们可以使用typedef int MyInt
6type MyInt int //type相当于typdef
7
8//C:
9//struct Person {
10//
11//}
12
13//go语言结构体使用type + struct来处理
14type Student struct {
15 name string
16 age int
17 gender string
18 score float64
19}
20
21func main() {
22 t1 := struct {
23 a int
24 }{
25 a : 100,
26 }
27
28 fmt.Println(t1)
29
30 var i, j MyInt
31 i, j = 10, 20
32
33 fmt.Println("i+j:", i+j)
34
35 //创建变量,并赋值
36 lily := Student{
37 name: "Lily",
38 age: 20,
39 gender: "女生",
40 //score: 80, //最后一个元素后面必须加上逗号,如果不加逗号则必须与}同一行
41 //}
42 score: 80} //最后一个元素后面必须加上逗号,如果不加逗号则必须与}同一行
43
44 //使用结构体各个字段
45 fmt.Println("lily:", lily.name, lily.age, lily.gender, lily.score)
46
47 //结构体没有-> 操作
48 s1 := &lily
49 fmt.Println("lily 使用指针s1.name打印:", s1.name, s1.age, s1.gender, s1.score)
50 fmt.Println("lily 使用指针(*s1).name打印:", (*s1).name, s1.age, s1.gender, s1.score)
51
52 //在定义期间对结构体赋值时,如果每个字段都赋值了,那么字段的名字可以省略不写
53 //如果只对局部变量赋值,那么必须明确指定变量名字
54 Duke := Student{
55 name: "Duke",
56 age: 28,
57 //"男生",
58 // 99,
59 }
60 Duke.gender = "男生"
61 Duke.score = 100
62
63 fmt.Println("Duke:", Duke)
64}
运行结果:
1{100}
2i+j: 30
3lily: Lily 20 女生 80
4lily 使用指针s1.name打印: Lily 20 女生 80
5lily 使用指针(*s1).name打印: Lily 20 女生 80
6Duke: {Duke 28 男生 100}
7
8Process finished with the exit code 0
5.init函数
C语言没有init函数,C语言一般需要自己去写init,然后在构造函数中调用
Go语言自带init函数,每一个包都可以包含一个或多个init函数
1package sub
2
3import "fmt"
4
5//0.这个init会在包被引用的时候(import)进行自动调用
6//1.init函数没有参数,没有返回值,原型固定如下
7//2.一个包中包含多个init时,调用顺序是不确定的(同一个包的多个文件中都可以有init)
8//3. init函数时不允许用户显示调用的
9//4. 有的时候引用一个包,可能只想使用这个包里面的init函数(mysql的init对驱动进行初始化)
10//但是不想使用这个包里面的其他函数,为了防止编译器报错,可以使用_形式来处理
11//import _ "xxx/xx/sub"
12func init() {
13 fmt.Println("this is first init() in package sub ==> sub.go")
14}
15
16func init() {
17 fmt.Println("this is second init() in package sub ==> sub.go ")
18}
19
20//在go语言中,同一层级目录,不允许出现多个包名
21func Sub(a, b int) int {
22 //init() ==> 不允许显示调用
23 test4() //由于test4与sub.go在同一个包下面,所以可以使用,并且不需要sub.形式
24 return a - b
25}
utils.go
1package sub
2
3//package utils //不允许出现多个包名
4
5import "fmt"
6
7func init() {
8 fmt.Println("this is init in sub utils.go")
9}
10
11func test4() {
12 fmt.Println("this is test4() in sub/utils!")
13}
main.go
1package main
2
3import (
4 _ "day02/05-init函数/sub" //此时,只会调用sub里面的init函数,编译还不会出错
5 //"fmt"
6)
7
8func main() {
9 //res := sub.Sub(10, 5)
10 //fmt.Println("sub.Sub(20,10) =", res)
11}
效果:
使用init场景,在配置文件管理器中写init,用于加载配置文件并解析:
1configManager {
2 //解析加载配置文件
3 //IP, PORT
4}
6.defer(延迟)
延迟,关键字,可以用于修饰语句,函数,确保这条语句可以在当前栈退出的时候执行
1lock.Lock()
2a = "hello"
3lock.Unlock() <=== 经常容易忘掉解锁
go语言可以使用defer来解决这个问题
1{
2 lock.Lock()
3 defer lock.Unlock() <=== 在当前栈退出的时候(例如:函数结束时)
4 a = "hello"
5}
6
7{
8 f1,_ := file.Open()
9 defer f1.Close()
10}
实例:
1package main
2
3import (
4 "fmt"
5 "os"
6)
7
8func main() {
9 //1.延迟,关键字,可以用于修饰语句,函数,确保这条语句可以在当前栈退出的时候执行
10 //2. 一般用于做资源清理工作
11 //3. 解锁、关闭文件
12 //4. 在同一个函数中多次调用defer,执行时类似于栈的机制:先后入后出
13
14 filename := "mail.go"
15 readFile(filename)
16}
17
18func readFile(filename string) {
19 //func Open(name string) (*File, error) {
20 //1. go语言一般会将错误码作为最后一个参数返回
21 //2. err一般nil代表没有错误,执行成功,非nil表示执行失败
22 f1, err := os.Open(filename)
23
24 //匿名函数,没有名字,属于一次性的逻辑 ==> lamada表达式
25 defer func(a int) {
26 fmt.Println("准备关闭文件, code:", a)
27 _ = f1.Close()
28 }(100) //创建一个匿名函数,同时调用
29
30 if err != nil {
31 fmt.Println("os.Open(\"mail.go\") ==> 打开文件失败, err:", err)
32 return
33 }
34
35 defer fmt.Println("0000000")
36 defer fmt.Println("1111111")
37 defer fmt.Println("2222222")
38
39 buf := make([]byte, 1024) //byte ==> char ==> uint8
40 //func (f *File) Read(b []byte) (n int, err error) {
41 n, _ := f1.Read(buf)
42 fmt.Println("读取文件的实际长度:", n)
43 fmt.Println("读取的文件内容:", string(buf)) ==> 类型转换
44
45}
运行结果:
1读取文件的实际长度: 1024
2读取的文件内容: package main
3
4import (
5 "fmt"
6 "os"
7)
8
9func main() {
10 //1.延迟,关键字,可以用于修饰语句,函数,确保这条语句可以在当前栈退出的时候执行
11 //2. 一般用于做资源清理工作
12 //3. 解锁、关闭文件
13 //4. 在同一个函数中多次调用defer,执行时类似于栈的机制:先后入后出
14
15 filename := "main.go"
16 readFile(filename)
17}
18
19func readFile(filename string) {
20 //func Open(name string) (*File, error) {
21 //1. go语言一般会将错误码作为最后一个参数返回
22 //2. err一般nil代表没有错误,执行成功,非nil表示执行失败
23 f1, err := os.Open(filename)
24
25 //匿名函数,没有名字,属于一次性的逻辑 ==> lamada表达式
26 defer func(a int) {
27 fmt.Println("准备关闭文件, code:", a)
28 _ = f1.Close()
29 }(100) //创建一个匿名函数,同时调用
30
31 if err != nil {
32 fmt.Println("os.Open(\"mail.go\") ==> 打开文件失败, err:", err)
33 return
34 }
35
36 defer fmt.Println("0000000")
37 defer fmt.Println("1111111")
38 defer fmt.Prin
392222222
401111111
410000000
42准备关闭文件, code: 100
43
44Process finished with the exit code 0