版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Go语言程序设计项目化教程(微课版)1.1Go语言概况.pptx1.2初识Go程序.pptx 2.1基本运算.pptx 2.2复合数据类型.pptx 2.3流程控制.pptx 2.4循环控制.pptx 3.1函数.pptx 3.2函数的使用.pptx 3.3变参与递归函数.pptx 3.4Go语言特有函数.pptx 4.1结构体.pptx 4.2结构体进阶.pptx 4.3结构体内嵌.pptx 4.4接口与结构体.pptx 5.1反射与文件.pptx 5.2并发.pptx 6.1数据库基本操作.pptx 6.2CRUD操作.pptx 7.1初识Gin.pptx 7.2路由.pptx 7.3中间件.pptx
Go语言概况Go语言的发展历程Go语言的应用领域Go语言的特性Go程序运行环境01.03.02.04.目录01Go语言的发展历程Go语言的诞生Go语言的重要里程碑2008年初,Unix之父肯·汤普逊实现了第一版Go编译器。1Go语言的发展历程1Go语言的发展历程2009年11月10日Go语言诞生日2012年3月28日Go1.0发布同时发布“Go1兼容性”承诺2015年8月11日Go1.5发布完全移除C语言部分2018年8月25日Go1.11发布引入新的Go包管理机制:GoModules2021年2月17日Go1.16发布GoModules成为默认包管理机制2021年8月16日Go1.17发布将Go程序性能提高约5%2022年3月15日Go1.18发布支持泛型、模糊测试、工作区2022年8月3日Go1.19发布完善Go1.18,丰富文档注释语法02Go语言的特性编译快,效率高易学习,成本低强大的标准库简单的高并发便捷的应用良好的规范持续的发展编译快,效率高相较于Java和C++相对较慢的编译速度,Go语言的编译速度快是一个主要的优势。易学习,成本低Go语言语法简单,与C语言的语法类似。强大的标准库Go语言中的标准库非常稳定并且丰富多样,包括网络、系统、加密、编码、图形等各个方面。简单的高并发Go语言的Goroutine和Channel的出现让处理并发和异步编程的问题变得优雅和流畅。便捷的应用不依赖任何系统提供的编译器和链接器,其编译出来的二进制可执行文件几乎可以运行在任何系统环境中。良好的规范除代码规范之外还拥有强大的编译检查、严格的编码规范和很强的稳定性。持续的发展Google公司聚集了一批具备世界水准的软件工程师。2Go语言的特性03Go语言的应用领域服务器端云计算云服务区块链大数据、人工智能C和C++能做的事情,Go语言都可以做Go语言目前在服务器端的落地应用有:数据打包、日志处理、文件系统、数据库代理、Web应用、API应用等云计算时代的C语言Go语言目前在云计算的落地应用有:京东的消息推送服务、京东分布式文件系统3Go语言的应用领域区块链的主流开发语言正是Go语言Go语言目前在区块链的落地应用有:以太坊、金链盟区块链技术框架FISCO-BCOSGo语言非常适合做数据挖掘、分析、存储Go语言目前在人工智能和大数据的落地应用有:pholcus(爬虫)、TiDB(存储)、针对Tensorflow编写各种API3Go语言的应用领域04Go程序运行环境程序的定义开发(运行)环境运行步骤要想让计算机完成某个任务,就需要将任务分解为能够让计算机识别的指令,最终将指令汇合形成程序。4Go程序运行环境使用文本编辑器创建Go程序保存文件编译程序运行编译得到的可执行文件4Go程序运行环境名词解释$GOROOTGo的实际安装路径$GOARCH计算机的处理器架构(x86、ARM等)$GOOS计算机的操作系统(Windows、Linux等)$GOBIN编译器和链接器的安装位置,默认是$GOROOT/bin$GOPATH项目的工作目录,内含三个规定的目录:src(存放源码文件)、pkg(存放包文件)和bin(存放可执行文件)4Go程序运行环境4Go程序运行环境谢谢观看初识Go程序开发工具GoModules01.02.目录第一个Go语言程序03.编译与运行04.01开发工具开发工具定义GoLandLitelDEVSCodeEclipseVimEmacs1开发工具用于辅助软件生命周期过程的基于计算机的工具,能够很方便地把一种编程语言代码化并编译执行。开发工具用户易操作功能强大很方便修改、扩展覆盖面大可靠性高1开发工具是Jetbrains针对Go语言所开发的一款商业IDEGoLand整合了IntelliJ平台提供了针对Go语言的编码辅助和工具集成对代码编写、自动补全和运行调试都有极大的帮助是大多数开发者的首选工具GoLand1开发工具一款国人所设计开发的Go集成开发环境一款非常好用的轻量级Go语言集成开发环境支持跨平台开发包含了抽象语法树视图的功能支持在各个Go开发环境之间随意切换支持交叉编译LitelDE1开发工具全称是VisualStudioCode由微软Microsoft所开发的一款免费的开发工具具有简单、轻快、开放的特点支持多种语言,默认提供Go语言的语法高亮在安装Go语言插件之后,还可以支持智能提示、编译运行等诸多实用功能VSCode1开发工具开放式IDE的鼻祖是一个开源免费的平台安装不同的插件即可运行不同的语言提供了GoEclipse插件Eclipse1开发工具从vi发展出来的一个Linux平台的文本编辑器以字体颜色辨别语法的正确性具有代码补全、编译及错误跳转等功能是很多程序员在Linux下必备的一款工具Vim1开发工具一款运行在Linux和Unix系统下的文本编辑器具有强大的可扩展性同时也是一个集成开发环境Emacs02GoModulesGoModules的出现gomod命令2GoModulesgo1.11之前代码开发必须在gopathsrc目录下,不然在执行过程中会遇到问题。使用gopath进行管理,极其依赖手动管理,并且依赖包没有版本可言。后推出govendor解决了包依赖,一个配置文件就管理;但是依赖包全都下载到项目vendor下,导致每个项目都会持有一部分相同文件。go1.11推出特性gomodules,用于解决之前没有地方记录依赖包具体版本的问题,方便依赖包的管理。Modules是相关Go包的集合,是源代码交换和版本控制的单元。Modules和传统的GOPATH不同,不需要包含例如src,bin这样的子目录,一个源代码目录甚至是空目录都可以作为Modules,只要其中包含有go.mod文件。gomod相关命令初始化项目gomodinit+模块名称项目如果不在GOPATH下,则必须要有go.mod文件,否则运行会报错命令作用gomoddownload下载依赖包到本地(默认为GOPATH/pkg/mod目录)gomodedit编辑go.mod文件gomodgraph打印模块依赖图gomodinit初始化当前文件夹,创建go.mod文件gomodtidy增加缺少的包,删除无用的包gomodvendor将依赖复制到vendor目录下gomodverify校验依赖gomodwhy解释为什么需要依赖2GoModules03第一个Go程序包的认识fmt包main()函数程序结构3第一个Go程序packagemain //指定其所在的包import“fmt“ //导入fmt包funcmain(){ //main()函数是程序的入口fmt.Println("不忘初心,牢记使命!")}在Go语言中所有的文件都需要指定其所在的包(package)运行结果为:不忘初心,牢记使命!"包有两种类型main包在代码的开头使用packagemain进行声明非main包在代码的开头使用package+包名进行声明3第一个Go程序import"fmt"是导入fmt包fmt包实现了类似C语言printf和scanf的格式化I/O注意:import导入的是相对路径,而不是包名Println()是fmt包中的一个函数,用来格式化输出数据3第一个Go程序Go语言程序结构包声明引入包函数变量语句&表达式注释易错点注意“{”不能单独放在一行;否则会在运行时产生“syntaxerror:unexpectedsemicolonornewlinebefore{”的错误。在整个程序中有且仅能有一个main函数;如果出现多个main函数则不能正常运行。04编译与运行gobuildgorun4编译与运行Go语言中使用gobuild命令主要用于编译代码gobuild命令会将1.2-hello.go文件编译成1.2-hello.exe文件GoLand的Run‘gobuild1.2-hello.go’操作会运行编译后的1.2-hello.exe文件,在文件运行结束后会自动删除1.2-hello.exe文件gorun命令也能够编译源码不会在当前目录留下可执行文件把编译和执行合为一步完成本质是:把编译过程隐藏了起来,编译过程依然存在,可执行文件被放在临时文件中被执行4编译与运行谢谢观看基本运算关键字与标识符数据类型变量和常量运算符01.03.02.04.目录字符串拼接05.数据类型转换06.01关键字和标识符25个关键字标识符命名规则1关键字和标识符breakdefaultfuncinterfaceselectcasedefergomapstructchanelsegotopackageswitchconstfallthroughifrangetypecontinueforimportreturnvar关键字:被赋予了特殊含义的单词,又叫保留字。Go语言中的关键字一共有
25个。标识符特点标识符的命名要尽量采取简短且有意义。不能和标准库中的包名重复。为变量、函数、常量命名时采用驼峰命名法,例如stuId、stuName。标识符声明使用标识符之前必须进行声明。声明一个标识符就是将这个标识符与常量、类型、变量、函数或者代码包绑定在一起。在同一个代码块内标识符的名称不能重复。标识符定义Go语言对各种变量、方法、函数等命名时使用的字符序列。由若干个字母、下划线(_)、和数字组成,且第一个字符必须是字母。1关键字和标识符标识符规则由26个英文字母、0~9、_组成不能以数字开头Go语言中严格区分大小写标识符不能包含空格不能以系统保留关键字作为标识符标识符的命名要尽量采取简短且有意义的词不能和标准库中的包名重复1关键字和标识符1关键字和标识符预定义标识符:自身具有一些特殊含义的标识符。Go语言中的预定义标识符一共有
37个。内建常量nil、iota、true、false内建类型int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、uintprt、float32、float64、complex64、complex128、bool、byte、rune、string、error内建函数append、cap、close、complex、copy、delete、imag、len、make、new、panic、real、recovervarstuIdint//声明一个int类型、名为stuId的标识符varstuNamestring=“姓名“//声明一个string类型、名为stuName、值为姓名的标识符标识符声明示例错误标识符示例0102var1numint//不能以数字开头varbreakstring//不能以系统保留关键字作为标识符1关键字和标识符02变量和常量变量的定义变量的标准格式声明变量的批量格式声明变量的简短格式声明常量的定义常量的显式定义常量的隐式定义varaint=100x000110变量内存varp*int=&a0x00010x0005变量:一种能够储存值或者计算结果的抽象概念。
是内存中的一个数据存储空间的标识,变量可以看做是一个内存地址,通过内存地址,我们可以找到这个地址所存储的数据。2变量和常量局部变量函数体内声明的变量称之为局部变量,作用域只在函数体内,函数的参数和返回值变量都属于局部变量。函数调用结束后这个局部变量就会被销毁。全局变量在函数体外声明的变量称之为全局变量,全局变量声明必须以var关键字开头,如果想要在外部包中使用全局变量的首字母必须大写。形参变量在定义函数时函数名后面括号中的变量叫做形式参数变量。形式参数只在函数调用时才会生效,函数调用结束后就会被销毁。2变量和常量2变量和常量关键字var开头,后置变量类型格式:var变量名变量类型标准初始化格式:var变量名变量类型=初始化值变量标准格式声明示例1:vargoodsNamestring="Go语言“示例2:varstuNamestringstuName=“小明“2变量和常量存放一组变量定义格式:var(a变量类型b变量类型c,d变量类型)变量批量格式声明示例:var(goodsPricefloat32goodsNum,goodsIdint)goodsId=123goodsNum=5goodsPrice=6.72变量和常量定义在函数内部的显式初始化,不提供数据类型格式:变量名:=变量值变量名1,变量名2:=变量值1,变量值2变量简短格式声明示例1:goodsName:="Go语言“示例2:goodsSize,goodsID:="50kg“,”go0001”2变量和常量常量的数据类型布尔型数字型整数浮点复数字符串型标准定义格式:const常量名[常量类型]=常量值显式定义格式:const常量名
常量类型=常量值隐式定义格式:const常量名=常量值常量:一种简单值的标识符,在程序运行时它的值不会被改变。2变量和常量packagemainimport"fmt"funcmain(){
constaint=1
constb,c=2,"C" fmt.Println(a) fmt.Println(b) fmt.Println(c)}运行结果为:12Ca是显式类型定义,即能看到数值类型。b,c是隐式类型定义。03数据类型布尔型(bool)数字类型字符串类型派生类型3数据类型类型解释布尔型(bool)布尔型的值只可以是常量、true或者false数字类型整型(int)和浮点型(float32、float64)字符串类型字符串就是一串固定长度的字符连接起来的字符序列派生类型指针类型(Pointer)数组类型结构体类型(struct)Channel类型函数类型切片类型接口类型(interface)Map类型3数据类型数字类型解释uint8无符号8位整型(0到255)uint16无符号16位整型(0到65535)uint32无符号32位整型(0到4294967295)uint64无符号64位整型(0到18446744073709551615)int8有符号8位整型(-128到127)int16有符号16位整型(-32768到32767)int32有符号32位整型(-2147483648到2147483647)int64有符号64位整型(-9223372036854775808到9223372036854775807)float32IEEE-75432位浮点型数float64IEEE-75464位浮点型数complex6432位实数和虚数complex12864位实数和虚数byte类似uint8rune类似int32uintptr无符号整型,用于存放一个指针3数据类型packagemainimport"fmt"funcmain(){varnumintfmt.Println("num=",num)varpai_32float32=3.12345678901234567890varpai_64float64=3.12345678901234567890fmt.Println("pai_32=",pai_32)fmt.Println("pai_64=",pai_64)varnum1complex64=1.2+3ivarnum2=complex(1.2,3)fmt.Printf("num1的数据类型是:%T\n",num1)fmt.Printf("num2的数据类型是:%T\n",num2)}运行结果为:num=0pai_32=3.1234567pai_64=3.1234567890123457num1的数据类型是:complex64num2的数据类型是:complex128数值类型默认值为0float32大约可以提供小数点后6到8位的精度float64可以提供小数点后15位的精度Complex64分为32位实数和32位虚数Complex128分为64位实数和64位虚数04运算符算术运算符关系运算符逻辑运算符位运算符赋值运算符其它运算符运算符描述实例实例结果+相加1+12-相减1-10*相乘1*11/相除1/21%求余(取模)1%2(1÷2=0……1)1++自增a=1a++(等价于a=a+1)a=2--自减a=1a—(等价于a=a-1)a=0+正号+11-负号-1-1+字符串相加(连)"hello"+"World"helloWorld4算数运算符两个运算数的类型必须相同并且为基本数据类型packagemainimport"fmt"funcmain(){ fmt.Println("1.0/2=",1.0/2)}运算结果为:1.0/2=0.5packagemainimport"fmt"funcmain(){ fmt.Println("1/2=",1/2)}运算结果为:1/2=04算数运算符 varaint=1 varbint a++ //正确 b=(a++) //错误,因为自增自减只能当作一个独立的语句使用 ++a //错误,因为自增自减只能写在变量的后面自增和自减在Go语言中构成单独的语句,不是表达式4算数运算符运算符运算含义实例==等于检查两个值是否相等,如果相等返回True否则返回False。(1==1)为True(1==2)为False!=不等于检查两个值是否不相等,如果不相等返回True否则返回False。(1!=2)为True(1!=1)为False>
大于检查左边值是否大于右边值,如果是返回True否则返回False。(1>0)为True(1>2)为False<
小于检查左边值是否小于右边值,如果是返回True否则返回False。(1<2)为True(1<0)为False>=大于等于检查左边值是否大于等于右边值,如果是返回True否则返回False。(1>=1)为True(1>=2)为False<=小于等于检查左边值是否小于等于右边值,如果是返回True否则返回False。(1<=2)为True(1<=0)为False4关系运算符运算符描述含义实例&&逻辑与逻辑AND运算符。如果两边的操作数都是True,则条件True,否则为False。(一假为假)varabool=truevarbbool=false(a&&a)为True(a&&b)为False(b&&b)为False||逻辑或逻辑OR运算符。如果两边的操作数有一个True,则条件True,否则为False。(一真为真)varabool=truevarbbool=false(a||a)为True(a||b)为True(b||b)为False!逻辑非逻辑NOT运算符。如果条件为True,则逻辑NOT条件False,否则为True。(结果取反)varabool=truevarbbool=false(!a)为False(!b)为True4逻辑运算符运算符含义按位与(&)两位全为1,结果为1,否则为0。(全1为1)按位或(|)两位有一个为1,结果为1,否则为0。(有1为1)按位异或(^)两位一个为0,一个为1,结果为1,否则为0。(相同为0,不同为1)pqp&qp|qp^q000000101111110100114位运算符运算符含义左移(<<)右边的数指定移动的位数,符号位不变,低位补0右移(>>)低位溢出,符号位不变,并用符号位补溢出的高位4位移运算符packagemainfuncmain(){ varaint=1 varbint=2 println("a&b=",a<<b) println("a&b=",a>>b)}运行结果为:a<<b=4a>>b=01的二进制为01,左移2位是100,转换成十进制为4。1的二进制为01,右移2位是00,转换成十进制是0。运算符描述含义实例=等于简单的赋值运算符,将一个表达式的值赋给一个左值c=a+b将a+b表达式结果赋值给c+=加等于相加后再赋值a+=b等价于a=a+b-=减等于相减后再赋值a-=b等价于a=a-b*=乘等于相乘后再赋值a*=b等价于a=a*b/=除等于相除后再赋值a/=b等价于a=a/b%=取模等于求余后再赋值a%=b等价于a=a%b<<=左移等于左移后赋值a<<=2等价于a=a<<2>>=右移等于右移后赋值a>>=2等价价于a=a>>2&=位于等于按位与后赋值a&=2等价于a=a&2^=异或等于按位异或后赋值a^=2等价于a=a^2|=位或等于按位或后赋值a|=2等价于a=a|24赋值运算符运算符描述实例&返回变量存储地址&a;取出变量的实际地址*指针变量*a;定义一个指针变量go不支持三元运算符若要实现三元运算,可以使用if-else进行实现4其它运算符05字符串拼接5种拼接方式5字符串拼接str=str1+str2str=fmt.Sprintf("%s%d%s",str1,i,str2)“+”sprintf()varstrs[]string=[]string{str1,str2}str:=strings.Join(strs,"")join()//定义字节缓冲变量btvarbtbytes.Bufferbt.WriteString(str1)bt.WriteString(str2)str:=bt.String()buffer.WriteString()varbuildstrings.Builderbuild.WriteString(str1)build.WriteString(str2)str:=build.String()buffer.Builder()packagemainimport( "bytes" "fmt")funcmain(){ varstr1="a" varstr2="b" varstrA=str1+str2 fmt.Println(strA) varstrB=fmt.Sprintf("%s%d%s",str1,1,str2) fmt.Println(strB) varbtbytes.Buffer bt.WriteString(str1) bt.WriteString(str2) strC:=bt.String() fmt.Println(strC)}运算结果为:aba1bab5字符串拼接06数据类型转换数据类型转换要求6数据类型转换valueOfTypeB=typeB(valueOfTypeA)Go语言所有的类型转换都必须显式的声明类型转换只能在定义正确的情况下转换成功,例如从一个取值范围较小的类型转换到一个取值范围较大的类型(将int16转换为int32)。当从一个取值范围较大的类型转换到取值范围较小的类型时(将int32转换为int16或将float32转换为int),会发生精度丢失(截断)的情况。只有相同底层类型的变量之间可以进行相互转换(如将int16类型转换成int32类型),不同底层类型的变量相互转换时会引发编译错误(如将bool类型转换为int类型)定义packagemainimport( "fmt" "reflect" "strconv")funcmain(){ //初始化一个32位整型值
varaint32=1234567890 fmt.Printf("a的值为:%d,类型为:%s\n",a,reflect.TypeOf(a)) b:=int16(a)//精度丢失
fmt.Printf("b的值为:%d,类型为:%s\n",b,reflect.TypeOf(b)) c:=strconv.Itoa(int(a)) fmt.Printf("c的值为:%s,类型为:%s\n",c,reflect.TypeOf(c))}运算结果为:a的值为:1234567890,类型为:int32b的值为:722,类型为:int16c的值为:1234567890,类型为:string6数据类型转换谢谢观看复合数据类型数组map映射切片01.03.02.目录01数组数组定义数组声明拷贝数组数组元素修改1数组一个由固定长度的特定类型元素组成的序列varvariable_name[size]type数组定义标准格式声明数组vara[3]int //声明一个数组名为a、类型为int、大小为3的数组a[0]=12 //为第一个元素填充数据a[1]=78 //为第二个元素填充数据a[2]=50 //为第三个元素填充数据a:=[3]int{12,78,50} //定义且声明数组内容a:=[3]int{12} //可以只填充部分数据varvariable_name=[size]type{value,……}初始化数组a:=[...]int{12,78,50} //编译器自行推断vara=[3]int{12,78,50} //定义且声明数组内容varvariable_name=[...]type{value,……}自行推断数组大小a:=[3]int{1:78,2:50} //填充指定位置1数组数组的每个元素可以通过索引下标来访问索引下标的范围从0开始到数据长度减1结束数组无法灵活扩容:在定义数组元素数量后,赋值元素变量个数必须要小于或者等于预设置的元素数量type指任意的基本类型,也可以是数组本身,实现多维数组在Go语言中数组是值类型而不是引用类型这意味着当数组变量被赋值时,将会获得原数组的拷贝,新数组中元素的改变不会影响原数组中元素的值数组特点packagemainimport"fmt"funcmain(){a:=[...]int{12,78,50}b:=a //将a数组复制给b数组
b[0]=60fmt.Println(a)fmt.Println(b)}1数组在Go中数组是值类型而不是引用类型。当数组变量被赋值时:将会获得原数组的拷贝。新数组中元素的改变不会影响原数组中元素的值。运行结果为:[127850][607850]packagemainimport"fmt"funcmain(){ vara[1]string//定义一个1个元素的string类型数组,string默认值为空
varb=[2]string{“a”,“b”}//定义一个2个元素的string类型数组
c:=[3]string{"a","b","c"}//定义并初始化一个3个空间的string类型数组
d:=[...]string{"a","b","c","d"}//自动推到元素个数
e:=d//拷贝数组
e[0]="e"//修改数组指定位置的值
fmt.Println(a,len(a))//打印a数组、a数组长度
fmt.Println(b) fmt.Println(c) fmt.Println(d,len(d)) fmt.Println(e,len(e))}1数组运行结果为:[]1[ab][abc][abcd]4[ebcd]402切片切片声明基于数组创建切片使用make()函数构造切片使用append()为切片动态添加元素使用copy()复制新的切片数组与切片相互转换2切片动态数组:切片可以按需自动扩充和缩减数组:长度固定现实中会面临:往数组内增加>len(数组名)个元素varname[]type=[]type{……}切片声明[]中不需要指定长度,即:长度是不固定的可以追加元素,在追加时可能使切片的容量增大,可以从数据中生成新的切片或者是声明新的切片。切片特点packagemainimport"fmt"funcmain(){vara[]int=[]int{10,11,12,13}fmt.Println(a,len(a))}运行结果为:[10111213]42切片varname[]type=数组名[开始位置:结束位置]基于数组创建切片特点结束位置的元素不取切片数量=结束位置下标-开始位置下标当缺省开始位置时,表示从连续的区域开头到结束位置当缺省结束位置时,表示从开始位置到整个连续区域末尾两者同时缺省时,与数组本身等效两者同时为0时,等于空切片,一般用于切片复位packagemainimport"fmt"funcmain(){a:=[5]string{"A","B","C","D"}varb[]string=a[1:2]fmt.Println(a)fmt.Println(b,len(b))}运行结果为:[ABCD][B]1packagemainimport"fmt"funcmain(){a:=[5]int{76,77,78,79,80}varb[]int=a[1:3] //取a数组的第1到第3个元素varc[]int=a[:3] //取a数组的第0到第3个元素vard[]int=a[1:] //取a数组的第1到最后一个元素vare[]int=a[:] //取a数组的第0到最后一个元素varf[]int=a[0:0] //空切片fmt.Println(a,len(a))fmt.Println(b,len(b))fmt.Println(c,len(c))fmt.Println(d,len(d))fmt.Println(e,len(e))fmt.Println(f,len(f))}运行结果为:[7677787980]5[7778]2[767778]3[77787980]4[7677787980]5[]02切片packagemainimport"fmt"funcmain(){a:=[5]string{"A","B","C","D","E"}varb[]string=a[1:3]fmt.Println("修改前的a数组:",a)fmt.Println("修改前的b切片:",b)
b[1]="2"fmt.Println("修改后的a数组:",a)fmt.Println("修改后的b切片:",b)}运行结果为:修改前的a数组:[ABCDE]修改前的b切片:[BC]修改后的a数组:[AB2DE]修改后的b切片:[B2]2切片切片本身不包含任何数据切片仅仅是底层数组的一个上层表示对切片进行的任何修改都将反映在底层数组中2切片packagemainimport("fmt")funcmain(){a:=[...]string{"A","B","C","D","E"}b:=a[1:3]fmt.Printf("数组a长度为:%d\n切片b容量为:%d",len(a),cap(b))}运行结果为:数组a长度为:5切片b容量为:4切片的长度是指切片中元素的个数切片的容量是指从切片的起始元素开始到其底层数组中的最后一个元素的个数切片的长度可以动态的改变(最大为其容量)任何超出最大容量的操作都会发生运行时错误2切片varname[]type=make([]type,size,cap)使用make()函数构造切片特点type指切片元素类型size指的是为这个类型分配多少个元素cap为预分配的元素数量cap设定后不会影响size,只是为了提前分配空间,降低多次分配空间造成的性能问题packagemainimport"fmt"funcmain(){vara[]int=make([]int,5,10)//创建一个切片,初始元素个数为5,并预留10个元素的存储空间a[0]=10a[4]=14fmt.Println(a)}运行结果为:[1000014]2切片append(name,value)append(name,[]type[value,value,value]...)使用append()为切片动态添加元素特点可以为切片追加单个或多个元素;或者是追加切片使用append()函数为切片动态添加元素时,如果空间不足以容纳足够多的元素,切片就会进行“扩容”,此时新切片的长度会发生改变。扩展容量小于1024个元素时按当前切片的容量(Cap)2倍扩容,扩展容量大于1024个元素时按Cap的1/4扩容。2切片packagemainimport"fmt"funcmain(){a:=[]int{10,20,30,40,50}b:=a[1:3]fmt.Println(a)fmt.Println(b)b=append(b,60)fmt.Printf(“第一次追加后,切片a为:%d切片a容量为:%d\n",a,cap(a))fmt.Printf(“第一次追加后,切片b为:%d切片b容量为:%d\n",b,cap(b))b=append(b,70,80,90,100)fmt.Printf(“第二次追加后,切片a为:%d切片a容量为:%d\n",a,cap(a))fmt.Printf(“第二次追加后,切片b为:%d切片b容量为:%d\n",b,cap(b))}运行结果为:[1020304050][2030]第一次追加后,切片a为:[1020306050]切片a容量为:5第一次追加后,切片b为:[203060]切片b容量为:4第二次追加后,切片a为:[1020306050]切片a容量为:5第二次追加后,切片b为:[203060708090100]切片b容量为:82切片copy(destSlice,srcSlice)使用copy()复制新的切片特点destSlice为复制的目标切片srcSlice为数据来源切片目标切片必须分配过空间且足够承载复制的元素个数,并且来源和目标的类型必须一致。copy()函数来源切片和目标切片可以共享同一个底层数组,甚至有重叠也没有问题。packagemainimport"fmt"funcmain(){a:=[]int{0,1,2,3,4,5}b:=[]int{10,11,12}fmt.Println(a)fmt.Println(b)copy(b,a)//只会复制a的前3个元素到b中
fmt.Println(a)fmt.Println(b)}运行结果为:[012345][101112][012345][012]2切片packagemainimport"fmt"funcmain(){//切片转成数组
s:=[]int{10,11,12}vara[3]intfmt.Println(copy(a[:],s))fmt.Println(a)}运行结果为:3[101112]packagemainimport"fmt"funcmain(){//数组转成切片
a:=[...]int{10,11,12}b:=make([]int,3)fmt.Println(copy(b,a[:]))fmt.Println(b)}运行结果为:3[101112]数组与切片相互转换时:需要使用[:]将数组伪装为切片类型后再进行赋值,否则无法通过编译数组与切片中的元素类型必须相同03map映射map定义使用make()函数创建map用切片作为map的值使用delete()函数删除元素3map映射一种无序的key/value的集合;能够通过key值快速检索数据值。map这种数据结构在其他编程语言中也称为字典、映射或哈希表。Golang的map由两种重要的结构构成:hmap和bmap。map定义声明map集合varnamemap[key_type]value_type语法说明如下:(a).name为map变量名;(b).key_type为键类型;(c).value_type为键对应值类型。packagemainimport"fmt"funcmain(){a:=map[int]string{110:"报警电话",120:"急救电话",119:"消防电话"}fmt.Println(a)}运行结果为:map[110:报警电话119:消防电话120:急救电话]3map映射make(map[KeyType]ValueType,[cap])使用make()函数创建map特点map可以在声明的时候填充元素,也可以单独填充元素map中的数据都是成对出现的map类型的变量默认初始值为nil其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。packagemainimport"fmt"funcmain(){a:=make(map[string]int,10)a["报警电话"]=110;a["急救电话"]=120;a["火警电话"]=119;fmt.Println(a)}运行结果为:map[急救电话:120报警电话:110火警电话:119]3map映射运行结果为:[map[A:1a:2]map[]]packagemainimport"fmt"funcmain(){//map的值为切片:
a:=make(map[int][]string,2)a[1]=make([]string,0,2)a[1]=append(a[1],"A","a")fmt.Println(a)}packagemainimport"fmt"funcmain(){//切片的元素类型为map:
b:=make([]map[string]int,2)b[0]=make(map[string]int,2)b[0]["A"]=1b[0]["a"]=2fmt.Println(b)}运行结果为:map[1:[Aa]]3map映射delete(map,key)使用delete()函数删除元素特点如果要删除的key不存在,那么这个调用将什么都不发生,也不会有什么副作用但是如果传入的map变量的值是nil,该调用将导致程序抛出异常(panic)packagemainimport"fmt"funcmain(){a:=map[int]string{110:"报警电话",120:"急救电话",119:"消防电话"}delete(a,110)fmt.Println(a)}运行结果为:map[119:消防电话120:急救电话]谢谢观看流程控制if分支结构语句switch语句01.02.目录01if分支结构语句单分支双分支多分支注意事项1if分支结构语句条件语句:根据是否满足条件,有选择地跳转到相应的执行序列。if语句单分支双分支多分支if分支结构语句一般会由关键字if、条件表达式和由花括号包裹的代码块组成。其中代码块为:包含了若干表达式和语句的序列。在Go语言中,代码块必须由花括号包裹。多分支if<condition>{<Executestatement>}elseif<condition>{<Executestatement>}else{<Executestatement>}双分支if<condition>{<Executestatement>}else{<Executestatement>}单分支if<condition>{<Executestatement>}1if分支结构语句packagemainimport"fmt"funcmain(){vara=1varb=2//如果if语句条件为真,则会执行相对应的代码ifa<=b{fmt.Println("a<=b")}else{fmt.Println("a>b")}}运行结果为:a<=bif语句的条件判断表达式不需要也不能加小括号,即
(),这是Go语言与其他语言if语句的区别。if语句后面的大括号必须跟条件表达式写在一行,不能换行写,换行写会导致编译错误。1if分支结构语句packagemainimport"fmt"funcmain(){
vara=10varb=20//如果if语句条件为真,则不会执行elseif相对应的代码ifa>5{fmt.Println("a>5")}elseifa<b{fmt.Println("a<b")}}运行结果为:a>5if语句与elseif语句是互斥的执行因为if语句已经成立了,所以elseif里面的语句未能执行。1if分支结构语句packagemainimport"fmt"funcmain(){vara=11varb=5ifa>20{fmt.Println("a>20")}elseifa>15{fmt.Println("a>15")}elseifa>10{fmt.Println("a>10")}elseifa>b{fmt.Println("a>b")}}运行结果为:a>10多个elseif语句,会被依次判断,直到其中一个满足条件的被执行1if分支结构语句packagemainimport"fmt"funcmain(){vara=10ifa>5{ifa>20{fmt.Println("a>20")}elseifa>10{fmt.Println("a>10")}else{fmt.Println("a>5")}}else{fmt.Println("a<=5")}}运行结果为:a>5if语句里面可以嵌套多层的if、elseif以及else1if分支结构语句if分支结构语句使用注意事项条件语句不需要使用括号()将条件包含无论语句体内有几条语句,花括号{}都是必须存在的左花括号{必须与if或者else处于同一行在if之后,条件语句之前,可以添加变量初始化语句,使用;间隔在有返回值的函数中,不允许将“最终的”return语句包含在if...else...结构中,否则会编译失败1if分支结构语句02Switch选择语句有表达式无表达式2Switch选择语句Switch选择语句:根据不同条件来执行不同动作,每一个条件对应一个case分支。switch语句有表达式无表达式switch语句的执行过程从上至下,直到找到匹配项匹配项后不需要再加break每一个switch语句只能包含一个可选的default分支,若没有找到匹配项,会默认执行default分支中的代码块switch表达式{//case后的条件可以是多个值casevalue1,value2:<Executestatement>1casevalue3:<Executestatement>2//若以上条件都不满足,则执行下面的语句default:
<Executestatement>n}有表达式switch{case<condition>1:<Executestatement>1case<condition>2:<Executestatement>2//若以上条件都不满足,则执行下面的语句default: <Executestatement>n}无表达式2Switch选择语句2Switch选择语句packagemainimport"fmt"funcmain(){score:=80switchscore{case90:fmt.Println("A")case80:fmt.Println("B")case70:fmt.Println("C")default:fmt.Println("D")}}运行结果为:B首先定义整数变量
score接着使用switch语句判断score如果是90,则打印A如果是80,则打印B如果是70,则打印C其他情况,则打印D2Switch选择语句packagemainimport"fmt"funcmain(){score:=80ifscore==90{fmt.Println("A")}elseifscore==80{fmt.Println("B")}elseifscore==70{fmt.Println("C")}else{fmt.Println("D")}}运行结果为:B将上述代码改成if-else写法如果是90,则打印A如果是80,则打印B如果是70,则打印C其他情况,则打印D2Switch选择语句packagemainimport"fmt"funcmain(){switchscore:=80;score{case90:fmt.Println("A")case80:fmt.Println("B")case70:fmt.Println("C")default:fmt.Println("D")}}运行结果为:B可以在判断条件前面定义变量用;号分割2Switch选择语句packagemainimport"fmt"funcmain(){score:=66switch{casescore>90:fmt.Println("A")casescore>80:fmt.Println("B")casescore>70,score>60://可以放多个条件
fmt.Println("C")default:fmt.Println("D")}}运行结果为:Cswitch后面可以没有条件表达,将条件放在case的后面,也可以放多个条件,但每个case后面的条件不能重复。2Switch选择语句packagemainimport"fmt"funcmain(){switchscore:=80;score{case90:fmt.Println("A")case80:fmt.Println("B")fallthrough//强制执行下一case后面的代码case70:fmt.Println("C")default:fmt.Println("D")}}运行结果为:BCswitch语句支持使用fallthrough关键字强制执行下一case里面的代码2Switch选择语句switch语句还可以被用于type-switch来判断某个interface变量中实际存储的变量类型TypeSwitchswitchx.(type){/*定义任意个数的case*/casetype1:statement(s)casetype2:statement(s)/*可选*/default: statement(s)}语法格式2Switch选择语句packagemainimport"fmt"funcmain(){varxinterface{}switchi:=x.(type){
casenil:fmt.Printf("x的类型:%T\r\n",i)caseint:fmt.Printf("x是int型")casefloat64:fmt.Printf("x是float64型")casefunc(int)float64:fmt.Printf("x是func(int)型")casebool,string:fmt.Printf("x是bool或string型")default:fmt.Printf("未知类型")}}运行结果为:x的类型:<nil>通过switch语句判断类型2Switch选择语句Switch选择语句注意事项switch/case后是一个表达式(即:常量,变量,一个有返回的函数都可以);case后的各个表达式的值的数据类型,必须和switch的表达式数据类型一致;case后面可以带多个表达式,使用逗号间隔;case后面的表达式如果是常量值,则要求不能重复;case后面不需要带break,程序匹配到一个case后就会执行对应的代码块,然后退出switch,如果一个都匹配不到,则执行default;default语句不是必须的;switch后也可以不带表达式,类似if--else分支来使用;switch后也可以直接声明一个变量,分号结束,不过不推荐;switch穿透:如果在case语句增加fallthrough,则会继续执行下一个case,默认只穿透一层;type-switch:来判断interface变量中实际指向的变量类型。谢谢观看循环控制for循环break语句01.02.目录03.continue语句04.goto跳出循环01for循环for循环语法几种循环方式for和rangeGo语言中的循环逻辑通过for关键字实现Go语言没有while关键字,不存在while循环for循环可以执行指定循环次数,从而让程序多次执行相同的代码块for循环用的最多的地方是:遍历数组或切片等Go语言中的循环for循环三种方式常见的for循环,在指定条件下运行,支持初始化语句条件表达式控制循环:当满足条件时会进入循环。进入循环后,当条件不满足时会跳出循环。无限循环:不断的执行程序,也称作死循环,通常会配合break关键字进行使用。1for循环语法详解forinit;condition;post{expression}for循环语法init:一般为赋值表达式,给控制变量赋初值condition:关系表达式或逻辑表达式,循环控制条件post:一般为赋值表达式,给控制变量增量或减量判别赋值表达式init是否满足给定condition条件,若其值为真,满足循环条件,则执行循环体内语句,然后执行post,进入第二次循环,再判别condition;否则判断condition的值为假,不满足条件,就终止for循环,执行循环体外语句1for循环packagemainimport"fmt"funcmain(){/*for初始化条件;判断条件;条件变化{ 1+2+…+100累加
}*/sum:=0fori:=1;i<=100;i++{sum+=i}fmt.Println("sum=",sum)}运行结果为:sum=50501for循环packagemainfuncmain(){s:="abc"fori,n:=0,len(s);i<n;i++{println(s[i])}}运行结果为:979899packagemainimport"fmt"funcmain(){s:="abc"n:=len(s)forn>0{fmt.Println(s[n-1])n--}}运行结果为:9998971for循环packagemainimport"fmt"funcmain(){s:="abc"for{fmt.Println(s)}}运行结果为:abcabcpackagemainfunclength(sstring)int{println("calllength.")returnlen(s)}funcmain(){s:="abcd"fori,n:=0,length(s);i<n;i++{println(i,s[i])}}运行结果为:calllength.09719829931001for循环for[conditio
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论