注意事项四
1)数组
语法格式: var 变量名 [数组长度] 数据类型//长度整数且大于0,无空数组(与切片不同)
初始化数组语法格式:var nums=[5]int{1,2,3,4,5} var nums=[...]int{1,2,3,4,5}
多维数组----声明方式:var variable_name [size1][size2]...[sizen] variable_type
注意:将数组作为函数参数进行传递,通过值传递,原数组保持不变;
package main
import "fmt"
//遍历数组的两种方式
func main() {
a:=[5]float64{3.4,2.3,45.6,66.7,99.2}
b:=[...]int{1,2,3,4,5}
for i:=0;i<len(a);i++{
fmt.Print(a[i],"\t")
}
fmt.Println()
for _,value:=range b{
fmt.Print(value,"\t")
}
}
2)切片
数组长度不可变---切片(slice)是可变长度的序列,每个元素是相同的类型,可追加元素;
切片没有自己的任何数据---只是底层数组的引用---对切片的任何修改都将反映在底层数组;
数组---值类型 切片---引用类型
语法格式:var identifier []type//空切片---默认为nil---长度为0;
使用make()函数创建切片:var slice1 []type=make([]type,len) 简写---slice2:=make([]type,len)
//创建切片时可以指定容量,其中capacity为可选参数:make([]T,length,capacity)
-----初始化-----
第一种:直接初始化---s:=[] int{7,8,9}
第二种:通过数组截取来初始化切片----arr:=[5] int{7,8,9} s:=arr[startIndex:endIndex]//前闭后开
第三种:通过切片截取来初始化切片---[lower-bound:upper-bound]
package main
import "fmt"
func main() {
num:=[]int{9,8,7,6,5,4,3,2,1}//自定义切片
printSlice(num)
fmt.Println("num=",num)//原始切片
fmt.Println("num[2:5]=",num[2:5])
fmt.Println("num[:3]=",num[:3])//默认下限
fmt.Println("num[4:]=",num[4:])//默认上限
printSlice(num[2:5])
printSlice(num[:3])
}
func printSlice(x []int) {
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)//分别是切片的长度、容量、自身
}
修改切片数组---当多个切片共享相同底层数组时---对元素的更改将在数组中反映出来;
3)切片的append()函数和copy()函数
append()---追加一个or多个元素,也可以是一个切片;会改变切片所引用的数组,从而影响引用同一数组的切片;
---容量不够时,Go会创建一个新的内存地址来存储元素;
利用append()删除中间元素----a:=int(len(numbers)/2) numbers=append(numbers[:a],numbers[a+1:]...)
copy()---返回值是复制元素的个数;不会建立源切片与目标切片之间的联系,互不影响;
package main
import "fmt"
func main() {
fmt.Println("1.--------------------------")
num:=make([]int,0,20)//创建切片-长度为0-容量为20
printSlices("num:",num)
num=append(num,1)//向切片添加一个元素
printSlices("num:",num)
num=append(num,2,3,4,5,6,7,8,9)//向切片添加多个元素
printSlices("num:",num)
fmt.Println("2.--------------------------")
a:=[]int{10,20,30,40,50,60,70,80}//在切片num上追加一个切片a
num=append(num,a...)//注意---后面...
printSlices("num:",num)
fmt.Println("3.--------------------------")//删除会改变切片的地址---追加不会修改地址
num=num[1:]//删除第一个元素
printSlices("num:",num)
num=num[:len(num)-1]//删除最后一个元素
printSlices("num:",num)
ith:=int(len(num)/2)//获取中间数的排位数,而不是下标
fmt.Println("中间数为:",num[ith])
num=append(num[:ith],num[ith+1:]...)
printSlices("num:",num)
fmt.Println("4.--------------------------")//复制不改变地址
//创建一个容量是num两倍的num1
num1:=make([]int,len(num),cap(num)*2)
n:=copy(num1,num)//copy()函数返回值---复制的个数
fmt.Println("复制个数:",n)
printSlices("num1:",num1)
//验证copy()不会建立两个切片的联系
num[0]=10000
num1[len(num1)-1]=1000
printSlices("num1:",num1)
printSlices("num:",num)
}
func printSlices(name string,x []int) {//输出切片信息
fmt.Print(name,"\t")
fmt.Printf("addr:%p \t len=%d \t cap=%d \t slice=%v \n",x,len(x),cap(x),x)//这里%p---地址
}
4)Go语言中—字符串和数值类型的相互转换
strconv包中的Atoi()、Itia()、parse系列函数、format系列函数、append系列函数等实现了如string、int、int64、float等数据类型之间的转换;
Atoi():字符串转整型---func Atoi(s string) (i int,err error)//返回值中的i为转换成功的整型,err为转换失败对应的错误信息;
Itoa():整型转字符串---func Itoa(i int) string
Parse系列函数---将字符串转为指定类型的值;
ParseBool():func ParseBool(str string) (value bool, err error)//将字符串转换为 bool 类型的值----只能接受 1、0、t、f、T、F、true、false、True、False、TRUE、FALSE,其它的值均返回错误;
ParseInt():func ParseInt(s string, base int, bitSize int) (i int64, err error)//用于返回字符串表示的整数值(可以包含正负号)----(base-指定进制,取值范围是 2 到 36。如果 base 为 0,则会从字符串前置判断,“0x”是 16 进制,“0”是 8 进制,否则是 10 进制;bitSize-指定结果必须能无溢出赋值的整数类型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64;返回的 err 是 *NumErr 类型的,如果语法有误,err.Error = ErrSyntax,如果结果超出类型范围 err.Error = ErrRange)
ParseUnit():func ParseUint(s string, base int, bitSize int) (n uint64, err error)//似于 ParseInt() 函数,但 ParseUint() 函数不接受正负号,用于无符号整型;
ParseFloat():func ParseFloat(s string, bitSize int) (f float64, err error)//将一个表示浮点数的字符串转换为 float 类型---(s-合乎语法规则,函数会返回最为接近 s 表示值的一个浮点数(使用 IEEE754 规范舍入);bitSize 指定了返回值的类型,32 表示 float32,64 表示 float64;返回值 err 是 *NumErr 类型的,如果语法有误 err.Error=ErrSyntax,如果返回值超出表示范围,返回值 f 为 ±Inf,err.Error= ErrRange);
Format系列函数---将给定类型数据格式化为字符串类型;
FormatBool():func FormatBool(b bool) string//一个 bool 类型的值转换为对应的字符串类型;
FormatInt():func FormatInt(i int64, base int) string//将整型数据转换成指定进制并以字符串的形式返回---(参数 i 必须是 int64 类型,参数 base 必须在 2 到 36 之间,返回结果中会使用小写字母“a”到“z”表示大于 10 的数字);
FormatUint():func FormatUint(i uint64, base int) string//与 FormatInt() 函数的功能类似,但是参数 i 必须是无符号的 uint64 类型;
FormatFloat():func FormatFloat(f float64, fmt byte, prec, bitSize int) string//用于将浮点数转换为字符串类型(bitSize---表示参数 f 的来源类型(32 表示 float32、64 表示 float64),会据此进行舍入;fmt ---表示格式,可以设置为“f”表示 -ddd.dddd、“b”表示 -ddddp±ddd,指数为二进制、“e”表示 -d.dddde±dd 十进制指数、“E”表示 -d.ddddE±dd 十进制指数、“g”表示指数很大时用“e”格式,否则“f”格式、“G”表示指数很大时用“E”格式,否则“f”格式;prec---控制精度(排除指数部分):当参数 fmt 为“f”、“e”、“E”时,它表示小数点后的数字个数;当参数 fmt 为“g”、“G”时,它控制总的数字个数。如果 prec 为 -1,则代表使用最少数量的、但又必需的数字来表示 f);
package main
import (
"fmt"
"strconv"
)
func main(){
var sa []string//sa:=make([]string,0,20)
printSliceMsg(sa)
//append函数追加时,容量不够-Go回创建新的切片变量存储元素;所以切片容量是成倍增长的;
for i:=10;i<20;i++{
sa=append(sa,strconv.Itoa(i))//Itoa():整型转字符串
printSliceMsg(sa)
}
printSliceMsg(sa)
}
//输出格式化信息
func printSliceMsg(sa []string){
fmt.Printf("addr:%p \t len:%v \t cap:%d \t value:%v \n",sa,len(sa),cap(sa),sa)//地址、长度、容量、值
}
5)map
键值对—(key-value)只能通过key获取,无序性—每次打印出来的map不同;
长度可扩展----len()函数获取键值对的数量—不能使用cap()函数计算容量;
同一个map中的key是唯一的;
map与切片类似--引用类型--将map赋值给一个新变量时,指向同一块内存(底层数据结构)
声明方式:
1)var 变量名 map[key类型]value类型//未初始化默认值为nil----nil map不能存放键值对;除非声明时初始化||使用make()函数分配内存空间;
2)变量名 := make(map[key类型]value类型)//不初始化map,map也不等于nil;
package main
import "fmt"
func main() {
//1.声明时同时初始化
var class_=map[string]int{//初始化的时候最后一个元素要加,
"class1":10,
"class2":20,
"class3":30,
"class4":40,
}
fmt.Println(class_)
//短变量声明初始化方式
language:=map[string]float64{"java":4,"c":3.9,"go":4.8,"c++":4.6}
fmt.Println(language)
fmt.Println("--------------------")
//2.先创建再赋值
country:=make(map[string]string)
country["China"]="Beijing"
country["Japan"]="Tokyo"
country["France"]="Paris"
fmt.Println(country)
fmt.Println("--------------------")
//3.遍历的三种情况
//第一种key、value---无序的
for k,v:=range language{
fmt.Println("语言",k,"评分",v)
}
//第二种只有value
for _,v:=range language{
fmt.Println("评分",v)
}
//第三种只有k
for k:=range language{
fmt.Println("语言",k)
}
fmt.Println("--------------------")
//4.通过key检查元素是否在集合中 通过value,ok:=map[key]---ok为bool型
if value,ok:=language["php"];ok{
fmt.Println("评分",value)
} else{
fmt.Println("未检索到!")
}
fmt.Println("--------------------")
//5.delete(map,key)//删除集合的某个元素---参数为map、key---不返回任何值
fmt.Println("删除前",language)
if _,ok:=language["c"];ok{//首先得查找这个key是否在集合中
delete(language,"c")
}
fmt.Println("删除后",language)
//清空集合---唯一方式就是重新make一个新的map;
//language= map[string]float64{}//第一种清空方式
language=make(map[string]float64)
fmt.Println("清空后",language)
}