copy:拷贝后的结果,更改其中的值对原来的切片没有影响,使用copy的时候,destslice必须指定长度,否则拷贝后的值为0
a1 := []int{1,2,3} a2 := a1 var a3 = make([]int, 3, 3) // 需要指定destslice切片的长度 copy(a3, a1) 指针go语言不存在指针操作,两个关于指针的符号:&,*。
&: 取地址
*:根据地址取值
new函数申请一个内存地址,一般是个基本数据类型申请内存,int,string,bool,返回的是对应类型的指针。
make也是用于内存分配的,只作用于slice,map,以及chan,make函数返回的是对应的这三个类型的本身。
mapGo语言中提供的映射关系容器为map,其内部使用散列表(hash)实现。
map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。
初始化:在内存中开辟内存空间
var m1 map[string]int //没有初始化,nil m1 = make(map[string]int, 10) //要估算好map的容量,避免在程序运行期间再动态扩容 value, ok := m1["迪丽热巴"] if !ok{ fmt.Println("查无此key") } else { fmt.Println(value) }切片和map的定义
// 切片 var a []int // map map[string]int切片和map一定要初始化
// 元素为map的切片 var s1 = make(map[int]string, 10, 20) s1[0] = make([int]string, 1) // 值为切片类型的map var s2 = make(map[string][]int, 10) 函数函数的定义,可以没有参数,没有返回值,返回值可以命名可以不命名。不命名一定要显式的返回。
package main func name(arg1 string, arg2 int)(res1 string, res2 int){ //code return res1, res2 } func name(){ //code } func name(arg1 string, arg2 int){ //code } func name()(res1 string){ // code return res1 } //可变长度参数,该参数必须写在最后,y的类型是切片,可以传可以不传 func name(x int, y ...int){ // code }在一函数中不能再命名另一个函数。
deferdefer语句把它后面的语句延迟到函数即将返回的时候再执行,defer执行的时候会把函数和变量的状态都带进去。
比如在文件操作的过程中,就需要将文件关闭,否则占用内存资源,甚至造成内存泄漏。
网络socket,数据库连接的释放,也需要进行关闭的操作,类似于python的close。
多个defer的语句的执行顺序类似于栈,先进后出。
go语言中,函数的return操作不是原子性的,在底层分为两步执行
给返回值赋值
执行defer后面的语句
执行真正的return操作
package main func f1() int { x := 5 defer func(){ x++ }() return x } func main(){ f1() // 5 }上面的示例,修改的是x的值,在执行defer之前,返回值已经确认好了。
匿名函数
函数内部没有办法声明带名字的函数
匿名函数一般在函数内部定义和调用
立即执行的匿名函数:定义之后在花括号外加括号执行,常用于只调用了一次的函数
闭包函数内部提供对函数外部变量的引用。
内置函数new返回的是指针
make
panic/recovergo语言没有错误处理机制,go把错误也当成值来处理,把每一个错误的值都做显式的处理if else new if else new。
recover()必须搭配defer使用。
defer一定要在可能引发panic的语句之前定义
fmtfmt.scan
func Scan(a ...interface{})(n int, err error) 递归递归一定要有明确的出口,否则就变成无限循环。
递归适合处理问题相同,规模越来越小的场景,比如:阶乘
自定义类型和类型别名类型别名只在于代码编写的过程中有效,编译完之后就不存在,内置的byte和rune都属于类型别名。
结构体结构体是值类型,
指针接收者
修改结构体中变量的值,需要使用指针接收者。
结构体本身比较大时,拷贝的内存开销比较大时候,也需要用指针。
保持一致性:如果有一种方法使用了指针接收者,其他方法为了统一,也需要用指针。
结构体字段的类型后加tag,可以在反序列化时指定输出格式
type person struct { name string `json:"name" db:"name"` } JSON序列化与反序列化经常出现的问题:
结构体内部的字段首字母要大写!!!否则外部无法访问结构体中的字段。
反序列化时要传递指针。
接口接口是一种数据类型。
接口的定义 type 接口名 interface { 方法名1(参数1, 参数2, ...)(返回值1, 返回值2, ...) 方法名2(参数1, 参数2, ...)(返回值1, 返回值2, ...) }用来给变量,参数,返回值等设置类型。
接口是一种数据类型。
接口是一种特殊的类型,它规定了变量有哪些方法。
不关心一个变量是什么类型,只关心能调用它的什么方法。