一、字符串和数组
首先这里没有集合与数组的概念,可以将切片当成List集合这类来看代
数组从一开始初始化之后就是固定的,而切片不是,是可变长的
1、字符串
一般用来存储可读字符,因为Go语言要求为UTF-8编码,所以一般将字符串按照UTF-8进行理解
字符串本质上是不可变字节序列,for range并不支持非UTF-8编码遍历,因为程序“不知道”对应几个字节对应一个字符,在这,len()函数在Go语言中返回的是字符串结束而非字符个数
string[M:N],为左闭右开取得字符
新字符串为对应字符共享的
string的函数
strings:提供搜索、比较、切片与字符串连接功能
bytes:对字符串底层操作,可以使用[]bytes转化类型后进行处理
strconv:主要是字符串与其他类型的转换,比如整数、布尔
unicode:主要是对字符串中的单个字符做判断,比如IsLetter、IsDigit、IsUpper等
2、数组
先看如何定义的数组
var a [3]int
默认都是0
var b [3]int = [3]int{1, 2, 3}
定义数组的同时进行初始化的赋值
c := [...]int{1, 2, 3}
省略了数组长度,其长度由后面初始化值的长度确认
d := [...]int{4, 4:1, 1:2}
其实就是部分赋值,使用的index:value方式,比如4:1就是给下标4的元素赋值1
3、slice切片
结构定义
是表示拥有相同类型元素的可变长序列,且slice的定义与数组的定义非常像,就是没有固定长度的数组
基本的定义
s := []int{1,2,3,4}
如果只想创建一个slice而不是赋值,可以使用make函数进行操作,示例如下:
ss := make([]int, 10)
可以使用range方式遍历ss切片
//第一种,使用for range进行询缓
for i,v := range ss {
}
//使用for int; condition; posit {
}
//使用for
for{}
常用函数
append
可以在原来的切片上插入元素,可以在开头、结尾、指定位置插入或者其他slice
copy
切片之间可以利用copy函数来实现
4、Map
定义:Key:value形式的无序集合
基本定义方式为:
m1 := make(map[string]int)
func main() { m1 := make(map[string]int) m1["k1"] = 11 m1["k2"] = 22 println(m1) delete(m1, "k1") println(m1) }
struct
struct非常适合定义一个有意义的对象,可以用于定义属性和方法
struct也是复合类型,而非引用类型,复合类型和引用类型是有区别的,复合类型是值传递,而引用类型是引用传递
函数
函数的定义
函数是Go语言的基本组成因素,而实际上面向对象的用法在Go语言并不是很常见
闭包
匿名函数可以赋值给一个变量,也可以直接卸载另一个函数的内部
面向函数的编程中,大的功能往往回通过函数切分成多个独立的较小的功能,而且不可以定义太多的全局变量,这就导致变量的作用域往往是包。大哥比方,闭包在作用上类似与面向对应编程中的实例,他会把函数和所访问的变量打包到一起,不在关心这个变量原来的作用域,闭包本身可以看作是独立对象。闭包函数与普通函数的最大区别是函数不是值传递,二十引用传递,所以闭包函数可以操作自己函数以外的变量,结合GC来看,因为闭包函数对外部变量的引用才导致其不能被释放回收,从而跨国了作用域的限制
func main() { f := double() fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) } func double() func() int { var r int return func() int { r++ return r*3 } }
因为闭包可以使我们的变量的作用域失效,故,我们需要注意如下:
func main() { var funcList1 []func() for i := 0; i < 3; i++ { funcList1 = append(funcList1, func() { fmt.Println(i) }) } for _, f := range funcList1 { f() } var funcList2 []func() for i := 0; i < 3; i++ { j := i funcList2 = append(funcList2, func() { fmt.Println(j) }) } for _, f := range funcList2 { f() } var funcList3 []func(int) for i := 0; i < 3; i++ { funcList3 = append(funcList3, func(i int) { fmt.Println(i) }) } for i, f := range funcList3 { f(i) } }
PS:Go语言里面的局部变量和全局变量名称是可以重复的,重复的适合,系统默认会把重名的变量看作局部变量。当然不建议这样写,容易给人带来困扰
闭包会将自己用到的 变量都保存在内存中,导致变量无法被级市回收,并且可能通过闭包修改父函数使用的变量值,需要注意性能和安全
多返回值及边长参数
func main() { fmt.Println(swap(1, 2)) fmt.Println(sum(1, 2, 3,4,5,6,7,8,9,10)) args := []int{2, 3,4,5,6,7,8,9,10} fmt.Println(sum(sum(1, args...))) print(args) } func swap(a, b int) (int, int) { return b, a } func sum(a int, others ...int) int { for _, v := range others { a += v } return a } func print(a ...interface{}) { fmt.Println(a...) }
defer关键字
defer主要用于释放资源,会在函数返回之前调用,即函数崩溃也会在结束前调用defer
接口
接口即约定
反射