golang 面经积累

Posted XUPT-BDAL-LAB-ML&OP

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang 面经积累相关的知识,希望对你有一定的参考价值。

—1—

通用问题

开放式问题

设计模式相关问题

代码设计相关问题

语言相关问题

Web相关问题

数据库相关问题

—1—

https://www.zhihu.com/question/482563210

1. mysql有哪几种log

2. MySQL的复制原理以及流程

3. 事物的4种隔离级别

4. 相关概念 脏读 可重复读 不可重复读 幻读

5. MySQL数据库几个基本的索引类型

添加链接描述

6. drop、delete与truncate的区别

7. 数据库的乐观锁和悲观锁是什么?

8. SQL优化方式

9. 从锁的类别上分MySQL都有哪些锁呢?

非关系型数据库相关问题

代码版本管理相关问题

并发问题

分布式系统相关问题

软件生命周期和团队管理相关问题

逻辑和算法相关问题

软件架构相关问题

面向服务架构(SOA)和微服务(Microservice)相关问题

安全相关问题

比尔盖茨式问题

代码示例问题

—2—

1、请解释Golang中的interface是什么,以及它们的使用场景?

答案:interface表示空接口,可以保存任何类型的值。它的使用场景包括动态类型,类型断言和将任意类型的值传递给函数等。

2、Golang中的内存模型是什么?请详细解释。

答案:Golang的内存模型基于happens-before原则,它定义了Golang程序中的并发操作如何相互作用。具体来说,内存模型描述了如何安排操作顺序以保证正确的结果。

3、Golang中的锁是什么?请列举一些锁的类型并解释它们的用途。

答案:锁是一种同步机制,用于保护共享资源免受并发访问的影响。Golang中有三种锁类型:sync.Mutex,sync.RWMutex和sync.WaitGroup。sync.Mutex和sync.RWMutex用于互斥访问共享资源,而sync.WaitGroup用于等待一组协程完成执行。

4、请解释Golang中的垃圾回收机制,并描述它的优点和缺点。

答案:Golang中的垃圾回收机制使用标记-清除算法,它自动回收不再使用的内存。优点包括减少内存泄漏和避免手动管理内存的复杂性,缺点则包括影响程序的性能和增加内存占用。

5、请解释Golang中的context是什么,以及它们的作用?

答案:context是一个用于传递请求范围值的标准Go库。它用于控制Golang中的请求生命周期,例如控制请求的超时和取消。它在Go语言中的网络编程和多线程编程中广泛使用。

6、Golang中的panic和recover是什么,以及它们的作用?

答案:panic和recover是Golang的错误处理机制。当程序遇到无法处理的错误时,它会引发panic,这会使程序停止执行并打印出错误消息。recover可以用来捕获panic,然后继续执行程序。

7、请解释Golang中的defer关键字,并提供一个使用例子。

答案:defer关键字用于在函数退出时执行一些代码,无论是否发生异常。它通常用于资源管理和异常处理。例如:goCopy codefunc main() defer fmt.Println(“world”) fmt.Println(“hello”)// Output: // hello// worldGolang中的select关键字是什么,以及它们的作用?答案:select是Golang中的一种控制流语句,用于同时等

8、Golang中的select关键字是什么,以及它们的作用?

答案:select是Golang中的一种控制流语句,用于同时等待多个通道上的操作。它的作用是在通道之间进行非阻塞选择,一旦一个通道准备好了就可以执行相应的操作。这个特性在实现高效的并发操作时非常有用。

9、Golang中的内存分配器是什么,以及它们的作用?

答案:Golang中的内存分配器是一种用于动态分配和管理内存的工具。它的作用是在程序运行时分配内存,并在使用完毕后释放内存。这可以避免手动管理内存的复杂性,并提高程序的性能。

10、Golang中的闭包是什么,以及它们的作用?

答案:闭包是一种函数,它可以访问其外部函数作用域中的变量。在Golang中,闭包通常用于实现函数式编程和处理异步事件等情况。

11、Golang中的反射是什么,以及它们的作用?

答案:反射是一种机制,它可以在程序运行时动态地检查和修改类型信息。在Golang中,反射通常用于实现通用代码和处理未知类型的值。

12、Golang中的RPC是什么,以及它们的作用?

答案:RPC是一种远程过程调用机制,它允许程序在不同的进程和计算机之间调用函数。在Golang中,RPC通常用于实现分布式应用程序和客户端-服务器模型。

13、Golang中的并发模型是什么,以及它们的作用?

答案:Golang中的并发模型是基于goroutine和通道的模型。goroutine是一种轻量级的线程,它可以在程序中并发执行任务。通道是一种同步的并发数据结构,它用于在不同的goroutine之间传递数据。这种并发模型可以避免共享内存的问题,并提高程序的并发性能。

14、Golang中的CGO是什么,以及它们的作用?

答案:CGO是一种Golang语言与C/C++代码交互的机制。它允许Golang程序与C/C++库交互,并利用现有的C/C++代码资源。CGO在处理低级别的系统操作和性能优化方面非常有用。

15、Golang中的模板是什么,以及它们的作用?

答案:模板是一种用于生成文本输出的工具。在Golang中,模板通常用于生成网页和邮件等文本输出。模板提供了一种方便和灵活的方式来生成结构化的文本输出,可以帮助开发人员快速构建动态网页等应用程序。

16、Golang中的GC是什么,以及它们的作用?

答案:GC是Golang中的垃圾回收机制,它可以在程序运行时自动检测和回收不再使用的内存。这可以避免内存泄漏和程序崩溃等问题,同时方便和灵活的方式来生成结构化的文本输出,可以帮助开发人员快速构建动态网页等应用程序。

17、Golang中的反向代理是什么,以及它们的作用?

答案:反向代理是一种在服务器端进行的代理机制,它可以将客户端请求转发到其他服务器上。在Golang中,反向代理通常用于负载均衡和缓存等功能,可以提高服务器的性能和可靠性。

18、Golang中的文件处理是什么,以及它们的作用?

答案:Golang中的文件处理是一种用于读写文件的工具。它的作用是在程序运行时访问文件,并进行读写操作。文件处理通常用于读取配置文件、日志文件等操作。

19、Golang中的WebSocket是什么,以及它们的作用?

答案:WebSocket是一种在Web应用程序中实现双向通信的协议。在Golang中,WebSocket通常用于实现实时通信和推送服务等功能。

20、Golang中的错误处理是什么,以及它们的作用?

答案:错误处理是Golang中处理错误的机制,它可以在程序运行时检测和处理各种类型的错误。错误处理可以避免程序崩溃和异常情况,提高程序的可靠性和稳定性。在Golang中,错误处理通常使用返回值和panic/recover机制实现。

—3—

添加链接描述

1. go的调度

GMP
添加链接描述

2. go struct能不能比较

添加链接描述

3. go defer(for defer)

defer关键字用于在函数退出时执行一些代码,无论是否发生异常。它通常用于资源管理和异常处理

4. select可以用于什么

select是Go中的一个控制结构,类似于switch语句,用于处理异步IO操作。select会监听case语句中channel的读写操作,当case中channel读写操作为非阻塞状态(即能读写)时,将会触发相应的动作。
添加链接描述

5. context包的用途

在 Go http包的Server中,每一个请求在都有一个对应的 goroutine 去处理。请求处理函数通常会启动额外的 goroutine 用来访问后端服务,比如数据库和RPC服务。用来处理一个请求的 goroutine 通常需要访问一些与请求特定的数据,比如终端用户的身份认证信息、验证相关的token、请求的截止时间。 当一个请求被取消或超时时,所有用来处理该请求的 goroutine 都应该迅速退出,然后系统才能释放这些 goroutine 占用的资源。
在Google 内部,我们开发了 Context 包,专门用来简化 对于处理单个请求的多个 goroutine 之间与请求域的数据、取消信号、截止时间等相关操作,这些操作可能涉及多个 API 调用

一句话:context 用来解决 goroutine 之间退出通知、元数据传递的功能。

6. client如何实现长连接

在Golang中使用持久化连接发起HTTP请求,主要依赖Transport,官方封装的net库中已经支持。

Transport实现了RoundTripper接口,该接口只有一个方法RoundTrip(),故Transport的入口函数就是RoundTrip()。
Transport的主要功能:

缓存了长连接,用于大量http请求场景下的连接复用
对连接做一些限制,连接超时时间,每个host的最大连接数

5

7. 主协程如何等其余协程完再操作

方法一:sync.WaitGroup
方法二:contextContext
添加链接描述

8. slice,len,cap,共享,扩容

9. map如何顺序读取

10. 实现set

11. 实现消息队列(多生产者,多消费者)

12. 大文件排序基本排

13. 哪些是稳定的

14. http get跟head

15. http 401,403

16. http keep-alive

17. http能不能一次连接多次请求,不等后端返回

18. tcp与udp区别,udp优点,适用场景

19. time-wait的作用

20. 数据库如何建索引

21. 孤儿进程,僵尸进程

22. mysql底层有哪几种实现方式

—4—

添加链接描述

1. 垃圾回收

—5—

添加链接描述

—6—

添加链接描述

—7—

添加链接描述

Golang面经ChannelContextGoroutine

目录

Channel

Channel是Go中的一个核心类型,你可以把它看成一个管道,通过它并发核心单元就可以发送或者接收数据进行通讯(communication)。
它的操作符是箭头 <-
channel一般用于协程之间的通信,channel也可以用于并发控制。比如主协程启动N个子协程,主协程等待所有子协程退出后再继续后续流程,这种场景下channel也可轻易实现。

ch <- v    // 发送值v到Channel ch中 
v := <-ch  // 从Channel ch中接收数据,并将数据赋值给v
(箭头的指向就是数据的流向)

就像 map 和 slice 数据类型一样, channel必须先创建再使用:
ch := make(chan int, 100) // 使用make初始化Channel,并且可以设置容量

Channel读写特性(15字口诀)

首先,我们先复习一下Channel都有哪些特性?

  • 给一个 nil channel 发送数据,造成永远阻塞
  • 从一个 nil channel 接收数据,造成永远阻塞
  • 给一个已经关闭的 channel 发送数据,引起 panic
  • 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值
  • 无缓冲的channel是同步的,而有缓冲的channel是非同步的

以上5个特性是死东西,也可以通过口诀来记忆:“空读写阻塞,写关闭异常,读关闭空零”。

使用channel来控制子协程的优点是实现简单,缺点是当需要大量创建协程时就需要有相同数量的channel,而且对于子协程继续派生出来的协程不方便控制。

channel线程安全

如果把线程安全定义为允许多个goroutine同时去读写,那么golang 的channel 是线程安全的。不需要在并发读写同一个channe时加锁。
Golang的Channel,发送一个数据到Channel 和 从Channel接收一个数据 都是 原子性的。
而且Go的设计思想就是:不要通过共享内存来通信,而是通过通信来共享内存,前者就是传统的加锁,后者就是Channel。
也就是说,设计Channel的主要目的就是在多任务间传递数据的,这当然是安全的

限制goroutine的数量

如何限制goroutine的数量
限制goroutine的数量

尝试 chan

使用带缓冲的channel,当channel数量达到限制的最大数量时,会阻塞。

以下是没有使用waitgroup的情况,最后结果是并不是所有的url都打印了,这当然不是想要的结果。

package main

import (
    "fmt"
    "sync"
    "time"
)
var maxRoutineNum = 2
// routine限制最大数量
func main()
    ch := make(chan int, maxRoutineNum)
    var urls = []string
        "http://www.golang.org/",
        "http://www.google.com/",
        "http://www.somestupidname.com/",
        "http://www.golang.org/11",
        "http://www.google.com/11",
        "http://www.somestupidname.com/11",
        "http://www.golang.org/22",
        "http://www.google.com/22",
        "http://www.somestupidname.com/22",
        "http://www.golang.org/33",
        "http://www.google.com/33",
        "http://www.somestupidname.com/33",
    
    
    for _, u := range urls 
        
        ch <- 1
        
        go download1(u, ch)
    

// 模拟下载方法
func download1(url string, ch chan int) 
    fmt.Println( url)
    // 休眠2秒模拟下载
    time.Sleep(time.Second * 2)
    // 下载完成从ch取出数据
    x:= <- ch
    fmt.Println("x:",x)

![image.png](https://img-blog.csdnimg.cn/img_convert/9b1fc25926ee08d436c3eddf4ff58ae0.png#clientId=ub6925226-3b16-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uf8774407&margin=[object Object]&name=image.png&originHeight=384&originWidth=338&originalType=url&ratio=1&rotation=0&showTitle=false&size=42294&status=done&style=none&taskId=ud5620e77-2852-49ae-80ad-78a1723b02a&title=)

但是新的问题出现了,因为并不是所有的goroutine都执行完了,在main函数退出之后,还有一些goroutine没有执行完就被强制结束了。这个时候我们就需要用到sync.WaitGroup。使用WaitGroup等待所有的goroutine退出。如下:

package main
 
import (
	"fmt"
	"sync"
	"time"
)
var maxRoutineNum = 2
// routine限制最大数量
func main()
	ch := make(chan int, maxRoutineNum)
	var urls = []string
		"http://www.golang.org/",
		"http://www.google.com/",
		"http://www.somestupidname.com/",
		"http://www.golang.org/11",
		"http://www.google.com/11",
		"http://www.somestupidname.com/11",
		"http://www.golang.org/22",
		"http://www.google.com/22",
		"http://www.somestupidname.com/22",
		"http://www.golang.org/33",
		"http://www.google.com/33",
		"http://www.somestupidname.com/33",
	
	wg := sync.WaitGroup
	for _, u := range urls 
		wg.Add(1)
		ch <- 1
		go download(u, ch, &wg)
	
	wg.Wait()

// 模拟下载方法
func download(url string, ch chan int , wg *sync.WaitGroup) 
	fmt.Println( url)
	// 休眠2秒模拟下载
	time.Sleep(time.Second * 2)
	// 下载完成从ch取出数据
	x:= <- ch
	wg.Done()
 
	fmt.Println("x:",x)

![image.png](https://img-blog.csdnimg.cn/img_convert/ce27e30981b12e054a5753f0694a5209.png#clientId=ub6925226-3b16-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ubb8e3dbc&margin=[object Object]&name=image.png&originHeight=431&originWidth=345&originalType=url&ratio=1&rotation=0&showTitle=false&size=45358&status=done&style=none&taskId=ua98e36d2-a756-4acf-9822-cff9b098037&title=)

Context

Golang context是Golang应用开发常用的并发控制技术,它与WaitGroup最大的不同点是context对于派生goroutine有更强的控制力,它可以控制多级的goroutine。
context翻译成中文是”上下文”,即它可以控制一组呈树状结构的goroutine,每个goroutine拥有相同的上下文。
![image.png](https://img-blog.csdnimg.cn/img_convert/2e039d6d06d050f8b1cb329656388dc3.png#clientId=uf27bda7a-6a20-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uf8e007b6&margin=[object Object]&name=image.png&originHeight=356&originWidth=590&originalType=url&ratio=1&rotation=0&showTitle=false&size=16834&status=done&style=none&taskId=ufbdc6d36-316b-4fb0-a560-4fbee82902b&title=)

接口定义

源码包中src/context/context.go:Context 定义了该接口:

type Context interface 
    Deadline() (deadline time.Time, ok bool)
    
    Done() <-chan struct
    
    Err() error
    
    Value(key interface) interface

基础的context接口只定义了4个方法,下面分别简要说明一下:

Deadline()

该方法返回一个deadline和标识是否已设置deadline的bool值,如果没有设置deadline,则ok == false,此时deadline为一个初始值的time.Time值

Done()

该方法返回一个channel,需要在select-case语句中使用,如”case <-context.Done():”。
当context关闭后,Done()返回一个被关闭的管道,关闭的管道仍然是可读的,据此goroutine可以收到关闭请求;
当context还未关闭时,Done()返回nil。

Err()

该方法描述context关闭的原因。关闭原因由context实现控制,不需要用户设置。比如Deadline context,关闭原因可能是因为deadline,也可能提前被主动关闭,那么关闭原因就会不同:

  • 因deadline关闭:“context deadline exceeded”;
  • 因主动关闭: “context canceled”。

当context关闭后,Err()返回context的关闭原因;
当context还未关闭时,Err()返回nil;

Value()

有一种context,它不是用于控制呈树状分布的goroutine,而是用于在树状分布的goroutine间传递信息。
Value()方法就是用于此种类型的context,该方法根据key值查询map中的value。具体使用后面示例说明。

  • Context仅仅是一个接口定义,根据实现的不同,可以衍生出不同的context类型;
  • cancelCtx实现了Context接口,通过WithCancel()创建cancelCtx实例;
  • timerCtx实现了Context接口,通过WithDeadline()和WithTimeout()创建timerCtx实例;
  • valueCtx实现了Context接口,通过WithValue()创建valueCtx实例;
  • 三种context实例可互为父节点,从而可以组合成不同的应用形式;

更多文章如下:

【面向校招】全力备战2023Golang实习与校招

欢迎进群共同进步:
QQ群:1007576722

阅读世界,共赴山海 423全民读书节,邀你共读

以上是关于golang 面经积累的主要内容,如果未能解决你的问题,请参考以下文章

Golang面经ChannelContextGoroutine

Golang面经ChannelContextGoroutine

第三十四期Golang社招面经-快手

Golang开发面经字节跳动(三轮技术面)

第三十二期春招 Golang实习面经 七牛

Golang开发面经360(一轮游)