如何让一个goroutine停止?
只需要监听,case中监听对应的chan
func main() {
ch := make(chan bool)
go func(){
for {
select {
case <- ch:
return
default :
fmt.Println("linten")
}
}
}()
ch <- true
}
如何在运行时检查变量类型?
通过反射来检查reflect.typeOf 和 reflect.valueOf
其中typeOf是的入参是interface value返回其type值,通过switch 和case结合即可判断类型,在对应的case下根据valueOf接口将值转化为目标值
Go interface和struct之间的关系?
package main
import "fmt"
type AbCourseInterface interface {
GetCourseInfo() string
}
type AiCourseStruct struct {
Name string
}
func (aiCourse AiCourseStruct) GetCourseInfo() string {
return aiCourse.Name
}
type BcCourseStruct struct {
Name string
}
func (BcCourseStruct BcCourseStruct) GetCourseInfo() string {
return BcCourseStruct.Name
}
func EchoName (obj AbCourseInterface) string {
return obj.GetCourseInfo()
}
func main() {
a := AiCourseStruct{
Name:"13",
}
fmt.Println(EchoName(a))
}
结果输出 13
interface定义方法A,如果结构体实现了interface的方法A,那么这是如果有方法B的入参类型是AbCourseInterface,那么当前方法调用方法B可以直接传入实现了AbCourseInterface的结构体
Go 当中同步锁有什么特点?作用是什么
mutex,分为读锁和写锁和mysql比较类似
当一个goroutine给一个key设置了读锁,那么其他的goroutine可以读到当前锁,但是不能对当前锁进行操作
当一个goroutine给一个key设置了写锁,那么其他锁将会获取不到当前锁,即不能读也不能写
Go 语言当中 Channel(通道)有什么特点,需要注意什么?
如果给一个 nil 的 channel 发送数据,会造成永远阻塞。
如果从一个 nil 的 channel 中接收数据,也会造成永久阻塞。
给一个已经关闭的 channel 发送数据, 会引起 panic
Go 语言当中 Channel 缓冲有什么特点?
make(chan bool, 1000)
第二个参数是是否设置缓冲区
不设置缓冲区的话那么就是同步的
不设置缓冲区,初始化一个chan,这是如果没有接收者在读区当前的chan那么往里写数据会报错
设置缓冲区的话那么就是异步的
设置缓冲区,初始化一个chan,比如大小是2,那么在没有接收者读区的情况下往chan里面写数据超过2条就会报错
Go 语言中 cap 函数可以作用于哪些内容
cap查看数组 slice、map、chan的容量
slice的底层结构
struct Slice
{
byte* array; // actual data
uintgo len; // number of elements
uintgo cap; // allocated number of elements
};
首先slice当作参数传入函数时,会发生copy,slice1变为slice2,但是array的指针实际上是一样的,所以在方法哪对当前slice进行值修改,外层函数的值是也会被修改的
但是slice的cap和len不是指针,所以不会修改,如果需要修改的话需要在用之前加上*
map
type hmap struct {
count int
flags uint8
B uint8
noverflow uint16
hash0 uint32
buckets unsafe.Pointer // 当前桶大小
oldbuckets unsafe.Pointer // 扩容时存放buckets的一半
nevacuate uintptr
extra *mapextra
}
当我们make一个map字段后其实是返回的一个8个字节的指针,当前指针指向了hmap这个结构,接下来让我们看一下hmap结构中每个字段代表的具体含义:
count 代表了当前map结构的长度
flag 代表了当前map的状态,写入中还是?空闲等
B 代表了hash桶的对数 比如B是3 那么 2的三次方当前就有八个桶
noverflow 代表了当前溢出桶的数量
hash0 生成hash的种子数
buckets 指针,指向当前所有的数据桶
oldbuckets 如果map需要扩容的话,old这个指向buckets这个桶,然后让buckets去扩容(扩容1倍)
nevacuate 扩容进度
extra 代表当前溢出桶指针
接下来我们重点讲解一下buckets这个字段和extra这个字段
type bmap struct{
tophash [8]uint8 长度为8的数组,用于定位当前key是否在这个桶里
keys [8]keytype
// keytype
values [8]elemtype
// elemtype
overflow uintptr
// overflow指向下一个bmap,overflow是uintptr而不是*bmap类型,保证bmap完全不含指针,是为了减少gc,溢出桶存储到extra字段中
}
接下来我们讲解一下mapextra这个结构
type mapextra struct {
overflow *[]*bmap
oldoverflow *[]*bmap
nextOverflow *bmap
}
当1个桶的数据存满了之后,bmap的overflow会指向uintptr 而不是指针,为了防止被gc删除,所以数据就都会放到mapextra中