美文网首页
Go知识点

Go知识点

作者: ES_KYW | 来源:发表于2020-10-09 07:55 被阅读0次

    1、进程和线程的区别
    答:计算机由CPU和操作系统组成,CPU执行计算任务,操作系统执行资源调度任务。在操作系统上会有很多软件可以执行,每个软件的执行系统都会单独分配资源,即一个独立的进程,进程和进程之间是相互独立的,每个进程有单独的分配内存空间,进程是系统进行资源分配和调度的一个独立单位。每个进程都至少有一个线程,线程执行代码程序,共享进程的数据资源,线程是轻量级的,有自己的堆栈、寄存器,共享进程空间,一个进程可以有多个线程,并发执行由CPU控制时间段,做上下文切换,上下文切换由调度器控制,在不同的时间段内执行不同的线程,每次上下文切换的时候都保存当前状态,下次回来时重新从中断点开始接着执行。线程切换是轻量级的,相对于进程切换消耗更少的资源。进程由内存空间(代码、数据、进程空间,打开的文件)和一个或者多个线程组成。一个标准的线程由线程ID,当前指令指针PC,寄存器和栈组成。线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位,线程是一个进程中代码的不同执行路线。

    2、go的调度
    答:go支持多线程,在代码中我们可以通过关键字go创建一个线程,多线程并发执行,由系统调度切换上下文,即在不同的时间段分间断的执行不同的线程内容;

    3、go struct能不能比较
    Go是强类型语言,不能隐性转换,不同类型不能比较。但同一类型的实例值可以比较的。实例不可以比较,因为是指在类型

    4、go defer
    先进后出,后进先出

    5、select可以用于什么,常用语gorotine的完美退出
    select是Go的一个控制结构,类似于用于通信的switch语句,每个case语句必须是一个通信操作,要么是发送要么是接收。select随机执行一个可运行的case.如果没有case可以运行,它将阻塞,直到有case可运行。一个默认的子句总是可运行的。select会循环检查条件,如果有满足则执行并退出,否则一直循环检测,阻塞运行,直到有case可以运行。

    6、context包的用途Context通常被译作为上下文,它是一个比较抽象的概念,其本质是【上下上下】存在上下层的传递,上会把内容传递给下。在Go语言中,程序单元也就指的Goroutine
    答:系统在做线程调度的时候,会将产生中断,保存当前线程状态,切出到其他线程,执行其他线程,之后返回这个中断的线程,取出数据继续执行该线程。多线程并发就是CPU的时间片段之行,CPU总是顺序执行任务的,要达到并发就要不断的在不同线程间快速切换,切换过程中就会有线程的中断,数据的保存,线程的重启,数据的重读,上下文就是线程的调度,中断线程,保存数据,重读数据,继续执行线程。

    7、主协程如何等待其余协程操作完再执行
    利用channl和select,select是Go的控制语句,类似于switch,每个case语句都是一个通信操作,发送或者接收。如果没有满足条件的case,select会一直循环监听,阻塞线程,直到有case语句被执行

    8、slice,len,cap,共享,扩容
    slice的数据结构由指向数组的指针、len,cap组成,在使用append扩容的时候,会查看有没有可用的连续内存,如果有直接添加,没有就重新组成一个大的数组,扩容总是cap的倍数执行,如果原切片的容量大于等于1024时,每次增加25%。扩容slice后,指向的数组的指针发生改变,已不再指向原数组

    9、map如何顺序读取
    map是无序的,不能顺序读取,如果想要顺序读取,先要将key顺序化。用切片将排序,再给map依次赋值

    10、实现SET功能
    // 实现set

    type Set struct {
        sync.RWMutex
        v map[string]bool
    }
    
    func New() *Set {
        return &Set{
            sync.RWMutex{},
            map[string]bool{},
        }
    }
    // 不重复 添加
    func (s *Set)AddItem(val string)  {
        s.Lock()
        defer s.Unlock()
        s.v[val] = true
    }
    // 删除
    func (s *Set)RemoveItem(val string)  {
        s.Lock()
        defer s.Unlock()
        delete(s.v, val)
    }
    

    11、实现消息队列(多生产者,多消费者)
    带缓存channel 队列结构,先进先出

    12、大文件排序

    归并排序,分而治之,拆分为小文件,在排序

    13、基本排序,哪些是稳定的
    快速排序,冒泡排序,插入排序

    14 http中get和head的区别
    head请求中信息放在请求投中,没有返回体,get可在请求链接中拼接参数,有请求信息返回。
    用head请求可以判断某个资源是否存在

    15 401,403,404,502,504错误
    400:请求格式错误
    401:用户无权限
    403:拒绝访问
    404:找不到服务
    502:网关错误
    504:服务器错误

    16、http重连接机制 keep-alive
    请求头中加入Connection: keep-alive来告诉对方这个请求响应完成后不要关闭,下一次咱们还用这个请求继续交流。

    17、http能不能一次连接多次请求,不等后端返回
    http本质上市使用socket连接,因此发送请求,接写入tcp缓冲,是可以多次进行的,这也是http是无状态的原因

    18、主键索引和唯一索引的区别
    主键是一种约束,唯一索引是索引,本质不同。主键创建时默认创建唯一索引。主键不能为空,主键可以当作外键,主键唯一。唯一索引可以创建多个

    26、项目里的微信支付这块,在支付完微信通知这里,收到两次微信相同的支付通知,怎么防止重复消费
    redis锁(setNX)
    28、Go的反射包怎么找到对应的方法

    29、Redis基本数据结构

    31、Mysql的索引有几种,时间复杂度
    4种,主键、唯一、普通、全文,B+树,时间复杂度O(logn)
    32、InnoDb是表锁还是行锁,为什么
    InnoDb即支持行锁,也支持表锁,只有在通过索引检索数据时使用行锁。

    33、Go的channel(有缓冲和无缓冲)

    34、退出程序时怎么防止无缓存的channel没有消费完
    退出程序时将生产者关闭,不会有多余的数据给消费者消费

    35、用过什么消息中间件之类吗?

    38、生产者消费者模式,利用channel

    var wg  sync.WaitGroup
    // 生产者
    func Send(ch chan int){
        x := 0
        defer func(){
            close(ch)
            wg.Done()
        }()
        for i:=0;i<10;i++{
                x++
                ch <-
        }
    }
    // 消费者
    func Receive(ch chan int){
        defer func(){
            close(ch)
            wg.Done()
        }()
        for x := range ch {
            fmt.Println(x)
        }
    }
    
    func main(){
        ch := make(chan int)
        wg.Add(2)
        go Send(ch)
        go Receive(ch)
        wg.Wait()
        fmt.Println("任务完成")
    }
    

    39、手写循环队列

    // 循环队列
    type CircleQueue struct{
        queue []interface{}
        tail int
        front int
        cap int
    }
    
    // 创建循环对例
    func NewCircleQueue(n int) *CircleQueue  {
        loop := &CircleQueue{
            make([]interface{},0,n),
            0,
            0,
            n,
        }
        return loop
    }
    
    // 添加元素
    func (c *CircleQueue)AddQueue(a interface{}) bool {
        // 判断是否已经满了
        if c.front == (c.tail+1)%c.cap {
            return false
        }
        c.queue = append(c.queue,a)
        c.tail = (c.tail+1)%c.cap
        return true
    }
    
    // 删除元素
    func (c *CircleQueue)DeleteQueue() bool {
    
        if c.tail == c.front {
            return false
        }
        c.queue = c.queue[c.front:]
        c.front = (c.front+1)%c.cap
        return true
    }
    
    // 获取长度
    func (c *CircleQueue)Len()int {
        // 当c.tail == c.front时循环队列,不一定为空
        if c.tail == c.front && c.front != (c.tail+1)%c.cap{
            return 0
        }
        return c.tail - c.front
    }
    

    40、如何保证循环队列线程安全
    1.可以加锁。2.channel本身是一个带锁的队列,可以将结构体中的切片换成带缓存的channel

    42、Linux会不会,只会几个命令,一共也就一百多个命令

    43、TimeWait和CloseWait原因

    45、看过什么源码,nsq(Go的消息中间件)

    46、sync.Pool用过吗,为什么使用,对象池,避免频繁分配对象(GC有关),那里面的对象是固定的吗

    49、证明二叉树的叶子节点跟度数为2的节点的关系

    50、唯一索引和主键索引

    52、字符串解析为数字(考虑浮点型)

    53、单点登录,tcp粘包

    54、手写洗牌

    56、goroutine调度用了什么系统调用

    57、进程虚拟空间分布,全局变量放哪里

    58、有没有网络编程,有,怎么看连接状态?netstat,有哪些?ESTABLISHED,LISTEN等等,有异常情况吗?TIME_WAIT很多,为什么?

    59、几种基本排序算法说一下,问了堆的时间复杂度,稳定性,为什么不稳定
    快速排序、冒泡排序、插入排序
    61、什么是主键

    62、联合索引和唯一索引

    63、越多的索引越好吗?
    不是,占用资源,插入性能差

    64、建立索引要注意什么

    65、死锁?

    66、tcp三次握手

    67、http,https

    68、状态码401,301,302,201

    69、项目我说只有一台机子,所以用的单机部署,面试官说单机也可以部署多个,有什么方法吗?我说docker,问docker有哪些网络,不熟,dockerfile关键字,只答几个。顺便扯了下nginx转发。

    70、数据库隔离级别,提交读会造成什么

    71、go调度

    72、goroutine泄漏有没有处理,设置timeout,select加定时器

    73、mysql高可用的方案
    读写分离

    75、排序算法以及时间复杂度

    77、go的线程,给他讲了跟goroutine调度

    78、io模型,同步阻塞,同步非阻塞,异步

    79、cookie和session

    80、接口kps测试

    81、redis分布式,如何减少同步延迟

    93、go优缺点

    94、go的值传递和引用
    天生指针类型:map、channel、slice
    值类型:数组
    Golang默认采用值传递,即拷贝传递
    区别:
    函数调用数组时,默认会是值传递,在函数内部修改数组值,外部数组内容不会改变
    如果传入的是map,内部修改完后,外部也会改变

    相关文章

      网友评论

          本文标题:Go知识点

          本文链接:https://www.haomeiwen.com/subject/klinyktx.html