sisterofdc

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

GO 面试题 GO基础篇

https://www.golangroadmap.com/
https://golang.design/under-the-hood/
书上内容大部分是go 1.15 1.16
看的面试题来自于这里

golang里的数组和切片有了解过吗?

点击查看代码

array 和 slice 区别

首先是申请方式
array 申请方式

var myArray = new([]int)

slice 申请方式

var mySlice = make([]int, 10)

本质上slice 是一个引用类型,切片提供对该数组中编号元素序列的访问。
切片是在內存的组织方式实际上还是有三个域的结构体,
{
ptr:指向相关数组的指针
len:切片长度
cap:切片容量
}

对已经关闭的channel进行读写操作会发生什么?

点击查看代码

代码,对一个int 类型的channel 发数据。
在5秒后关闭channel

package main

import (
	"log"
	"time"
)

func main() {
	var myChannel = make(chan int)
	go ReadFromCloseChannel(myChannel)
	go CloseChannel(myChannel)
	for {
		myChannel <- 1
		time.Sleep(1 * time.Second)
		myChannel <- 2
	}
}

func ReadFromCloseChannel(myChannel chan int) {
	for {
		var number, ok = <-myChannel
		log.Println(number, ok)
		/*
		panic: send on closed channel

		goroutine 1 [running]:
		main.main()
		        E:/webProject/faceProject/main.go:15 +0xd6

		*/
	}
}

func CloseChannel(myChannel chan int) {
	time.Sleep(5 * time.Second)
	close(myChannel)
}

如果直接关闭的channel 写数据,系统会直接进行panic处理。因为channel已经关闭
如果往关闭的channel 读数据,系统会把channel 缓存中的数据全部取出

Go语言中是如何实现继承的?

点击查看代码
通过struct组合
在GRPC中如果要使用Server,需要新的结构,然后写出所有的方法。然后继承的函数是大写。

数组怎么转集合?

点击查看代码
struct to map 
for range 

Go的GMP模型?

点击查看代码
问GO协程的问题。
上面才是內核級线程
G goroutine 
M machine 
P Processer GO代码所需要的上下文环境。

channel实现方式/原理/概念/底层实现

点击查看代码

因为我自己用的大部分都是go 1.95所有源码的阅读

https://go.googlesource.com/go/+/refs/tags/go1.19.5/src/runtime/chan.go
如果是老版本的解读
https://juejin.cn/post/7129085275266875422
go 协程通过channel来实现共享内存,和协程之间的通信
本质上是问数据结构的问题
实现方式,

结构体

type hchan struct {
	qcount   uint           // total data in the queue 所有数据数量
	dataqsiz uint           // size of the circular queue 所有数据大小
	buf      unsafe.Pointer // points to an array of dataqsiz elements 在有缓冲区的chan进行设置,集中buf实现是循环数组
	elemsize uint16
	closed   uint32  //是否关闭
	elemtype *_type // element type 申请channel里面的数据类型
	sendx    uint   // send index
	recvx    uint   // receive index
	recvq    waitq  // list of recv waiters 其中waitq就是等待队列。里面就是
	sendq    waitq  // list of send waiters 
	// lock protects all fields in hchan, as well as several
	// fields in sudogs blocked on this channel.
	//
	// Do not change another G's status while holding this lock
	// (in particular, do not ready a G), as this can deadlock
	// with stack shrinking.
	lock mutex
}

同一个协程里面,对无缓冲channel同时发送和接收数据有什么问题,channel和锁的对比,channel的应用场景

点击查看代码
首先在channel结构中lock mutex。如果没有缓存。相当于两个协程对同一个数据进行读取。会直接死锁。
channel更多是在 Channels make goroutines share memory by communicating
一个是通过channel
锁 更多是 we use traditional concurrency synchronization techniques, such as mutex locks, to protect the shared memory to prevent data races
直接对公共资源直接加锁

WaitGroup的坑

点击查看代码
第一次使用在apllo 配置中心中使用。update中就有waitGroup
保证计数器的一致,建议直接一个结构中传递 *waitGroup
首先waitGroup需要设置初始值,waitGroup.add()
如果需要传递

type Lock struct {
	ID    int
	Value string
	*sync.WaitGroup
}

申请的时候
	var wg = new(sync.WaitGroup)

使用的时候
defer receiver.WaitGroup.Done()

go 实现不重启热部署

点击查看代码
> https://www.apolloconfig.com/#/zh/README
> https://www.cnblogs.com/sisterofdc/articles/17124711.html
在apollo中有GO的客户端。就可以想办法自己写部署。

goroutine与线程的区别?

点击查看代码
1.进程:进程是资源分配的最小单位,进程切换需要的资源很大,效率很低,进程消耗内存大,系统调度
2.线程:线程是系统调度的最小单位,线程切换的资源一般,效率一般,线程消耗内存也是M级别的,系统调度
3.协程:协程是用户态的线程,协程切换任务资源很小,效率高,协程消耗内存是kb级别的,协程是用户自己调度
这个和go GMP模型可以以前解释

进程调度,线程调度。在多线程中会占用大量的空间和时间



go垃圾回收,什么时候触发,了解的gc算法有哪些?

点击查看代码
Garbage Collection

内存管理
自动释放

**go 中垃圾回收机制,三色标记,GC混合写屏障机制**

主要版本,1.3 1.5 1.8

1.3之前的垃圾清除mark and sweep标记清除
第一步,STW (stop the world)暂停所有业务逻辑,找到不可达对象和可达对象。因为程序中不一定每一个都是需要用的,只需要找到,现在程序能用到的。
第二步,在所有可达对象中打上标记,那么剩下就是需要回收的
第三步,回收垃圾,把没有标记的都回收了
第四步,到程序结束前重复前三部,让程序继续跑

缺点,
让程序暂停,程序暂停
标记需要扫描整个heap
清除数据会产生heap碎片

1.5三色标记法

首先三色标记法是动态的
三种标记 白 灰 黑

第一步,把所有对象放入白色的表格
第二部,从根节点开始访问,把能访问的对象放入灰表
循环
把灰表中的元素扫描到下一个为空,灰变黑,白变灰
在灰表中没有元素后,退出循环
清除白表剩下的对象

缺点
如果不加入STW 
在白表中的对象
1.被黑表中的引用了(就是变成了合法对象)
2.同时灰表又不指向白表了
就是误删

强三色不变式
直接让黑色对象不能引用白色对象(第一个条件不满足,就是让一个对象合理化)
弱三色不变式
黑色可以引用,但是必须保证白色上游链路必须有灰色(保证上游必须有)

屏障
插入屏障
(不在栈上使用)原因,因为栈要要求性能,如果每一次我都去判断新对象,那么直接耗时。
在A对象引用B对象时候,B对象标记为灰色
对象引用

需要STW来保护栈

删除配置
对象不引用
被删除的对象,如果自身为灰色或者白色,那么被标记为灰色

被删除的对象的下链依然会保留,但是只有一轮。这个是优点保证被删除的节点可能被其他节点引用
也是缺点,回收精度低。

1.8三色标记法和混合写屏障

上面都是管理了栈的
所有,GC开始将栈上的对象全部扫描为黑色。GC期间然后栈上的都是黑色。相当于直接没有管栈了
删除的对标记为灰色
添加的对象为灰色


如何实现一个线程安全的 map? Go map 的底层实现 ?

Context 包的作用

go 语言的 panic 如何恢复

defer 的执行顺序

服务器能开多少个M由什么决定

Go 有哪些并发同步原语?

点击查看代码
关键字 go 用于创建基本的并发单元。

go func() {
	// 并发代码块
	...
}()
被并发的函数将发生在一个独立的 Goroutine 中,与产生 Goroutine 的代码并发的被执行。



Channel
Channel 主要有两种形式:

有缓存 Channel(buffered channel),使用 make(chan T, n) 创建
无缓存 Channel(unbuffered channel),使用 make(chan T) 创建
posted on 2023-04-01 00:50  SistersOfDC  阅读(41)  评论(0)    收藏  举报