【go学习合集】外记2 ------->总结go中各种关键字

汇总

  • make
  • new
  • iota
  • defer
  • panic
  • recover
  • for…range…
  • select

make和new

定义

  • make 的作用是初始化内置的数据结构,比如切片、哈希表和 Channel;
  • new 的作用是根据传入的类型分配一片内存空间并返回指向这片内存空间的指针;

区别

  • make 只能用于创建 map、slice、channel;
  • make 会进行初始化,new 不会初始化,new只是申请一段内存空间,并返回指向这片内存的指针

代码

package main

import "fmt"

func main() {
	slice := make([]int, 10, 11)
	tempMap := make(map[int]int, 10)
	tempChannel := make(chan int, 10)
	fmt.Println(slice)
	fmt.Println(tempMap)
	fmt.Println(tempChannel)
}
----------------------运行结果-------------------------
[0 0 0 0 0 0 0 0 0 0]
map[]
0x140000be000

iota

定义

iota 是一个常量生成器,用于简化定义递增枚举值的过程。它通常用于 const 声明块中,每当 const 声明块中的每一行新声明时,iota 的值会递增。

代码

package main

import "fmt"

const (
	a = iota
	b
	c
)

func main() {
	fmt.Println("a = ", a)
	fmt.Println("b = ", b)
	fmt.Println("c = ", c)
}
----------------------运行结果-------------------------
a =  0
b =  1
c =  2

defer

定义

defer 关键字用于延迟执行一个函数,直到包含 defer 的函数执行完毕后才会运行。defer 通常用于资源清理、文件关闭、解锁互斥锁等场景,确保在函数返回之前,一些必要的清理工作一定会被执行,即使函数中间发生了错误或者提前返回。

代码

单个defer
package main

import "fmt"

func main() {
	defer say()
	fmt.Println("你好")
}

func say() {
	fmt.Println("hello world")
}
----------------------运行结果-------------------------
你好
hello world
多个defer

后进先出原则

package main

import "fmt"

func main() {
	defer fmt.Println("我是第一个defer")
	defer fmt.Println("我是第二个defer")
	defer fmt.Println("我是第三个defer")
	fmt.Println("你好")
}
----------------------运行结果-------------------------
你好
我是第三个defer
我是第二个defer
我是第一个defer
参数被前置定义

定义defer函数的时候,参数已经被前置定义了,不过此时会去区分是指针还是副本,如果是副本,则后续的修改都不影响defer,否则会影响defer。

package main

import "fmt"

type Student struct {
	Name string
	Age  int
}

func main() {
	fmt.Println(change())
	fmt.Printf("%+v\n", changeStudent())
	fmt.Println(changeI())
}

func change() int {
	i := 1
	defer func() {
		i = 8
	}()
	return i
}

func changeStudent() *Student {
	student := &Student{
		Name: "zhangsan",
		Age:  18,
	}
	defer func() {
		student.Age = 80
	}()
	return student
}

func changeI() (res int) {
	res = 1
	defer func() {
		res++
	}()
	return res
}

----------------------运行结果-------------------------
1
&{Name:zhangsan Age:80}
2

panic 和 recover

定义

  • panic 能够改变程序的控制流,调用 panic 后会立刻停止执行当前函数的剩余代码,并在当前 Goroutine 中递归执行调用方的 defer;
  • recover 可以中止 panic 造成的程序崩溃。它是一个只能在 defer 中发挥作用的函数,在其他作用域中调用不会发挥作用;

代码

panic会导致整个进程终止,后续逻辑不再运行

package main

import "fmt"
// panic 的case
func main() {
	fmt.Println("start")
	panic("there is a panic")
	fmt.Println("end")
}
----------------------运行结果-------------------------
start
panic: there is a panic

goroutine 1 [running]:
main.main()
        /Users/bytedance/GolandProjects/awesomeProject/main.go:7 +0x6c


使用recover捕获panic,使得程序能够正常运行,但是panic仍然会导致当前goruntine的停止

package main

import "fmt"

// case1
func main() {
	fmt.Println("start")
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("recover from panic")
		}
	}()
	panic("there is a panic")
	fmt.Println("end")
}
----------------------运行结果-------------------------
start
recover from panic
package main

import "fmt"

package main

import "fmt"

package main

import (
	"fmt"
	"time"
)

// case2
func main() {
	fmt.Println("start")
	go func() {
		defer func() {
			if r := recover(); r != nil {
				fmt.Println("recover")
			}
		}()
		fmt.Println("go start")
		panic("go there is a panic")
		fmt.Println("go end")
	}()
	time.Sleep(1 * time.Second)
	fmt.Println("end")
}
----------------------运行结果-------------------------
start
go start
recover
end

for range

定义

通常配合起来联合使用,用作迭代字符串、数组、切片、映射、通道的访问。

代码

package main

import "fmt"

func main() {
	arr := [5]int{1, 2, 3, 4, 5}
	slice := []int{1, 2, 3, 4, 5}
	tempMap := make(map[int]int)
	tempMap[1] = 1
	tempMap[2] = 2
	tempMap[3] = 3
	channel := make(chan int)
	s := "1234"
	go func() {
		defer close(channel)
		channel <- 1
		channel <- 2
		channel <- 3
	}()
	for index, elemet := range arr {
		fmt.Printf("arr[%d] = %d  ", index, elemet)
	}
	fmt.Println()
	for index, elemet := range slice {
		fmt.Printf("slice[%d] = %d  ", index, elemet)
	}
	fmt.Println()
	for key, value := range tempMap {
		fmt.Printf("tempMap[%d] = %d  ", key, value)
	}
	fmt.Println()
	for v := range channel {
		fmt.Printf("channel = %d    ", v)
	}
	fmt.Println()
	for _, i := range s {
		fmt.Printf("char = %d  ", i)
	}
}

----------------------运行结果-------------------------
arr[0] = 1  arr[1] = 2  arr[2] = 3  arr[3] = 4  arr[4] = 5  
slice[0] = 1  slice[1] = 2  slice[2] = 3  slice[3] = 4  slice[4] = 5  
tempMap[3] = 3  tempMap[1] = 1  tempMap[2] = 2  
channel = 1    channel = 2    channel = 3    
char = 49  char = 50  char = 51  char = 52  

select

定义

select 关键字用于处理多个通道(channels)操作的同时选择。它类似于 switch 语句,但 select 是专门用于通道操作的,它可以在多个通道上等待发送或接收操作,并且一旦某个通道操作完成,select 会执行对应的代码块。也可以做一些超时控制。

代码

select相当于switch,只不过仅操作通道

package main

import "time"

func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	ch3 := make(chan int)

	go func() {
		for i := 0; i < 10; i++ {
			ch1 <- i
		}
	}()
	go func() {
		time.Sleep(8 * time.Second)
		ch1 <- 2
	}()
	go func() {
		time.Sleep(9 * time.Second)
		ch1 <- 3
	}()
	select {
	case <-ch1:
		println("ch1")
	case <-ch2:
		println("ch2")
	case <-ch3:
		println("ch3")
	case <-time.After(4 * time.Second):
		println("timeout")
	default:
		println("default")
	}
}

----------------------运行结果-------------------------
ch1
  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值