【Golang开发面经】得物(两轮技术面)

文章目录

  • 写在前面
  • 笔试
  • 一面
    • 你用过gorm?那我直接用sql不也可以吗?为什么用gorm?
    • 你用过哪些锁?
    • 那map是线程安全的吗?为什么?
    • chan呢?
    • 对一个关闭的chan读写会怎么样?
    • 算法:一道回溯的题目,不太记得了
  • 二面
    • redis 用过吧?你知道redis有多少种高可靠集群的模型?
    • redis 支持事务吗?
    • mysql 的隔离等级?
    • 最左匹配原则是什么?
    • 我能在性别这个字段上面建索引吗?为什么?
    • go 里面 context 是怎么用的?
    • rabbitmq 是如何保证消息不丢失的?
    • 发送方确认模式
    • 接收方确认机制
    • 9个球,外观一样,但有一个球是重一点,怎么快速找到这个特殊的球?

写在前面

得物一顿面试下来感觉还行吧,挺注重基础的,面试官水平也很高。就是聊的挺开心的。

笔试

一面

聊项目。大概20分钟吧,如何优化之类的。。

还有一些我不太记得了。。。太久远了。。。

你用过gorm?那我直接用sql不也可以吗?为什么用gorm?

用 sql 是可以,但是会有sql注入的风险,而gorm是通过占位符的形式来一定程度减少了sql的注入。

你用过哪些锁?

用过读写锁 sync 包下的排斥锁或是读写锁,这两种锁。

一般在出现数据竞争的情况下使用的。

那map是线程安全的吗?为什么?

不是的,map 会发生数据竞争,因为底层结构中 map 是没有锁的支持的。

chan呢?

chan的底层是有锁结构,所以是线程安全的。

对一个关闭的chan读写会怎么样?

对一个关闭的chan进行读:

  • 如果chan里面还有值,那么就读出chan里面的东西
  • 如果chan里面没有值了,就会读出这个chan类型的零值。

对一个关闭的chan进行写:

  • 直接panic

算法:一道回溯的题目,不太记得了

二面

我不太记得了。。。太久远了。。。

redis 用过吧?你知道redis有多少种高可靠集群的模型?

我目前了解到的是redis的哨兵模式。

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它独立运行。 其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

【Golang开发面经】得物(两轮技术面)_第1张图片

redis 支持事务吗?

不支持,redis不支持原子性,只是支持最终一致性。

mysql 的隔离等级?

  • 未提交读(READ UNCOMMITTED):READ UNCOMMITTED 提供了事务之间最小限度的隔离。除了容易产生虚幻的读操作和不能重复的读操作外,处于这个隔离级的事务可以读到其他事务还没有提交的数据,如果这个事务使用其他事务不提交的变化作为计算的基础,然后那些未提交的变化被它们的父事务撤销,这就导致了大量的数据变化。
  • 提交读(READ COMMITTED):READ COMMITTED 隔离级别的安全性比 REPEATABLE READ 隔离级别的安全性要差。处于 READ COMMITTED 级别的事务可以看到其他事务对数据的修改。也就是说,在事务处理期间,如果其他事务修改了相应的表,那么同一个事务的多个 SELECT 语句可能返回不同的结果。
  • 可重复读(REPEATABLE READ):在可重复读在这一隔离级别上,事务不会被看成是一个序列。不过,当前正在执行事务的变化仍然不能被外部看到,也就是说,如果用户在另外一个事务中执行同条 SELECT 语句数次,结果总是相同的。(因为正在执行的事务所产生的数据变化不能被外部看到)。
  • 序列化(SERIALIZABLE):如果隔离级别为序列化,则用户之间通过一个接一个顺序地执行当前的事务,这种隔离级别提供了事务之间最大限度的隔离。

最左匹配原则是什么?

索引的底层是一颗B+树,构建一颗B+树只能根据一个值来构建。此处的索引当然也包括联合索引,当索引类型为联合索引时,数据库会依据联合索引最左的字段来构建B+树,也叫最左匹配原则。

最左匹配原则:最左优先,以最左边的为起点任何连续的索引都能匹配上。 同时遇到范围查询(>、<、between、like)就会停止匹配。

我能在性别这个字段上面建索引吗?为什么?

关于区分度不高的字段,比如性别,比如状态字段,不应该建索引。索引并不是建了就快,唯一性太差的字段不需要创建索引,只有2种取值的字段,建了索引数据库也不一定会用,只会白白增加索引维护的额外开销。因为索引也是需要存储的,所以插入和更新的写入操作,同时需要插入和更新你这个字段的索引的。

我们也可以从索引的选择性这方面去说:索引的选择性是指索引列中不同值的数目和表的记录数的比值。 假如表里面有 1000 条数据,表索引列有 980 个不同的值,这时候索引的选择性就是 980/1000=0.98 。索引的选择性越接近 1,这个索引的效率很高。

性别可以认为是3种,男,女,其他。如果创建索引,查询语句 性别=‘男’的数据,索引的选择性就是3/1000=0.003。索引的选择性值很低,对查询提升不大,所以性别建索引意义不大。

go 里面 context 是怎么用的?

context 一般我们用来传递上下文信息,在go中,理解为goroutine的运行状态、现场,存在上下层goroutine context的传递,上层goroutine会把context传递给下层goroutine。

rabbitmq 是如何保证消息不丢失的?

发送方确认模式

将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一ID。一旦消息被投递到目的队列后,或者消息被写入磁盘后,信道会发送一个确认给生产者(包括消息的ID)。

如果RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack消息。

发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。

当确认消息到达生产者应用程序,生产者应用的回调方法就会被触发来处理确认消息。

接收方确认机制

消费者接受每一条消息后都必须进行确认,只要有消费者确认了消息,MQ才能安全的把消息从队列中删除。

这里并没有用到超时机制,MQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。保证了数据的最终一致性。

还有几种情况:

  • 如果消费者接受到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消费重复的隐患,需要去重)
  • 如果消费者接受到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙。则不会给该消费者分发更多的消息。

9个球,外观一样,但有一个球是重一点,怎么快速找到这个特殊的球?

最快两次就好了,分三组,第一组和第二组对比,如果相等,那么第三组抽两个出来就选出来了,如果不相等,就在重的那组抽两个出来对比就好了。如果抽出来的这两个一样重,那么就是第三个了。如果倾向另一边,那么就是一边的重了。

没有算法,很奇怪,因为每次面试都要手撕代码,这次没有反而觉得缺了点什么。。

你可能感兴趣的:(Go语言面试题目,golang,数据库,redis)