五 函数和参数
函数和参数,函数内声明的变量是局部变量,函数执行结束后,被系统回收,局部变量的生命周期和函数相同。
函数的格式:func 函数名()返回值的类型{函数体 返回值的类型return},若函数有返回值,还需要定义返回值的类型。
1、参数:在设置函数的参数的时候,参数的数据类型相同的可以合并:如参数1 参数2 参数数据类型(string)。
1)无参: func 函数名(){函数体}
2)有参:
①、一个参数:func 函数名(参数 参数类型){函数体}
②、多个参数:func 函数名(参数1、参数2…参数n(类型合并) 参数类型…参数 参数类型){函数体}
③、不定长参数:类型为切片容器,可以变长的数据容器,类似与java中的集合,
list、map:func 函数名(参数 … 参数类型【必须放在参数列表的,后面不能有其他参数,可以在不定长参数的前面在添加其他参数】){函数体},不定长参数必须放在参数列表的末尾。
3)返回值: 函数执行的结果
①、有返回值的函数,必须要定义返回值的数据类型
②、预定义返回值的名称
func mian(){
a, b, c, d := result(9, 3)
fmt.Printf(“加%d\\n 减%d\\n 乘%d\\n 除%d\\n”,a,b,c,d)
}
func result(a,b int)(jia,jian ,chen ,chu int){
jia = a+b
jian = a-b
chen = a*b
chu = a/b
return
}
③、匿名函数:有封装的必要却没有复用的价值,没有必要长久存在,用于准确区分全局变量和成员变量各自的任务。不相干涉。
延时执行defer func(){函数体}()
:并发执行go func(){函数体}()
defer func(name string, age int) {
fmt.Println(name,age)
}(“张三”,20)
④、闭包函数:返回函数的函数,可以保存内部函数的状态。
func函数名(参数 返回类型…)func()string {函数体}
没有闭包时,就只能借助全局变量来保存函数的状态数据。
缺点:
①:全局变量泛滥。
②:不便于管理。
六 复合数据类型:特殊的数据结构
1 指针(pointer):&x:取变量x的地址,对变量取地址。
*aPointer:取地址的值,对地址取值。
*int:代表int型指针,代表指向一块存有int型数据的内存的地址。
**int:二级整型指针,指向指针的指针。一个指针指向另外一个指针,读取其中存储的地址值再根据那个地址值读取指向指针中的值。
①存储地址的容器,存储字节的地址,指针存储的是一个整形的十六进制地址(整型指针),对值取地址,对地址取值。
②、有指针就标志着这是一个底层的语言。
③、整型指针变量的值为空(nil),而整型数据的默认值为0。
④、声明变量时,系统开辟了一块内存【地址】,里面的值是赋给变量的值。
⑤、先定义的原始变量,修改其中的值,会直接改变原变量。指针如果没有重新赋值,永远指向同一块地址。
2) 数组(array):
①、定长定类型的元素容器,不能改变长度。
②、根据下标序号访问修改元素。查询对应的数据需要遍历数组的下标进行查询,因此速度比较慢。数组下标从0开始
③、创建数组 array:=[…]int{1 ,2,3,4,5,6,7,8,9}
④、数组的长度:内建函数len(array)
⑤、所有根据下标序号进行访问元素的容器,都不能出现下标越界的问题。
⑥、访问数组 元素:for index,value:=range array{fmt.println(index,value:)},获取数组的下标和对应的值,不需要获取的直接用下横杆代替.
3) 切片(slice):能动态扩容的元素容器 ,根据下标序号访问元素。
①、不定长,定类型的元素容器。其实切片就是一个不定长的数组。
②、切片就是从数组上截取下来的片段。slice:=arryay[start:end];start代表开始下标,默认开始从0开始,end代表结束下标(本身不包含)不写默认截取到尾部,即包括头部不包含尾部(包头部包尾),左闭右开。
③、切片可以对切片再进行截取得到新的切片。sunSlice:=slice[start:end].
④ 内建函数,append(任意类型的切片slice,xxx)向切片中追加数据,添加到尾部.可以追加一个,多个元素,还可以直接追加以块切片.
⑤ 动态扩容:容量就是该切片所能容纳的最大数据.容量内建函数(cap)captivity.内建函数make(创建的内容,长度,容量):创建指定长度和容量的切片.当切片容量装满以后需要扩容时,底层是重新找了一块更大的内存(内存足够时翻倍扩容1变2,2变4…,内存不够的话第一次翻倍后就进行添加,两个两个的增加)将原有的数据复制到新的内存中,老的内存如果没有对应的操作会被回收掉,若在其身上有其他操作,那么还会继续保留.扩容后地址发生改变.没有指定容量时,容量默认和长度一样.
⑥ 切片不是拷贝,是地址引用.牵一发而动全身,即修改切片内容会对原数组和其他切片参数改变,在地址没有发生改变的情况下.但是如果某一切片发生了扩容操作,地址发生了改变,那么该切片就会拷贝独立出来,该切片的操作不会影响其他切片,其他切片的改变也不会影响到该切片.
4) 映射:存储键值对的数据,根据健访问值,查询速度很快。
① var scoreMap map[String ] int =map[string]int {}
xxxMap:=map[string int{}
定义string为健int为映射.
② 当查一个不存在的健的时候,会有一个默认的值0,然而这是很不合理的.
③ 校验机制:映射名xxx,ok:=xxxMap[string健值]
当ok为true时,代表健值存在,有对应的值,若ok为false,代表健不存在;
func main() {
scoreMap:=map[string]int{}
scoreMap [“汪大虎”] = 59
scoreMap [“吴正贤”] = 80
scoreMap [“方小旭”] = 70
if score,ok := scoreMap[“陈家勇”];ok==true{
fmt.Printf(“吴正贤的成绩是%d”,score)
} else {
fmt.Println(“没有这个人”)
}
}
5) 函数:函数也是一种复合数据类型。列如闭包函数,匿名函数用一个变量去接收该闭包函数。
6)结构体:相当于java当中的类。
①、%p:地址占位符,指针占位符。