一 数组
1.1 一维数组
数组是同一种数据类型元素的集合,go语言中,数组可以修改数组成员内容,但不可以改变数组大小。
#声明长度为3 类型为int的数组
var a [3]int
数组的函数签名为
var 数组变量名称 [元素数量]T
数组的长度必须是常量,且长度也是数组类型的一部分,例如[5]int 与[2]int的类型是不同的。
也可以不指定数组长度,使用三个点
var boolArray = [...]bool{true.false,false,true,false}
for循环遍历数组的方式:
for i :=0; i
for index,value := range boolArray{}
1.2 二维数组
x := [2][2]string{
{"a", "b"},
{"c", "d"},
}
//二维数组的遍历
for _,rows := range(x) {
for _,col := range(rows){
fmt.Println(col)
}
}
二 切片
数组的长度是固定的,且长度属于数组的一部分,因此有很多局限性;在实际开发过程中 ,会使用较多的是切片。
切片是一个拥有相同类型元素的可变长序列,它是基于数组类型做的一层封装,支持自动服务器托管网扩容,切片是一个引用类型,内部结构包含地址、长度和容量。切片一般用于快速的操作一块数据。
函数签名为
var a[]
可以使用make函数来构造切片
d := make([]int,5,10)
表示容量是10 已经有5个元素 且元素的数据类型是int类型
可通过cap(d)来获得切片的容量,通过len(d)来获得切片的长度
切片的本质就是对底层数组的封装,包含了三个信息:底层数组的指针、切片的长度len,切片的容量cap
举个例子假如现在有一个数组
a := [8]int{0,1,2,3,4,5,6,7}
切片s1 := a[:5]
切片s2 := a[3:6]
通过上面图片可知,切片中的指针会指向数组的起始位置。
2.1 切片的赋值拷贝
func main() {
//创建一个长度为8的整数切片
x := make([]int,8)
b := x
b[0] = 100//修改b的值 a也会发生变化
fmt.Println(x)
fmt.Println(b)
}
//[100 0 0 0 0 0 0 0]
//[100 0 0 0 0 0 0 0]
切片的底层是数组,因此也支持索引遍历及for ind,val :=range x 遍历这两种方式。
2.2 切片的append扩容
//切片一定要初始化之后才可以使用
var a []int //此时并没有申请内存
a = append(a,10)
a = append(a,1,2,3,4,5)
fmt.Println(a)
2.3 切片的copy
a := []int{1, 2, 3, 4}
b := a
fmt.Println(a)
fmt.Println(b)
b[0] = 10000
fmt.Println(a)
fmt.Println(b)
//代码输出结果为:
[1 2 3 4]
[1 2 3 4]
[10000 2 3 4]
[10000 2 3 4]
因为切片是引用类型,所以a与b实际上都是指向了同一块内存地址,因此修改b的同时a也会发生变化。
go内置的copy函数可迅速的将一个切片的数据复制到另一个切片空间中,copy的函数签名如下
copy(targetSlice,srcSlice []T)
a := []int{1, 2, 3, 4}
b := make([]int,5,5)
copy(b,a)
fmt.Println(a)
fmt.Println(b)
b[0] = 10000
fmt.Println(a)
fmt.Println(b)
切片用来删除元素
a := []string{"a","b","c","d","e","f"}
//如果想删除c 可以使用索引进行删除
a = append(a[:2],a[3:]...)
三 map
map是一种无序的基于key-value的数据结构,go中的map是引用类型,必须初始化才能使用,类似切片
3.1 map的定义
map[keyType]valueType
keyType表示键的类型,valueType表示键对应的值的类型
map类型的变量默认初始值为nil,需要使用make函数来进行分配,
make(map[keyType]ValueType,[cap])
cap表示map的容量,该参数不是必须的,但应该在初始化的时候为map
指定一个合适的容量
func main() {
//声明map类型
var a map[string]int
fmt.Println(a == nil) //true
//map的初始化
a = make(map[string]int,8)
fmt.Println(a == nil) //false
//map添加键值对
a["kobe"] = 24
a["jordan"] = 23
// fmt.Println(a)
// fmt.Printf("type:%T",a)
//判断一个数据是否在map中
value,ok := a["kobe"]
if ok {
fmt.Printf("---%vn",value)
}
for k,v := range a {
fmt.Printf(k,v)
}
}
元素类型为map的切片
//对切片进行分配内存
var mapSlice = make([]map[string]int,8,8)
//对map进行分配内存
mapSlice[0] = make(map[string]int,8)
mapSlice[0]["kobe"] = 24
fmt.Println(mapSlice)
四 函数
go中支持函数、匿名函数和闭包
func cal(a int,b int, ...string)int{
return a+b
}
函数接收两个int类型数据,然后接收不定长的string类型
4.1 defer
延迟执行
func main() {
fmt.Println("starting")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("end")
}
执行结果
starting
end
3
2
1
根据上面的代码结果可知,defer就是在函数完成调用之后执行的操作,且最后的defer语句,最先执行类似于压栈操作。主要用来处理资源的释放问题。
4.2 作用域
在函数内部,会首先在函数内部寻找该变量,如果找不到,则可以访问全局变量。
在go中函数可以作为一个变量,由下面的代码块可知,函数可以赋值给一个变量,然后也可以直接调用。
func calnum(a int,b int)int{
return a+b
}
func main() {
test := calnum
res := test(3,4)
fmt.Println(res)
}
在go中,也可以讲函数作为参数传递给另一个函数,
func add(a,b int)int{
return a+b服务器托管网
}
func sub(a,b int)int{
return a-b
}
func calc(x,y int,op func(int,int) int) int{
return op(x,y)
}
func main() {
r1 := calc(100,200,add)
fmt.Println(r1)
r2 := calc(100,200,sub)
fmt.Println(r2)
}
4.3 匿名函数
匿名函数就是没有函数名的函数,匿名函数多用于实现回调函数与闭包。匿名函数格式如下所示
func(参数)(返回值){
函数体
}
func main() {
func(){
fmt.Printf("匿名函数")
}()//加上括号 立即执行
}
//闭包 = 函数 + 外层变量的引用
func a() func(){
name := "kobe"
//函数的返回值是一个函数
return func(){
fmt.Println("hellow biabo: ",name)
}
}
func main() {
func(){
fmt.Printf("匿名函数n")
}()//加上括号 立即执行
r := a() //相当于一个闭包
r()//相当于执行了函数内部的func
}
在函数中,如果遇到错误的地方,程序可能会崩溃panic,可以使用defer 函数来使得函数继续向下执行。
func b() {
defer func() {
err := recover()
if err != nil {
fmt.Println("func b is error: ")
}
}()
panic("pancin is b")
}
对于上面的函数来说,如果没有defer函数,则b函数会有panic导致函数无法正常往下执行,但如果在可能会发生panic的代码块前面加上defer延迟调用的话,就可以处理可能出现的panic现象。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
常见线程安全类 String Integer StringBuffer Random Vector Hashtable java.util.concurrent 包下的类 这里说它们是线程安全的是指,多个线程调用它们同一个实例的某个方法时,是线程安全的。也可以…