头图

文末有面经共享群

前面已经分享过几篇百度的面试了,这是其中一篇的面经详解,据粉丝说被疯狂拷打,大家一起来看看有那么难吗?

先来看看 职位描述

  • 工作职责:

    • 负责百度文库的服务端研发工作。
    • 精心编写核心代码,勇挑关键技术攻关重任。
    • 积极参与服务架构设计,独立完成业务需求的精准分析与巧妙设计。
    • 致力于现有服务框架的升级、性能优化以及稳定性建设。
    • 全力推动技术与产品创新,精心建设良好的技术文档,助力团队明晰需求和技术架构,大幅提高开发效率。
  • 任职资格:

    • 计算机或相关专业,本科及以上学历。
    • 拥有两年以上 Golang/PHP/Java/Python/C++ 项目开发经验,具备良好的编程习惯
    • 熟悉 Linux 操作系统和开发环境,拥有良好的数据结构、算法基础和系统设计能力。
    • 熟悉技术领域的通用组件如 Mysql、Redis、Kafka、ElasticSearch 等,在理论研究和实践经验方面造诣颇深,并能成功落地到业务中。
    • 熟悉 web service 相关技术,如高并发处理、存储与缓存,RPC、消息队列等技术。
    • 支付、会员、文档智能化等系统相关研发设计经验者优先。
    • 具备较好的团队合作精神,较强的沟通能力,主动性强,拥有很强的自我驱动力。
    • 拥有较好的产品意识,主动关注产品效果并积极推进产品方案的落实与完善。

面试流程

  1. 自我介绍
  2. 技能广度

    • 说明自己掌握多种语言,如Python、Java、Go、C/C++等。
  3. Go逃逸分析

    逃逸分析是 Go 语言编译器的一项重要优化技术。

    简单来说,逃逸分析用于确定一个变量的内存分配位置。它会分析变量的作用域和生命周期,来决定是在栈上分配内存还是在堆上分配内存。

为了理解Go 逃逸,我们要来看看变量可能会在哪些情况发生逃逸?

  1. 变量的作用域超出了其所在的函数:比如一个函数返回了一个局部变量的指针,由于函数返回后该局部变量仍然需要被访问,所以它不能在栈上分配,会逃逸到堆上。
func createPointer() *int {
    num := 5
    return &num
}

在这个例子中,num 变量发生了逃逸,因为函数返回了它的指针。

  1. 切片或映射等动态大小的数据结构:当为切片或映射分配内存时,如果其大小在编译时无法确定,那么这些变量可能会逃逸到堆上。
func createSlice() []int {
    return []int{1, 2, 3}
}
  1. 被全局变量引用:如果一个局部变量被全局变量引用,那么它也可能会逃逸。

我们可以通过 go build -gcflags="-m" 命令来查看编译器的逃逸分析结果。

  1. Gin的http方法怎么实现的

    • 路由注册:使用特定的方法来注册不同的路由路径和对应的处理函数。
    • 上下文对象(gin.Context):在处理函数中,通过 gin.Context 对象获取请求的相关信息,如请求参数、头部信息等,并设置响应的状态码、数据等。
    • 中间件支持:可以在路由处理之前或之后添加中间件来执行一些通用的逻辑,如日志记录、权限验证等。
    • 分组路由:可以将相关的路由分组,方便管理和组织。
    • 响应处理:设置响应的状态码、返回数据的格式(如 JSON、HTML 等)
    • 等等
  2. Gin框架的标签机制

    1. json 标签:用于将结构体字段与 JSON 数据进行绑定。
    2. uri 标签:用于从 URL 路径中提取参数。
    3. binding 标签:用于指定参数的验证规则。
    4. form 标签:用于将表单字段与结构体字段进行绑定。
  3. Channel了解吗

    • 内部结构
    • Channel 在内部由一个环形缓冲区两个等待队列组成。
    • 环形缓冲区用于存储发送的数据,当缓冲区满时,发送操作会阻塞,直到有接收操作取出数据腾出空间。
    • 两个等待队列分别用于存储因发送或接收操作而阻塞的 goroutine。当相应的条件满足(如缓冲区有空间可发送或有数据可接收),这些 goroutine 会被唤醒并继续执行。

      • 使用场景
    • 数据传递与共享
    • 任务分发与协调
    • 控制并发数量
    • 实现信号通知
    • 等等

Channel 的实现也说明了通过通信来共享内存

  1. Sync包有哪些东西

    • Mutex(互斥锁):用于保证在同一时刻只有一个 goroutine 可以访问共享资源,防止数据竞争。
    • RWMutex(读写互斥锁):提供了更细粒度的控制,允许多个 goroutine 同时读取共享资源,但在写操作时进行排他锁定。
    • Sync.Map:一种支持并发安全读写的 Map 数据结构,适用于多个 goroutine 同时读写的场景。
    • Sync.Once:确保某个操作只执行一次,常用于初始化只需要执行一次的共享资源。
    • Sync.Pool:对象池,用于复用临时对象,减少内存分配和垃圾回收的开销。
    • 等等
  2. HTTP状态码

    • 1XX 信息性状态码
    • 2XX 成功状态码
    • 3XX 重定向状态码
    • 4XX 客户端错误状态码
    • 5XX 服务器错误状态码
  3. HTTP状态码499

    • Nginx自定义状态,表示客户端在请求还未完成时关闭了连接。
  4. Redis应用与数据一致性

    • 可能会导致数据不一致的情况

      1. 并发操作:多个客户端同时对 Redis 中的数据进行读写操作,可能导致数据不一致。

        1. 数据过期:设置了过期时间的键,如果在过期时间到达之前没有及时更新或处理,可能导致数据不一致。
        2. 主从复制延迟:在 Redis 的主从架构中,主节点的数据变更需要同步到从节点,如果同步过程存在延迟,可能导致从节点读取到的数据与主节点不一致。
    • 解决数据一致性问题的方法

      1. 事务:使用一个原子操作,但需要注意的是,Redis 事务不支持回滚操作。
      2. 乐观锁:可以使用 Redis 的 WATCH 命令实现乐观锁机制。
      3. Lua 脚本:多个操作可以用lua脚本
  5. Mysql innodb为什么主键推荐用自增

    • 优化 B + 树结构InnoDB 使用 B + 树来组织数据,自增主键可以使 B + 树的结构更加紧凑和平衡减少树的深度,从而提高查找、插入和删除操作的性能。
    • 减少页分裂InnoDB 以页为单位存储数据,如果主键不是自增的,插入新数据时可能会导致页的频繁分裂和重组
    • 提高存储和查询性能:自增主键的数据分布更有序,有利于索引的构建和维护。
  6. Mysql删除数据,容量会不会变

不会变,因为删除操作只是在数据行上做了删除标记,而不是真正地从物理上删除数据和释放磁盘空间。

  1. Mysql表设计优化策略

    1. 为字段选择合适的数据类型
    2. 为字段选择合适的数值
    3. 合理设置字段属性
    4. 考虑存储引擎
    5. 索引优化
    6. 一些参数优化
    7. 连接数优化
    8. 等等
  2. 微服务架构利弊

    • 优点:

      • 独立部署和扩展
      • 灵活的技术选型
      • 容错性高
      • 职责明确
      • 敏捷开发
    • 缺点:

      • 分布式事务处理困难
      • 测试复杂性
      • 业务排查问题慢
      • 数据一致性
  3. 微服务故障排查技巧

    • 利用请求ID
    • 链路追踪
    • 监控工具
    • 日志记录
    • 测试环境复现
    • 等等
  4. 现场编码练习

    • 完成字符串处理任务。
  5. 提问环节

    • 询问业务方向、工作时间、工作薪资等。
  6. 面试反馈

结语

面试结束后,仅 30 分钟就约了周三的 HR 面,整个过程非常高效。
面试官全程未开摄像头,让我无法知晓对面的状态,但 Go 基础、Mysql 和微服务确实是提问的重点。希望这次面试经历能给大家带来启发和帮助,祝大家都能顺利拿下心仪的岗位!

欢迎关注 ❤

我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。

没准能让你能刷到自己意向公司的最新面试题呢。

感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:sf面试群。


王中阳Go
799 声望295 粉丝