# go **Repository Path**: erictor_admin/go ## Basic Information - **Project Name**: go - **Description**: go 学习记录 - **Primary Language**: Go - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-07-20 - **Last Updated**: 2023-08-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # go学习记录 go国内代理更换: 环境变量: [华为开源镜像站_软件开发服务_华为云 (huaweicloud.com)](https://mirrors.huaweicloud.com/home) ![image-20230811114425044](./images/image-20230811114425044.png) ``` GoProxy配置如下: 使用前请确认本地golang为1.11及以上版本,且工程为go module工程 export GO111MODULE=on export GOPROXY=https://repo.huaweicloud.com/repository/goproxy/ export GONOSUMDB=* ``` windos配置: ![image-20230811114623834](./images/image-20230811114623834.png) ``` GOPROXY https://repo.huaweicloud.com/repository/goproxy/,dirrect ``` ## 1.基本变量与类型 **对应代码unit2文件夹下** ### 1.1 变量的四种写法 ``` package main import "fmt" func main(){ //第一种 var mun int = 18 fmt.Println("mun is: ",mun) //第二种,int为赋值时,默认0 var mun2 int fmt.Println(mun2) //第三种,未指定类型,根据赋值自动识别 var mun3 = 10 fmt.Println(mun3) //第四种.省略var 。注意 := 不能 = sex := "男" fmt.Println(sex) } ``` ### 1.2 多个声明与赋值 ``` package main import "fmt" func main(){ fmt.Println("----------------------------------") //声明多个变量 var n1,n2,n3 int fmt.Println(n1,n2,n3) //多个赋值,以“,”分割 var n4,name,n5 = 10,"eric",6.6 fmt.Println(n4,name,n5) n6,height := 6.9,172 fmt.Println(n6,height) } ``` ### 1.3 全局变量和局部变量 ``` package main import "fmt" //全局变量,分别声明 var n7 = 100 var n8 = 200 //一次性声明 var( n9 = 500 n10 = 800 ) func main(){ //局部变量 //第一种 var mun int = 18 fmt.Println("mun is: ",mun) //第二种,int为赋值时,默认0 var mun2 int fmt.Println(mun2) //第三种,未指定类型,根据赋值自动识别 var mun3 = 10 fmt.Println(mun3) //第四种.省略var 。注意 := 不能 = sex := "男" fmt.Println(sex) fmt.Println("----------------------------------") //声明多个变量 var n1,n2,n3 int fmt.Println(n1,n2,n3) //多个赋值,以“,”分割 var n4,name,n5 = 10,"eric",6.6 fmt.Println(n4,name,n5) n6,height := 6.9,172 fmt.Println(n6,height) //输出全局变量 fmt.Println(n7,n8) fmt.Println(n9,n10) } ``` ### 1.4 变量的数据类型 ![](./images/image-20230721105105947.png) ### 1.5 进制和进制转换 ![image-20230721105834197](./images/image-20230721105834197.png) ![image-20230721110514061](./images/image-20230721110514061.png) ![image-20230721110750965](./images/image-20230721110750965.png) 可以用系统的计算机用 ![image-20230721111238232](./images/image-20230721111238232.png) ### 1.6 整数类型 ![image-20230721140547941](./images/image-20230721140547941.png) ![image-20230721140756912](./images/image-20230721140756912.png) ![image-20230721140842525](./images/image-20230721140842525.png) ``` package main // import "fmt" // import "unsafe" import( "fmt" "unsafe" ) func main(){ //定义一个整数类型 var num1 int8 = 6 fmt.Println(num1) var num2 uint8 = 216 fmt.Println(num2) //printf格式化,打印类型至%T var num3 = 28 fmt.Printf("mum3的类型是: %T",num3) fmt.Println() // 打出占用字节数 fmt.Println(unsafe.Sizeof(num3)) } ``` ### 1.7 浮点类型 ![image-20230721141005925](./images/image-20230721141005925.png) ``` package main import( "fmt" ) func main(){ var num1 float32 = 3.14 fmt.Println(num1) var num2 float32 = -3.14 fmt.Println(num2) //科学计数法,E不区分大小写 var num3 float32 = 314E-2 fmt.Println(num3) var num4 float64 = 314e+2 fmt.Println(num4) //精度有损失,建议使用float64.默认也是 var num5 float32 = 134.222260009 fmt.Println(num5) var num6 float64 = 134.222260009 fmt.Println(num6) var num7 = 3.14 fmt.Printf("num7默认类型: %T",num7) } ``` ## 2.运算符 **对应代码unit3文件夹下** ![image-20230721142430964](./images/image-20230721142430964.png) ### 2.1 算术运算符 ​ ![image-20230721144125255](./images/image-20230721144125255.png) ``` package main import( "fmt" ) func main(){ // + 1.正数2.加法3.字符串拼接 var n1 int = +10 fmt.Println(n1) var n2 int = 2 + 10 fmt.Println(n2) var s1 string = "eric" + "." + "G" fmt.Println(s1) // 除号 fmt.Println(10/3) //int相除值为整数 fmt.Println(10.0/3) //float相除值为小数 // % 取模 等价 :a%b=a-a/b*b fmt.Println(10%3) //10-10/3*2 = 1 fmt.Println(-10%3) fmt.Println(10%-3) fmt.Println(-10%-3) // ++ 自增 +1 -- -1 var a int = 10 a++ fmt.Println(a) //go语言里 ++,-- 只能单独使用,不能参与运算中,只能在变量后面 } ``` ### 2.2 赋值运算符 ![image-20230721155304661](./images/image-20230721155304661.png) ``` package main // import "fmt" // import "unsafe" import( "fmt" ) func main(){ //定义一个整数类型 var num1 int8 = 6 fmt.Println(num1) var num2 int = (10 + 20) % 3 + 3 - 7 //右侧计算值赋值给左侧 fmt.Println(num2) var num3 int = 10 num3 += 20 //num3 = num3 + 20 fmt.Println(num3) //练习:交换两个数的值并输出结果 var a int = 8 var b int = 5 fmt.Printf("a = %v,b = %v",a,b) fmt.Println() //交换,引入中间变量 var t int t = a a = b b = t fmt.Printf("a = %v,b = %v",a,b) } ``` ### 2.3 关系运算符 ![image-20230721155403054](./images/image-20230721155403054.png) ``` package main import "fmt" func main(){ fmt.Println(5==9) fmt.Println(5!=9) fmt.Println(5>=9) fmt.Println(5<=9) fmt.Println(5>9) fmt.Println(5<9) } ``` ### 2.4 逻辑运算符 ![image-20230721155750765](./images/image-20230721155750765.png) ``` package main import "fmt" func main(){ //与: && 只要有一个false就为false,第一个false,后面不用算 fmt.Println(true&&true) fmt.Println(true&&false) fmt.Println(false&&true) fmt.Println(false&&false) //或: || 只要有一个true就为true,第一个true,后面不用算 fmt.Println(true&&true) fmt.Println(true&&false) fmt.Println(false&&true) fmt.Println(false&&false) //非: ! fmt.Println(!true) fmt.Println(!false) } ``` ### 2.5 其他运算符 ![image-20230721161117678](./images/image-20230721161117678.png) ``` package main import( "fmt" ) func main(){ //& 输出存储空间的地址 var age int = 18 fmt.Println("age对应的存储空间的地址为: ",&age) //age对应的存储空间的地址为: 0xc0000120a0 // *取对应的具体值 var ptr *int = &age fmt.Println(ptr) fmt.Println("ptr对应的具体值: ",*ptr) } ``` ## 3.流程控制 代码:unit4 ### 3.1 引入 ![image-20230724094110189](./images/image-20230724094110189.png) ### 3.2 if - 单分支 ![image-20230724094655333](./images/image-20230724094655333.png) ``` package main // import "fmt" // import "unsafe" import( "fmt" ) func main(){ //小于30,提示不足 //var count int = 20 //单分支 // if count < 30 { // fmt.Println("没有了") // } //在goling if后面可以并量加入定义 if count := 20;count < 30 { fmt.Println("没有了") } } ``` - 双分支 ![image-20230724100913242](./images/image-20230724100913242.png) 代码测试 ``` package main // import "fmt" // import "unsafe" import( "fmt" ) func main(){ //小于30,提示不足 //var count int = 20 //单分支 // if count < 30 { // fmt.Println("没有了") // } //在goling if后面可以并量加入定义 if count := 40;count < 30 { fmt.Println("没有了") } else { fmt.Println("充足") } //else 不能再下一行 } ``` - 多分支 ![image-20230724103142819](./images/image-20230724103142819.png) ``` package main // import "fmt" // import "unsafe" import( "fmt" ) func main(){ //实现分级判定 //>=90 ---A //>=80 ---B //>=70 ---C //>=60 ---D //<60 ---E var count int = 59 //单分支 // if count >= 90 { // fmt.Println("得分为A,太棒了!") // } // if count >= 80 && count < 90 { // fmt.Println("得分为B,很棒!") // } // if count < 60 { // fmt.Println("得分为E,不及格") // } //多分支 if count >= 90 { fmt.Println("得分为A,太棒了!") }else if count >= 80 {//隐藏&& count < 90 fmt.Println("得分为B,很棒!") }else if count >= 70 {//隐藏&& count < 80 fmt.Println("得分为C,不错!") }else if count >= 60 {//隐藏&& count < 80 fmt.Println("得分为D,加油!") }else {//count < 60 fmt.Println("得分为E,不及格") } } ``` ### 3.3 switch 分支 ![image-20230724103252997](./images/image-20230724103252997.png) ``` package main // import "fmt" // import "unsafe" import( "fmt" ) func main(){ //实现分级判定 //>=90 ---A //>=80 ---B //>=70 ---C //>=60 ---D //<60 ---E var count int = 189 //switch 后面表达式结果和case比较输出: 后面的结果 switch count/10 { case 10 : fmt.Println("得分为A,太棒了!") case 8 : fmt.Println("得分为B,很棒!") case 7 : fmt.Println("得分为C,不错!") case 6 : fmt.Println("得分为D,加油!") case 5 : fmt.Println("得分为E,不及格") default: fmt.Println("你的分数为",count,"超出评估范围") } } ``` ### 3.4 循环结构for ![image-20230724141628545](./images/image-20230724141628545.png) ``` package main // import "fmt" // import "unsafe" import( "fmt" ) func main(){ //定义 var n1 int = 1 var n2 int = 2 var n3 int = 3 var n4 int = 4 var n5 int = 5 // var sum int = 0 sum += n1 sum += n2 sum += n3 sum += n4 sum += n5 fmt.Println(sum) } ``` 缩短定义: ``` package main // import "fmt" // import "unsafe" import( "fmt" ) func main(){ //定义 var i int = 1 // var sum int = 0 sum += i i++ sum += i i++ sum += i i++ sum += i i++ sum += i i++ fmt.Println(sum) } ``` for循环: ``` package main // import "fmt" // import "unsafe" import( "fmt" ) func main(){ //for var sum int = 0 for i := 1 ; i <= 5 ; i++ { sum += i } fmt.Println(sum) } //注意:for的初始表达式不能用var 要用 := ``` ## 4.函数 代码:unit5 ![image-20230724145152904](./images/image-20230724145152904.png) ``` package main // import "fmt" // import "unsafe" import( "fmt" ) //定义函数 func cal (num1 int,num2 int) (int) { var sum int = 0 sum += num1 sum += num2 return sum } func main(){ //调用函数 sum := cal(10,20) fmt.Println("10+20=",sum) //调用函数 sum1 := cal(10,420) fmt.Println(sum1) } ``` ### 4.1 函数名 遵循标识符命名规范 首字母不能是数字 首字母大写该函数可以包文件和其他包文件使用(类似public) 首字母小写只能被本包文件使用,其他不行(类似private) ### 4.2 形参列表 个数:0个,1个 ,n个 作用:接收外来参数 实际参数:传入的实践值 如:sum := cal(10,20)里的10,20 ### 4.3 返回值类型列表 个数:0个,1个 ,n个 - 0个返回值 ``` package main // import "fmt" // import "unsafe" import( "fmt" ) //定义函数 //func 函数名 (形参列表)(返回值类型){ //执行语句 //return + 返回值列表 //} func cal (num1 int,num2 int) {//如果返回值类型只有一种,可以不写 var sum int = 0 sum += num1 sum += num2 fmt.Println(sum) } func main(){ //调用函数 cal(10,20) //调用函数 cal(10,420) } ``` - 多个值 ``` package main // import "fmt" // import "unsafe" import( "fmt" ) //定义函数 //func 函数名 (形参列表)(返回值类型){ //执行语句 //return + 返回值列表 //} func cal (num1 int,num2 int) (int,int) {//如果返回值类型只有一种,可以不写 var sum int = 0 sum += num1 sum += num2 var cha int = num1 - num2 return sum,cha } func main(){ //调用函数 sum,cha := cal(10,20) fmt.Println("10+20=",sum) fmt.Println("10-20=",cha) } ``` 使用“—”占位 ``` package main // import "fmt" // import "unsafe" import( "fmt" ) //定义函数 //func 函数名 (形参列表)(返回值类型){ //执行语句 //return + 返回值列表 //} func cal (num1 int,num2 int) (int,int) {//如果返回值类型只有一种,可以不写 var sum int = 0 sum += num1 sum += num2 var cha int = num1 - num2 return sum,cha } func main(){ //调用函数 //sum,cha := cal(10,20) //fmt.Println("10+20=",sum) //fmt.Println("10-20=",cha) //fmt.Println(sum,cha) sum,_:= cal(10,20)//_可以占位 fmt.Println(sum) } ``` ### 4.4 作用域问题 ``` package main // import "fmt" // import "unsafe" import( "fmt" ) //定义函数 //func 函数名 (形参列表)(返回值类型){ //执行语句 //return + 返回值列表 //} func exchangeNum (num1 int,num2 int) { var t int t = num1 num1 = num2 num2 = t return } func main(){ //调用函数 var num1 int = 10 var num2 int = 20 fmt.Println(num1,num2) //调用函数 exchangeNum(num1,num2) fmt.Println(num1,num2) } ``` ![image-20230724155804258](./images/image-20230724155804258.png) ### 4.5 细节 ![image-20230724160425168](./images/image-20230724160425168.png) - golang中函数名不能重复 - 可变参数 ``` package main import "fmt" //可变参数用...表示 func test (args...int) { //将可变参数当作切片处理 for i :=0;i < len(args); i++{ fmt.Println(i) } } func main(){ //调用函数 test() test(2) test(1,2,3) } ``` - 8 问题代码 ``` package main import "fmt" //可变参数用...表示 func test (num int) { // num = 30 fmt.Println("test---",num) } func main(){ //调用函数 var num int = 10 test(num) fmt.Println("main---",num) } ``` - 9 ``` package main import "fmt" //可变参数用...表示 func test (num *int) {//*int表示指针 // *num = 30 fmt.Println("test---",&num) } func main(){ //调用函数 var num int = 10 test(&num)//&传地址 fmt.Println("地址:",&num) } ``` ![image-20230724163256480](./images/image-20230724163256480.png) ``` package main import "fmt" //定义一个函数 func test (num int) { fmt.Println(num) } //定义一个函数,把另一个函数作为形参 func test2 (num1 int ,num2 float32 ,testFunc func(int)){ fmt.Println(num1,num2,testFunc) } //使用自定义数据类型简洁写法 type myFunc func(int) func test3 (num1 int ,num2 float32 ,testFunc myFunc){ fmt.Println(num1,num2,testFunc) } //定义函数求和 func test4 (num1 int ,num2 int )(int,int){ sum := num1 + num2 diff := num1 - num2 //fmt.Println(sum,diff) return sum,diff } func test5 (num3 int ,num4 int )(sum1 int,diff1 int){ sum1 = num3 + num4 diff1 = num3 - num4 //fmt.Println(sum,diff) return } func main(){ //调用函数 //函数也是一种数据类型,可以赋值给一个变量 a := test fmt.Printf("a的数据类型是: %T,test函数的数据类型是: %T \n",a,test) //通过该变量可以使用函数调用 a(10)// 等价于test(10) //调用test2函数 test2(2,3.5,test) //自定义数据类型 type myint int var eric myint = 30 fmt.Println(eric) //虽然是别名,但go中认为int和myint不是同一种类型需要转换数据类型int(eric) var gwq int = int(eric) fmt.Println(gwq) //调用test3,试试自定义数据类型是否生效 test3(23,3.15,a) //调用test4 //var sum int //var diff int aaa,bbb := test4(5,3) fmt.Println(aaa,bbb) ccc,ddd := test5(7,8) fmt.Println(ccc,ddd) } ``` ## 5. 包的引入 ### 5.1 作用与方法 ![image-20230725112319111](./images/image-20230725112319111.png) ``` package main //package进行包的声明,建议和文件夹同名 import "fmt" //包名是从$GOPATH/src/后面开始,使用/分割,GOPATH用go env查看 import "unit5/5.5/db" func main(){ //调用外部包函数 db.GetConn() fmt.Println("你好,这是main函数") } ``` ``` package db //package进行包的声明,建议和文件夹同名 import "fmt" func GetConn(){//首字母大写,可以被其他包访问 fmt.Println("你好,已经调到外部函数") } ``` ### 5.2 细节 ![image-20230725141140194](./images/image-20230725141140194.png) ## 6. 错误处理 ### 6.1 defer+recover机制处理错误 ![image-20230725144051891](./images/image-20230725144051891.png) 报错后中断,不往后执行 【2】错误处理/捕获机制 go中追求代码优雅,引入机制:defer+recover机制处理错误 ``` package main import( "fmt" ) func main(){ fmt.Println("函数前执行。。。") test() fmt.Println("函数后执行。。。") } func test(){ //利用defer+recover来捕获错误 defer func() { //调用内置函数recover err := recover() //如果没有捕获错误,返回值为零值:nil if err != nil { fmt.Println("错误已捕获") fmt.Println("err是:",err) } }()//加上()表是匿名函数的调用 num1 := 10 num2 := 0 result := num1 / num2 fmt.Println(result) } ``` ![image-20230725145614547](./images/image-20230725145614547.png) 捕获错误,程序继续执行,不会中断。 ### 6.2 自定义错误 需要调用New函数(errors下) ``` package main import( "fmt" "errors" ) func main(){ fmt.Println("函数前执行。。。") err := test() if err != nil { fmt.Println(err) } fmt.Println("函数后执行。。。") } func test() (err error){ num1 := 10 num2 := 0 if num2 == 0 { //抛出自定义错误 return errors.New("除数不能为0~~") }else{ result := num1 / num2 fmt.Println(result) return nil } } ``` 使用panic函数强制停止程序 ``` package main import( "fmt" "errors" ) func main(){ fmt.Println("函数前执行。。。") err := test() if err != nil { fmt.Println("自定义错误:",err) panic(err)//使用panic函数强制停止程序 } fmt.Println("函数后执行。。。") } func test() (err error){ num1 := 10 num2 := 0 if num2 == 0 { //抛出自定义错误 return errors.New("除数不能为0~~") }else{ result := num1 / num2 fmt.Println(result) return nil } } ``` ## 7. 数组 ### 7.1 传统程序的缺点 ``` package main import( "fmt" ) func main(){ //给出5个学生的成绩,求和与平均数 score1 := 88 score2 := 98 score3 := 78 score4 := 68 score5 := 86 //和 sum := score1 + score2 + score3 + score4 + score5 avg := sum / 5 fmt.Printf("总分: %v\n平均成绩: %v",sum,avg) } ``` 以上程序缺点:定义太多 ### 7.2 数组的引入 ``` package main import( "fmt" ) func main(){ //给出5个学生的成绩,求和与平均数 //定义数组 var scores [5]int //填数 scores[0] = 88 scores[1] = 98 scores[2] = 78 scores[3] = 68 scores[4] = 86 //和 sum := 0 for i :=0; i < len(scores);i++ { sum += scores[i] } avg := sum / len(scores) fmt.Printf("总分: %v\n平均成绩: %v",sum,avg) } ``` ### 7.3 内存分析 ``` package main import( "fmt" ) func main(){ //定义数组 var arr [3]int16 //填数 //获取数组的长度 fmt.Println(len(arr)) //打印数组 fmt.Println(arr) //打印数组的地址 fmt.Printf("arr的地址: %p\n",&arr) fmt.Printf("arr的地址: %p\n",&arr[0]) fmt.Printf("arr的地址: %p\n",&arr[1]) fmt.Printf("arr的地址: %p\n",&arr[2]) } ``` ### 7.4 数组的遍历 ``` package main import( "fmt" ) func main(){ //给出5个学生的成绩,求和与平均数 //定义数组 var scores [5]int //填数 for i :=0;i < len(scores);i++{ fmt.Printf("请输入第%d个学生成绩:",i + 1 ) fmt.Scanln(&scores[i]) } //数组的遍历 //方式1:普通for循环 for i :=0; i < len(scores);i++ { fmt.Printf("第%d个学生成绩: %d\n",i+1,scores[i]) } fmt.Println("=================") //方法2:for-range for key,value := range scores { fmt.Printf("第%d个学生成绩: %d\n",key+1,value) } //不想输出key,_代替 for _,value := range scores { fmt.Printf("第学生成绩: %d\n",value) } } ``` ### 7.5 数组的初始化方法 ``` package main import( "fmt" ) func main(){ //第一种 var arr1 [3]int = [3]int{3,6,9} fmt.Println(arr1) //第二种 var arr2 = [3]int{1,4,7} fmt.Println(arr2) //第三种 var arr3 = [...]int{1,2,4,5} fmt.Println(arr3) //第四种 var arr4 = [...]int{2:55,0:33,1:99,3:66} fmt.Println(arr4) } ``` - 注意事项 1.长度属于类型的一部分 ``` package main import( "fmt" ) func main(){ //第一种 var arr1 = [3]int{3,6,9} fmt.Println(arr1) fmt.Printf("数组的类型:%T",arr1) fmt.Println() var arr2 = [6]int{3,6,9,5,3,8} fmt.Println(arr2) fmt.Printf("数组的类型:%T",arr2) } ``` 2.Go中数组的属值类型,在默认的情况下是值传递,因此会进行值拷贝。 ``` package main import( "fmt" ) func main(){ var arr3 = [3]int{3,6,9} test(arr3) fmt.Println(arr3)//还是[3 6 9] } func test(arr [3]int){ arr[0] = 7 } ``` 3.如想在其他函数中,去修改原来的数组,可以使用引用传递(指针方式)。 ``` package main import( "fmt" ) func main(){ var arr3 = [3]int{3,6,9} test(&arr3)//&传入地址 fmt.Println(arr3)//改变了[7 6 9] } func test(arr *[3]int){//* 代表修改对应地址 (*arr)[0] = 7 } ``` ### 7.6 二维数组 - 二维数组的定义,默认值0 ``` package main import( "fmt" ) func main(){ //定义二维数组 var arr [2][3]int16 fmt.Println(arr) } ``` ``` go run .\7.6.go [[0 0 0] [0 0 0]] ``` - 二维数组的内存(2字节一位) ``` package main import( "fmt" ) func main(){ //定义二维数组 var arr [2][3]int16 fmt.Println(arr) fmt.Printf("arr的地址:%p",&arr) fmt.Printf("\narr[0]的地址:%p",&arr[0]) fmt.Printf("\narr[0][0]的地址:%p",&arr[0][0]) fmt.Printf("\narr[0][1]的地址:%p",&arr[0][1]) fmt.Printf("\narr[0][2]的地址:%p",&arr[0][2]) fmt.Println("------------") fmt.Printf("\narr[1]的地址:%p",&arr[1]) fmt.Printf("\narr[1][0]的地址:%p",&arr[1][0]) fmt.Printf("\narr[1][1]的地址:%p",&arr[1][1]) fmt.Printf("\narr[1][2]的地址:%p",&arr[1][2]) fmt.Println("------------") } ``` - 赋值 ``` package main import( "fmt" ) func main(){ //定义二维数组 var arr [2][3]int16 fmt.Println(arr) fmt.Printf("arr的地址:%p",&arr) fmt.Printf("\narr[0]的地址:%p",&arr[0]) fmt.Printf("\narr[0][0]的地址:%p",&arr[0][0]) fmt.Printf("\narr[0][1]的地址:%p",&arr[0][1]) fmt.Printf("\narr[0][2]的地址:%p",&arr[0][2]) fmt.Println("------------") fmt.Printf("\narr[1]的地址:%p",&arr[1]) fmt.Printf("\narr[1][0]的地址:%p",&arr[1][0]) fmt.Printf("\narr[1][1]的地址:%p",&arr[1][1]) fmt.Printf("\narr[1][2]的地址:%p",&arr[1][2]) fmt.Println("------------") //赋值 arr[0][0] = 00 arr[0][1] = 01 arr[0][2] = 02 arr[1][0] = 33 arr[1][1] = 11 arr[1][2] = 12 fmt.Println(arr) } ``` - #### 初始化 ``` package main import( "fmt" ) func main(){ //初始化 var arr1 [2][3]int = [2][3]int{{1,4,7},{2,4,6}} fmt.Println(arr1) var arr2 = [2][3]int{{1,4,7},{2,4,6}} fmt.Println(arr2) } ``` - 二维数组的遍历 ``` package main import( "fmt" ) func main(){ //定义二维数组 var arr = [3][3]int{{1,4,7},{6,8,9},{2,4,6}} fmt.Println(arr) fmt.Println("-----------") //方式1:for循环 for i := 0;i < len(arr);i++{ for j := 0;j < len(arr[i]);j++{ fmt.Print(arr[i][j],"\t") } fmt.Println() } fmt.Println("-----------") //方式2:for range循环 for k,v := range arr { for k1,v1 := range v { fmt.Printf("arr[%v][%v]=%v\t",k,k1,v1) } fmt.Println() } } ``` ## 8.切片 ### 8.1 切片的引入 ![image-20230726102451096](./images/image-20230726102451096.png) ``` package main import( "fmt" ) func main(){ //定义一个数组 var intarr [6]int = [6]int{3,4,5,6,7,8} //定义切片,切出数组1--3(不包含)部分 var slice []int = intarr[1:3] fmt.Println("数组intarr:",intarr) fmt.Println("slice切片是:",slice) fmt.Println("切片slice长度:",len(slice)) //切片的容量 fmt.Println("切片slice容量:",cap(slice)) fmt.Printf("数组下标为1位置的地址: %p",&intarr[1]) fmt.Printf("\n数组下标为0位置的地址: %p",&slice[0]) slice[1] = 16 fmt.Println("\n数组intarr:",intarr) fmt.Println("slice切片是:",slice) } ``` ### 8.2 切片的定义 [1] 方式1: 定义一个切片,然后让切片去引用一个已经创建好的数组。 [2]方式2: 通过make内置函数来创建切片。基本语法: var切片名[type = make(0, len,[cap]) [3]方式3: 定一个切片,直接就指定具体数组,使用原理类似make的方式。 ``` package main import( "fmt" ) func main(){ //定义切片,切出数组1--3(不包含)部分 slice := make([]int,4,20) fmt.Println(slice) fmt.Println("切片的长度:",len(slice)) fmt.Println("切片的容量:",cap(slice)) //赋值 slice[0] = 66 slice[1] = 88 fmt.Println(slice) //定义切片 slice2 := []int{1,3,7} fmt.Println(slice2) fmt.Println("切片slice2的长度:",len(slice2)) fmt.Println("切片slice2的容量:",cap(slice2)) } ``` ### 8.3 切片的遍历 [1]方式1: for循环常规方式遍历 [2]方式2: for-range 结构遍历切片 ``` package main import( "fmt" ) func main(){ //定义切片 slice := make([]int,4,20) slice[0] = 66 slice[1] = 77 slice[2] = 88 slice[3] = 99 fmt.Println(slice) fmt.Println("切片slice2的长度:",len(slice)) fmt.Println("切片slice2的容量:",cap(slice)) //方式1: for循环遍历切片 for i :=0; i < len(slice);i++ { fmt.Printf("\nslice[%v] = %v \t",i,slice[i]) } //方式2: for range fmt.Println("\n---------------------") for key,value := range slice { fmt.Printf("\nslice[%v] = %v \t",key,value) } } ``` ### 8.4 切片的注意事项 [1] 切片定义后不可以直接使用,需要让其引用到一个数组,或者make一个空间供切片来使用 [2]切片使用不能越界。 [3]简写方式: 1) var slice = arr[0:end] ----》 var slice = arr[:end] 2) var slice = arr[start:len(arr)] ----》 var slice = arr[start:] 3) var slice = arr[0:len(arr)]----》 var slice = arr[:] [4]切片可以继续切片 [5] 切片可以动态增长 [6] 切片的拷贝 ``` package main import( "fmt" ) func main(){ //定义切片 var arr = [6]int{1,3,4,5,6,8} //3.1省略0开头 var slice []int = arr[:3] //3.2省略n到末尾 var slice1 []int = arr[4:] //3.3/4.切片继续切片,全切只写: slice2 := slice[:] //修改会改原值 slice2[1] = 55 fmt.Println(slice) fmt.Println(slice1) fmt.Println(slice2) fmt.Println("切片slice2的长度:",len(slice)) fmt.Println("切片slice2的容量:",cap(slice)) //5.追加,产出新数组再追加 slice4 := append(slice,88,77) fmt.Println(slice4) fmt.Println(slice) //要改原来的,重新赋值 slice = append(slice,88,77) fmt.Println(slice) //切片追加给切片 slice5 := []int{99,88} slice = append(slice,slice5...) fmt.Println(slice) //6.切片的拷贝 var b[]int = make([]int,10) copy(b,slice) fmt.Println(b) } ``` ## 9 . 映射(map) ### 9.1 映射的引入 [1] 映射(map),Go 语言中内置的一种类型,它将键值相关联,我们可以通过键 key 来获对应的值 value。类似其它语言的集合 [2]基本语法 var map变量名map[keytype]valuetype Ps: key、value的类型: bool、数字、string、指针、channel、还可以是只包含前面几个类型的接口、结构体、数组 PS: key通常为int、string类型,value通常为数字(整数、浮点数)、string、map、结构体 Ps: slice、map、function不可以 map的特点: (1)map集合在使用前一定要make (2)map的key-value是无序的 (3)key是不可以重复的,如果遇到重复,后一个value会替换前一个value (4)value可以重复的 [3] 代码: ``` package main import( "fmt" ) func main(){ //定义一个map变量 var a map[int]string //只声明,没有内存空间,需要make初始化 a = make(map[int]string,10) //赋值 a[20090291] = "eric" a[20090289] = "gwq" a[20090267] = "Gg" a[20090267] = "Mm"//key唯一,重复取后面 a[20090287] = "Mm"//value可以重复的 fmt.Println(a) } ``` ### 9.2 map的三种创建方式 ``` package main import( "fmt" ) func main(){ //方式1 var a map[int]string //只声明,没有内存空间,需要make初始化 a = make(map[int]string,10) //赋值 a[20090291] = "eric" a[20090289] = "gwq" a[20090267] = "Gg" a[20090267] = "Mm"//key唯一,重复取后面 a[20090287] = "Mm"//value可以重复的 fmt.Println(a) //方式2 b := make(map[int]string) b[20090291] = "eric" b[20090289] = "gwq" fmt.Println(b) //方式3 c := map[int]string{ 20090291 : "eric", 20090292 : "gwq", } c[20090267] = "Gg" fmt.Println(c) } ``` ### 9.3 map的操作 [1] 增加和更新操作:~》如果key还没有,就是增加,如果key存在就是修改map["key"]= value [2] 删除操作: delete(map,"key“),delete是一个内置函数,如果key存在,就删除该key-value,如果k的y不存在,不操作,但是也不会报错 [3] 清空操作: (1)如果我们要删除map的所有key ,没有一个专门的方法一次删除,可以遍历一下key,逐个删除 (2)或者map = make(...),make一个新的,让原来的成为垃圾,被gc回收 [4]查找操作: value ,bool = map[key] value为返回的value,bool为是否返回 ,要么true 要么false [5] 获取长度:len函数 [6] 遍历:for-range ``` package main import( "fmt" ) func main(){ //方式2 b := make(map[int]string) //增加 b[20090291] = "eric" b[20090289] = "gwq" fmt.Println(b) //4.获取长度 fmt.Println(len(b)) //5.遍历 for k,v := range b { fmt.Printf("\nkey为: %v,value为: %v\t",k,v) } fmt.Println("\n-------") //修改 b[20090291] = "GG" fmt.Println(b) //删除 delete(b,20090289) fmt.Println(b) //查找 value,flag := b[20090291] fmt.Println(flag,value) //获取长度 fmt.Println(len(b)) fmt.Println("\n-------") //加深难度 a := make(map[string]map[int]string) //赋值 a["class1"] = make(map[int]string) a["class1"][2008022] = "aa" a["class1"][2008033] = "bb" a["class1"][2008044] = "cc" a["class2"] = make(map[int]string) a["class2"][2008055] = "33" a["class2"][2008066] = "44" a["class2"][2008088] = "55" for kk,vv := range a { fmt.Println("\n",kk) for kkk,vvv := range vv { fmt.Printf("\n学生学号: %v 学生姓名: %v \t",kkk,vvv) } fmt.Println() } } ``` ## 10.面向对象 ### 10.1 面向对象的引入 [1] Golang语言面向对象编程说明: (1)Golang也支持面向对象编程(0OP),但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言。所以我们说Golang支持面向对象编程特性是比较准确的。( 2)olang没有类(class),Go语言的结构体(struct)和其它编程语言的类Class)有同等的地位,你可以理解Gelang是基于struct来实现00P特性的, (3)Golang面向对象编程非常简洁,去掉了传统OOP语言的方法重载、构造函数和析构函数、隐藏的this指针等等 (4)Golang仍然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其它OOP语言不一样,比如继承:Glang没有extends 关键字,继承是通过匿名字段来实现。 [2] 结构体的引入: ### 10.2 结构体 #### 10.2.1 结构体,结构体的对象的映入 ![image-20230727111744780](./images/image-20230727111744780.png) ``` package main import( "fmt" ) //定义一个结构体 type Teacher struct{ Name string Age int School string } func main(){ var t1 Teacher fmt.Println(t1) //默认{ 0 } //赋值 t1.Name = "eric" t1.Age = 34 t1.School = "bowen" fmt.Println(t1) fmt.Println(t1.Age + 10) } ``` #### 10.2.2 结构体的创建 ``` package main import( "fmt" ) //定义一个结构体 type Teacher struct{ Name string Age int School string } func main(){ //方式2 var t1 Teacher fmt.Println(t1) //默认{ 0 } t1.Name = "eric" t1.Age = 34 t1.School = "bowen" fmt.Println(t1) fmt.Println(t1.Age + 10) //方式2 var t Teacher = Teacher{"gwq",33,"niujing"} fmt.Println(t) //方式3 var t2 *Teacher = new(Teacher)//t2是指针,地址,给指向赋值 (*t2).Name = "GG" (*t2).Age = 12 t2.School = "DX" fmt.Println(*t2) //方式4 var t3 *Teacher = &Teacher{} (*t3).Name = "GG" (*t3).Age = 12 t2.School = "DX" fmt.Println(*t3) } ``` #### 10.2.3 结构体之间的转换 [1] 结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字、个数和类型) ``` package main import( "fmt" ) //定义一个结构体 type Teacher struct { Age int } type Student struct { Age int } func main(){ var t Teacher = Teacher{33} var s Student = Student{22} s = Student(t)//转换格式 fmt.Println(t) //默认{ 0 } fmt.Println(s) } ``` [2] 结构体进行type重新定义(相当于取别名),Golang认为是新的数据类型,但是相互间可以强转 ``` package main import( "fmt" ) //定义一个结构体 type Student struct { Age int } type Stu Student//type重新定义 func main(){ var s1 Student = Student{22} var s2 Stu = Stu{23} s1 = Student(s2) fmt.Println(s1) fmt.Println(s2) } ``` ### 10.3 方法的引入 [1]方法是作用在指定的数据类型上和指定的数据类型绑定,因此自定义类型,都可以有方法,而不仅仅是struct [2]方法的声明和调用格式 声明: ``` type A struct { Num int } func (a A) test() { fmt.Println{a.Num} } ``` 调用: var a A a.test() [3] 代码层面: ``` package main import( "fmt" ) //定义一个结构体 type Person struct{ Name string } //绑定方法 func (p Person) test(){ p.Name = "gwq" fmt.Println(p.Name)//gwq } func main(){ //创建结构体的对象 var p Person p.Name = "eric" p.test() fmt.Println(p.Name)//eric } ``` 注意: 1)test方法中参数名字随意起 2)结构体Person和test方法绑定,调用test方法必须靠指定的类型: Person 3)如果其他类型变量调用test方法一定会报错。 4)结构体对象传入test方法中,值传递,和函数参数传递一致 - #### 方法的注意事项: (1)结构体类型是值类型,在方法调用中,遵守值类型的传递机制,是值拷贝传递方式 (2)如程序员希望在方法中,力改结构体变量的值,可以通过结构体指针的方式来处理 (3)Golang中的方法作用在指定的数据类型上的,和指定的数据类型绑定,因此自定义类型,都可以有方法,而不仅仅是struct,比如int,float32等都可以有方法 ``` package main import( "fmt" ) //定义一个结构体 type Person struct{ Name string } //绑定方法 func (p *Person) test(){ (*p).Name = "gwq" fmt.Println(p.Name)//gwq } func main(){ //创建结构体的对象 var p Person p.Name = "eric" (&p).test() fmt.Println(p.Name)//gwq } ``` 简化: ``` package main import( "fmt" ) //定义一个结构体 type Person struct{ Name string } //绑定方法 func (p *Person) test(){ p.Name = "gwq" fmt.Println(p.Name)//gwq } func main(){ //创建结构体的对象 var p Person p.Name = "eric" p.test() fmt.Println(p.Name)//eric } ``` ``` package main import( "fmt" ) //定义一个结构体 type integer int //绑定方法 func (i integer) print(){ i = 30 fmt.Println("i = ",i) } func (i *integer) change(){ *i = 30 fmt.Println("i = ",*i) } func main(){ //创建结构体的对象 var i integer = 20 i.print() i.change() fmt.Println("i = ",i) } ```