!> Golang相关的面试题
!> 这里没有初始化的意思就是没有赋值 可以,例如 var a [5]int
将会赋对应类型的零值
!> 可以,未初始化只是一个为长度和容量都为0的一个切片,使用append将会触发扩容机制 注意:切片未只是声明并未初始化,如var a []int
,相当于一个nil,可以直接append进行追加元素,将会触发扩容
类似问题:切片和数组区别和底层 参考1参考2参考深度解密Go语言之Slice
empty slice用法:当我们查询或者处理一个空的列表的时候,这非常有用,它会告诉我们返回的是一个列表,但是列表内没有任何值。
package main
import (
"encoding/json"
"fmt"
)
/**
* @Author: yirufeng
* @Date: 2021/2/16 8:46 上午
* @Desc:
empty slice用法:当我们查询或者处理一个空的列表的时候,这非常有用,它会告诉我们返回的是一个列表,但是列表内没有任何值。
**/
type Student struct {
Id []int
Name string
}
func main() {
var a []int
b := []int{}
aByte, _ := json.Marshal(a)
fmt.Println(string(aByte)) //null
bByte, _ := json.Marshal(b)
fmt.Println(string(bByte)) //[]
c := Student{
Name: "123",
}
d := Student{
Id: []int{},
Name: "123",
}
cByte, _ := json.Marshal(c)
fmt.Println(string(cByte)) //{"Id":null,"Name":"123"}
dByte, _ := json.Marshal(d)
fmt.Println(string(dByte)) //{"Id":[],"Name":"123"}
}
类似问题:slice的底层原理 类似问题:切片怎么扩容,扩容过程中需不需要重新写入
参考1参考2参考3参考4 类似问题:go map结构实现,并发安全否
map不是线程安全的,需要使用sync.Map,可以看该文章的最后
数组,切片,映射,通道,所有的讲解参考
slice与map都不是线程安全的
参考 channel是线程安全的
!> 参考
参考 goroutine泄漏描述:如果你启动了一个 goroutine,但并没有符合预期的退出,直到程序结束,此goroutine才退出,这种情况就是 goroutine 泄露。 参考
!>(上次哔哩哔哩面试问到了,幸亏我事后看了一眼是类似双重检验锁的实现方式哦),让我写出来,我写出了一大半,还让我运行一下,我运行不出来
协程是轻量级线程,多个协程可以由一个或多个线程管理。 协程无需上下文切换,没有线程之间切换的开销。 协程的调度不需要多线程的锁机制,因为只有一个线程,不存在同时写变量冲突,执行效率比多线程高很多。 这题面试的时候没有答到第三点。
共享内存和协程通信。 「Don’t communicate by sharing memory, share memory by communicating」所以更提倡使用 channel 进行通信。 当时答的时候也只答了 channel,面试官说还有一种,怎么都想不起来Orz。
内置函数
其他内置函数可以参考golang包中的builtin function
默认采用值传递,且Go 中函数传参仅有值传递一种方式。 slice、map、channel 都是引用类型。 slice 能够通过函数传参后,修改对应的数组值,因为 slice 内部保存了引用数组的指针,并不是因为引用传递。 这题回答的时候以为有引用传递,答了 slice、map、channel 都是引用传递,结果一百度,发现是用起来像引用传递,其实都是值传递,就像 slice 传递的是指针的复制。
Golang 语言中的内置函数 make 和 new 都是用作变量初始化,但是它们初始化变量的方式不同。关于它们之间的区别,我们可以简述为 make 返回类型是引用类型,new 返回类型是指针类型。本文我们首先分别介绍二者,然后再介绍二者的区别。 02 内置函数 make 关于内置函数 make,官方的介绍是 make 内置函数仅用作分配内存空间并初始化 slice,map 和 chan 类型的对象。与 new 相同,第一个参数是类型,而不是值。与 new 不同,make 的返回类型与其参数的类型相同,而不是指向它的指针。 func make(t Type, size ...IntegerType) Type 返回值取决于传参的类型: Slice s := make([]T, 0, 10) 以上示例代码表示分配一个长度为 10 的底层数组,返回一个长度为 0,容量为 10 的切片。 使用内置函数 make 初始化 slice,第一个参数是类型,第二个参数是 slice 的长度,第三个参数是可选参数,它代表 slice 的容量,如果不传入第三个参数,slice 的容量与长度相同,但是如果传入第三个参数,它的值(容量)比如大于或等于传入的第二个参数(长度)。 Map m := make(map[T]T) 以上示例代码表示给 map 分配内存空间。 使用内置函数 make 初始化 map,传入的参数是类型,map 没有容量限制,初始化时无需指定容量的大小。 Channel c := make(chan T, 10) 以上示例代码表示给 channel 分配的内存空间大小(缓冲容量)为 10。channel 的缓冲区使用指定的值初始化缓冲容量。如果为零或忽略大小(不传入第二个参数),则 channel 为无缓冲的。 03 内置函数 new 关于内置函数 new,官方介绍是内置函数 new 仅用作分配内存空间,第一个参数是类型,而不是值,返回值是指向新分配该类型的零值的指针。 func new(Type) *Type 在 Golang 开发中,通常不太常用内置函数 new,它的使用场景一般是需要显式返回指针。 04 make 和 new 的区别 在阅读完上述内容后,我相信读者朋友们应该已经了解了二者的区别。 make 仅用于初始化 slice,map 和 chan,new 可用于初始化任意类型。 make 返回值是”引用类型“,new 返回值是指针类型。 05 总结 本文我们介绍了内置函数 make 和 new,并且对比归纳了二者的区别,在 Golang 开发中,内置函数 make 是必用的,因为 slice,map 和 chan,必须使用内置函数 make 初始化,才可以使用;而内置函数 new 并不常用,通常使用场景是需要显式返回指针。
从自己理解的角度看
cyan: 1.闭包引用 2.多协程竞争(同步原语,比如锁,waitgroup 等等) 3.匿名函数内的遍历是否逃逸
博大:我总结了一下,欢迎大家补充
还有个坑是 type Node struct{ Val int } var test map[string]Node
test["a"] 拿到的Node是不能修改的 即test["a"].Val = 1 会报错 正确的写法是 var test map[string]*Node
gc 算法
深拷贝,浅拷贝