1、golang 中 make 和 new 的区别?(基本必问)
1 .make和new都是golang用来分配内存的內建函
数,且在堆上分配内存,
2 .make 即分配内存,也初始化内存。
3 .new只是将内存清零,并没有初始化内存。
4 .make返回的还是引用类型本身,make只能用来
分配及初始化类型为slice,map,channel的数据
5 .new可以分配任意类型的数据
6 .而new返回的是指向类型的指针。
2、数组和切片的区别 (基本必问)
1 .内部结构
数组在内存中是一段连续的内存空间,元素的类型
和长度都是固定的。切片在内存中由一个指向底层
数组的指针、长度和容量组成,长度表示切片当前
包含的元素个数,容量表示切片可以扩展的最大元
素个数
2 .长度
数组的长度在创建时指定,不能更改。切片的长度
可以动态扩展或收缩,可以根据需要自由调整。
3 .使用方式
数组在使用时需要明确指定下标访问元素,不能动
态生成。切片可以使用 append 函数向其末尾添
加元素,可以使用 copy 函数复制切片,也可以
使用 make 函数创建指定长度和容量的切片
3、for range 的时候它的地址会发生变化么?for 循环遍历 slice 有什么问题?
1 .地址没有发生变化
2 .在使用 for range 语句遍历切片或数组时,
每次迭代都会返回该元素的副本,而不是该元素
的地址。这意味着,每次循环完成后,该元素所
对应的地址都是相同的( 最后一个) ,并不会改变
3 .for range循环的工作方式是为了优化性能和
降低内存分配。在for range中,迭代变量会被
重复使用,而不是在每次迭代中创建一个新的变量
这个设计选择有助于减少内存分配和提高性能。在
这种情况下,如果你尝试在循环中保存迭代变量的
地址,实际上保存的是同一个地址。因此,在循环
结束后,你可能会遇到保存的值都是最后一次迭代
的值的情况。这是Go语言中的一个设计决策,旨在
提高程序的性能。如果你需要在循环中保存每次迭
代的值,可以考虑在每次迭代中创建一个新的变量
来保存值,而不是直接使用迭代变量。这样可以确
保你在集合或数组中保存的是不同的地址而不是同
一个地址package main
import "fmt"
type girl struct { Name stringAge int
}
func main ( ) { gl := make( map[ string] *girl) studs := [ ] girl{ { Name: "Lili" , Age: 23 } ,{ Name: "Lucy" , Age: 24 } ,{ Name: "Han Mei" , Age: 21 } ,}
//错误的写法 for _, v := range studs { gl[ v.Name] = & v }
//正确的写法
for _, v := range studs { temp := v gl[ v.Name] = & temp
} for mk, mv := range gl { fmt.Println( mk, "=>" , mv.Age) }
}
4、go defer,多个 defer 的顺序,defer 在什么时机会修改返回值?(for defer)defer recover 的问题?(主要是能不能捕获)
1 .在Go语言中,defer关键字用于延迟执行一个
函数调用,通常用于确保在函数执行结束后释放
资源或执行一些清理操作。关于defer的几个问题:
多个 defer 的顺序: 多个defer语句按照后进
先出(Last In, First Out,LIFO)的顺序
执行,即最后一个defer语句会最先执行,倒数
第二个会在倒数第一个之后执行,以此类推。
2 .defer 在何时修改返回值: defer语句中
的函数调用是在包含它的函数执行完毕之后才执
行的。如果包含defer的函数有命名的返回值,
并且在defer语句执行时修改了这个返回值,那
么最终的返回值将是defer语句中修改后的值。func example( ) ( result int) { defer func ( ) { result += 10 } ( ) return 5
}
在这个例子中,尽管return 5 语句执行时返回
的是5,但由于defer中修改了result,实际上
最终的返回值是15。
3 .defer与recover通常一起使用,用于处理
函数中的错误。recover只能捕获在同一个
goroutine中发生的panic,而且必须在defer
中调用。如果recover在没有发生panic的情况
下调用,它会返回nil
4 .defer和recover是Go语言中用于处理资源
释放和错误恢复的重要机制。
5、 uint 类型溢出
Golang的uint类型溢出问题通常会在大量运算
中发生,特别是在涉及到大量循环或者大数运算时
当uint类型的值超过其最大值时,它会发生溢出,
然后从该类型的最小值开始循环,解决方案:
1 .使用更大的数据类型:例如,如果你正在使用
uint32,你可以尝试升级到uint64。这将提供
更大的值范围,从而减少溢出的可能性。
2 .添加溢出检查:在每次运算之后,你可以检查
结果是否小于任一操作数(假设我们只在正数上
进行操作)。如果是这样,那么就发生了溢出。
3 .使用 math/big 包:对于非常大的数值,你
也可以考虑使用 math/big 包中的 Int 类型
这个类型可以处理任意大小的数值,但是运算速
度会慢一些。
6、介绍 rune 类型
1 .rune相当int32
2 .golang中的字符串底层实现是通过byte数组的
中文字符在unicode下占2个字节,在utf-8编码
下占3个字节,而golang默认编码正好是utf-8
3 .byte 等同于int8,常用来处理ascii字符
4 .rune 等同于int32,常用来处理unicode或
utf-8字符