目录
1.golang执行流程
两种流程的区别:
2.指针及其内存布局
指针是类型,存的变量的地址,这个地址指向的空间才是变量的值。例如
var prt *int = &num
package main
import "fmt"
func main() {
var num int = 10
//1. ptr是一个变量
//2.ptr 的类型是*int
//3.ptr的本身的值是&i
var ptr *int = &num
fmt.Println(ptr)
//获取指正类型的地址
fmt.Println(&ptr)
//获取指针类型指向的值
fmt.Println(*ptr)
*ptr = 100
fmt.Println(num)
}
3.值类型和引用类型
不管是值传递还是引用传递,他们传递的都是变量的拷贝,值传递传递的是值的拷贝,引用传递传递的是地址的拷贝,拷贝地址的效率要比拷贝值的效率要高。
值类型,变量直接存储值,内存通常在栈中分配。
引用类型:变量存储的地址,地址对应的空间才是值。
4. break
用于跳出当前for循环或者跳出switch语句,并且在多层嵌套的时候break默认跳出最近的for循环
入门案例:
var count = 0
for {
rand.Seed(time.Now().UnixNano())
n := rand.Intn(100) + 1
count++
if n == 99 {
break
}
}
fmt.Println(count)
break语句出现在多层嵌套的时候,可以通过标签指明要终止的是哪一层语句块,
liable:
for i := 0; i < 4; i++ {
for j := 0; j < 4; j++ {
if j == 2 {
break liable
}
fmt.Println(j, i)
}
}
}
5. continue
跳出当前循环,后面的循环继续
for i := 0; i < 4; i++ {
for j := 0; j < 4; j++ {
if j == 2 {
continue
}
fmt.Println(j, i)
}
}
6.goto
尽量避免使用 除非迫不得已 避免造成流程混乱
var num2 = 20
fmt.Println("1")
fmt.Println("2")
if num2 > 1 {
goto labile2
}
fmt.Println("3")
fmt.Println("4")
fmt.Println("5")
labile2:
fmt.Println("6")
fmt.Println("7")
7.匿名函数
如果某个函数只使用一次,就可以考虑匿名函数,定义匿名函数的时候就直接调用,这种方式只能调用一次
var a1 = 10
var a2 = 20
//定义匿名函数的时候就直接调用,这种方式只能调用一次
result := func(a int, b int) int {
return a + b
}(a1, a2)
fmt.Println(result)
将函数赋值给一个变量就可以多次调用
//将函数赋值给一个变量就可以多次调用
a := func(a1 int, a2 int) int {
return a1 - a2
}
i := a(10, 5)
fmt.Println(i)
i2 := a(20, 5)
fmt.Println(i2)
全局匿名函数
8.闭包
闭包就是一个函数与其相关环境组成的一个整体
// 函数的返回值是一个函数类型 是一个匿名函数,这个匿名函数引用到外部的n,因此匿名函数与外部形成一个整体 构成闭包 // 闭包可以理解为一个类,函数式操作,n是字段 //反复调用时 n只初始化一次
package main
import "fmt"
// 函数的返回值是一个函数类型 是一个匿名函数,这个匿名函数引用到外部的n,因此匿名函数与外部形成一个整体 构成闭包
// 闭包可以理解为一个类,函数式操作,n是字段
//反复调用时 n只初始化一次
func Add() func(a1 int) int {
var n int = 10
return func(a1 int) int {
n = a1 + n
return n
}
}
func main() {
add := Add()
fmt.Println(add(1))
fmt.Println(add(2))
}
这一段构成闭包
9.defer
函数执行完毕后关闭资源
执行到这里的时候会将defer语句暂时压入到一个栈中 ,函数执行完毕后按照先入后出的方式执行defer语句,defer将语句入栈时,同时也会将相应的值拷贝入栈。