💼岗位职责:
- 负责基于 Go 的后端服务的设计、开发和维护;
- 参与系统架构设计,确保系统的高可用性、高性能和可扩展性;
- 编写高质量、可维护的代码,并进行代码评审;
- 解决复杂的技术问题,优化系统性能;
- 与跨职能团队合作,确保项目按时交付;
- 编写技术文档和开发规范,提升团队整体开发效率;
- 参与新技术的研究和引入,推动技术创新。
📋任职要求:
- 计算机科学或相关专业本科及以上学历,思维逻辑清晰;
- 熟悉 Go 语言的标准库和常用框架,了解 Go 语言的内存管理和并发模型;
- 具备微服务架构设计和开发经验,熟悉 gRPC、Protobuf 等技术;
- 熟悉常见的数据库(如 MySQL、PostgreSQL)和缓存技术(如 Redis);
- 有良好的代码风格和编写高质量单元测试的习惯;
- 熟悉 Docker、Kubernetes 等容器技术,具备一定的 DevOps 经验;
- 具备较强的分析和解决问题的能力,良好的沟通和团队协作能力;
- 有开源项目贡献者或个人技术博客者优先。
✨面试问题回顾:
1. 自我介绍
2. 选择一个项目或者需求详细介绍一下
根据自己的简历项目回答,要有理有据
3. 代码题,输出什么内容
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonStr := `{"id":321789788912372911233,"name":"John","age":30,"city":"New York"}`
var person map[string]interface{}
json.Unmarshal([]byte(jsonStr), &person)
person["married"] = true
person["children"] = []string{"Tom", "Jerry"}
fmt.Println(person)
jsonB,_ := json.Marshal(person)
fmt.Println(string(jsonB))
}
这段 Go 语言代码首先解析一个 JSON 字符串为 map[string]interface{}
类型的变量 person
。然后向 person
中添加了两个键值对 "married"
和 "children"
。接着打印出 person
,输出为一个包含所有键值对的 map。再将 person 序列化为 JSON 字符串并打印,输出经过修改后的 JSON 字符串。
具体的输出为:
map[age:30 children:[Tom Jerry] city:New York id:3.2178978891237294e+20 married:true name:John]
{"age":30,"children":["Tom","Jerry"],"city":"New York","id":321789788912372940000,"married":true,"name":"John"}
- 代码题
package main
import "fmt"
func main() {
a, b := float64(2.0), float64(1.1)
fmt.Println(a - b)
}
输出 0.8999999999999999
。这是因为在计算机中浮点数的存储和计算存在精度问题。
4. tcp 拥塞控制算法
TCP 拥塞控制算法主要有以下几种:
- 慢启动:初始发送窗口较小,每收到一个 ACK,窗口大小呈指数增长。
- 拥塞避免:当窗口达到一定阈值后,窗口大小线性增长,以避免网络拥塞。
- 快速重传:当接收方连续收到三个重复的 ACK 时,立即重传丢失的报文段,而不必等待超时。
- 快速恢复:结合快速重传,调整窗口大小,快速恢复数据传输。
5. mvcc 底层实现原理
MVCC(多版本并发控制) 的底层实现原理如下:
在数据库中,每一行数据都可能有多个版本。当一个事务对某一行数据进行修改时,不会直接覆盖原数据,而是创建一个新的版本。每个版本都包含了该行数据在特定事务下的状态信息,如数据值、创建事务的 ID、删除事务的 ID(如果已被标记为删除)等。如果一个版本的创建事务 ID 小于等于当前事务 ID,且没有被一个事务 ID 小于当前事务 ID 的事务删除,那么这个版本对当前事务可见。读操作读取的是符合其事务隔离级别的版本,不会被未提交的事务影响。写操作会创建一个新的版本,而不是直接覆盖旧版本。通过这种方式,实现了并发事务之间的隔离,提高了数据库的并发性能。
6. 在有些实际生产中会将默认隔离级别调整至读提交,为什么,有什么好处
- 原因:默认的隔离级别可能无法满足某些应用场景对数据一致性和并发性能的要求。读提交隔离级别可以避免脏读,同时相比更高的隔离级别,如可重复读和串行化,具有更好的并发性能。
- 好处:提高了并发度,减少了锁的竞争,从而提高了数据库的整体性能。同时,避免了脏读,保证了数据的一定程度的一致性。
7. mysql 怎么实现乐观锁和悲观锁
- 悲观锁:通过在查询语句中使用
FOR UPDATE
等方式来实现。在事务中,对查询到的数据行加上排他锁,防止其他事务对其进行修改,直到当前事务提交或回滚。 - 乐观锁:通常在表中增加一个版本号字段。在读取数据时,同时读取版本号。在更新数据时,检查版本号是否与读取时一致,如果一致则更新数据并增加版本号,否则表示数据已经被其他事务修改,需要重新读取和处理。
8. 一条 sql 语句,匹配到了一条语句,会加什么锁,锁表还是锁行
这取决于具体的 SQL 语句和数据库的实现。如果是查询语句,一般不会加锁;如果是更新、删除等写操作语句,可能会加行锁或表锁。具体加哪种锁取决于数据库的锁策略、索引的使用情况以及事务的隔离级别等因素。
9. es 里面是怎么实现分页的,分页有哪几种方式
- 使用 from 和 size 参数进行分页。在查询中指定 from 参数表示从哪个文档开始返回结果,size 参数表示返回的文档数量。但这种方式在数据量大时性能较差,因为需要从每个分片上获取大量数据。
- 使用 scroll API 进行深度分页。它创建一个一次性的游标,用于遍历大量数据,但不适合用于实时用户请求。
10. 算法题 力扣 42 接雨水
题目描述:
给定 n
个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
双指针法解题思路:
双指针法的核心思想是从两端向中间移动,同时维护左右两边的最大高度。具体步骤如下:
- 初始化两个指针
left
和right
,分别指向数组的起始和结束位置。 - 初始化两个变量
leftMax
和rightMax
,分别表示左边和右边的最大高度。 - 当
left
小于right
时,进行以下操作: - 如果
height[left]
小于height[right]
,则更新leftMax
,并计算当前位置能接的雨水量,然后移动 · 指针。 - 否则,更新
rightMax
,并计算当前位置能接的雨水量,然后移动 right 指针。 - 最终返回总的雨水量。
具体的代码实现如下:
func trap(height []int) (ans int) {
left, right := 0, len(height)-1
leftMax, rightMax := 0, 0
for left < right {
leftMax = max(leftMax, height[left])
rightMax = max(rightMax, height[right])
if height[left] < height[right] {
ans += leftMax - height[left]
left++
} else {
ans += rightMax - height[right]
right--
}
}
return
}
欢迎关注 ❤
我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:sf面试群。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。