竹云科技一二三面:
讲项目(看到我安全开发较多,延伸到)企业或者服务的安全隐患有哪些?(我答外部黑客攻击,漏洞及社工泄密;总结到内部隐患更大)-》安全防护措施有什么?-〉(面试官指出预防工作更重要,引出)零信任体系(我面的岗就是做IAM)
Go:channel;GPM;切片扩容;sync包还用过什么?(map,waitgroup,mutex等)
Go channel 实现原理分析 - 简书
深入理解Go的slice及其扩容规则 | QXQZX's Blog
GoLang GPM模型 - Go语言中文网 - Golang中文社区
Go语言sync包的应用详解 - 知乎
mysql:SQL优化
建表过程中:尽量使用vchar代替char,对经常查询和排序的字段建立索引,尽量使用组合索引
查询过程中:尽量避免索引失效情况,避免全表查询,避免select * ,组合索引中符合最左原则
Redis:数据类型,如何保证高可用?(集群,主从读写分离+同步,哨兵,内存淘汰)
https 具体过程(ca,证书链校验过程,非对称加密交换随机KEY,对称加密数据),ssl算法
全网最透彻HTTPS(面试常问)
写一个生产者消费者模型,生产者每次产生一百条数据,消费者每次读十条:
package main
import (
"fmt"
"sync"
)
func main(){
var mychan =make(chan int,100)
var mymutex = sync.Mutex{}
var wg sync.WaitGroup
wg.Add(10)
var p Producer
var w Worker
go p.Produce(&mychan,&mymutex)
var res []int
for i:=0;i<10;i++{
go w.Consume(&mychan,&wg,&res)
}
wg.Wait()
close(mychan)
}
type Producer struct {
}
type Worker struct{
}
func (p *Producer)Produce(mychan *chan int,mymutex *sync.Mutex){
mymutex.Lock()
for i:=0;i<100;i++{
*mychan <-i
}
mymutex.Unlock()
}
func (w *Worker)Consume(mychan *chan int,wg *sync.WaitGroup,res *[]int){
for i:=0;i<10;i++{
data := <-*mychan
fmt.Println(data)
*res = append(*res,data)
}
wg.Done()
}
敏于行一面:
go :GPM模型,new与make区别,锁,
mysql:锁 ,事务
项目中遇到的问题,周期
职业规划。。(我估计就是这里说漏嘴了,面试官最后问有没有回西安的打算,我说过几年,然后就截止一面了)
泰尔英福一面:
go:make与new 区别;内存泄漏(现象是内存正在被某个进程消耗完毕,c中经常遇到,用到malloc申请的内存要用free释放,否则会发生内存泄漏,go中使用垃圾回收);init执行顺序(在main函数之前,模块包中的先执行,package main中的后执行);channel有无缓冲的区别(一句话,有缓冲的是channel读写操作是异步的,无缓冲的读写操作是同步的)
问时针分针一天相遇多少次
redis:持久化,数据丢失后如何恢复
工具:git如何回退;docker如何编译(具体到dockerfile中的命令)
mysql:索引;最左前缀
python: cls装饰器;并发
二面:
redis 如果内存满了怎么办(应该回答内存淘汰的策略)
rmq消费者都挂了怎么办,如何保证的只有一个消费者拿到任务
(场景题答的不好,没有过这种高并发的经验,面的岗也是做区块链的,聊不投机)
三面:
哈哈哈哈竟然让我说七层模型,太久没看没记住气死我了,TCP/IP协议在哪一层?应用层有什么协议?太厉害了,终于有人能把TCP/IP协议讲的明明白白了!-51CTO.COM
docker的安全如何保证?我举例docker中经常需要copy配置文件,明文存储会有泄漏数据的风险,对敏感数据加密,在程序中解密,可以防止数据泄露
滴滴面试:
自我介绍-》安全研发中遇到什么困难?
讲项目-》sso单点登录过程?
什么是单点登录(SSO)
mysql:索引,非聚簇和聚簇?(主键索引是聚簇,其余是非聚簇)具体什么场景用什么锁?如何保证主从一致?如何回滚?
MySql主从复制,从原理到实践!
red is:string的数据结构是?(sds) 内存淘汰机制?(定时删除,惰性删除)
go:channel详细,map slice 是并发安全吗 为啥,mutex,wait group
网络IO: epoll
做了一道题:使用滑动窗口算法(要注意边界情况)
package main
import "fmt"
/*
正整数nums求和》=target的连续子数组 最小的长度
*/
func minSubArrayLen(target int, nums []int) int {
var length = len(nums)
if length ==0{
return 0
}
var minlength = length
var sum = 0
for start,end:=0,0;end<=length && start <= end;{
if sum >= target{
tempMinLen := end-start
if tempMinLen < minlength{
minlength = tempMinLen
}
sum -= nums[start]
start++
}else{
if end < length{
sum += nums[end]
}
end ++
}
}
return minlength
}
func testMinSunArr(){
res := minSubArrayLen(7,[]int{2,3,1,2,4,3})
fmt.Println(res)
res1 := minSubArrayLen(4,[]int{1,4,4})
fmt.Println(res1)
}
func main(){
testMinSunArr()
}
Mysql索引面试题 - 割肉机 - 博客园s
深信服一面:(面的是蓝军攻防岗 )
go:GPM
mysql:请求量过大,如何调优?(1分库分表 2 使用集群,并说了主从同步 3 使用redis缓存热键)
redis:是否是单线程?(网络IO和kv读写是单线程)雪崩了怎么办?
网络IO: 邮件协议,epoll模型,是否抓过包,Linux抓包命令
会爬虫吗
讲钓鱼项目,遇到什么难题
深信服二面:
Go:channel底层。如何读写数据
网络IO模型,select epoll
项目,sso
平时学习来源,是否封装过底层数据结构,了解漏洞和挖掘技术吗?
深信服三面:
为什么离职啦。 职业规划啦。加班态度啦。
诚迈科技一面:
讲项目,为什么选择Rocket MQ
redis中有序集合底层的数据结构 (跳表加hash)
Mysql 写SQL语句,查学生表中各个年级的男女学生个数;分布式同步如何做?(问如果一个事物需要多个应用服务完成写操作,其中一个失败了,之前的事务需要回滚,还顺便说了回滚的原理)
Go:GPM ;slice与数组的区别,slice如何扩容;如果给已关闭的channel读写数据,分别有什么影响?(写的话回Panic,读的话,返回零值);异常如何捕获(defer 和recover)
算法:跳台阶问题,多个协程并发执行,如何保证顺序打印?
package main
import (
"fmt"
"sync"
)
func main(){
var (
Awg sync.WaitGroup
Bwg sync.WaitGroup
Cwg sync.WaitGroup
)
for i:=0;i<10;i++{
Awg.Add(1)
Bwg.Add(1)
Cwg.Add(1)
go func() {
fmt.Print("A")
Awg.Done()
}()
go func() {
Awg.Wait()
fmt.Print("B")
Bwg.Done()
}()
go func() {
Bwg.Wait()
fmt.Print("C")
Cwg.Done()
}()
Cwg.Wait()
fmt.Println()
}
}
抖音一面:
讲项目,职责,难点
redis set zset 底层数据结构
mysql 事务,隔离级别,mvcc,具体如何实现的读可提交和可重复读
TCP如何保证可靠,拥塞控制具体流程
go的垃圾回收
做了一道题(没写出来,脑子固住了
package main
import "fmt"
func main() {
var matrix = [][]int{[]int{1,2,3,10},[]int{4,5,6,11},[]int{7,8,9,12}}
fmt.Println(matrixPrint(matrix))
}
//顺时针转圈打印多维数组
func matrixPrint(matrix [][]int)[]int{
if len(matrix) == 0 || len(matrix[0]) == 0{
return []int{}
}
row, col := len(matrix),len(matrix[0])
var res []int
var rowStart,rowEnd,colStart,colEnd = 0,row-1,0,col-1
var times = row * col
for index, i,j:=0,rowStart-1,colStart-1;index < times;{
for i,j=i+1,j+1;index = colStart;j--{
res = append(res,matrix[i][j])
index++
}
rowEnd--
for i,j=i-1,j+1;index = rowStart;i--{
res = append(res,matrix[i][j])
index++
}
colStart++
}
return res
}
知乎一面:
关于锁:不释放的情况;不是自己释放的情况;
mysql:事务及四种特性靠什么实现?四种隔离状态及MVCC如何实现可重复读和读可提交;联合索引具体查询过程,B+树存的是什么?
Redis: 缓存失效的情况;击穿和雪崩情况如何处理?
RocketMQ: 如何保证消息不丢失?消费者如何消费?
做一道题:合并多个有序的子数组(知乎的面试官好酷啊,说面试先到这,留一道课后题,让我在云文档上做,可以查资料)
/*
有若干有序子数组, 合并为一个有序数组,M个子数组, 子数组的平均长度是 N
如:
A: 1, 3, 5, 7, 9
B: 2, 3, 5, 6, 8
C: 4, 6, 8, 9
D: ...
...
目标: 1, 2,3,3,4,5,5,6,6,7,8, 8 ,9,9 ...
要求:时间复杂度,空间复杂度最优。
*/
package main
import "fmt"
func main(){
TestMergeArrays()
}
func TestMergeArrays(){
var arrays = [][]int{{1, 3, 5, 7, 9},{2, 3, 5, 6, 8},{4, 6, 8, 9}}
res := MergeArraysByQuickSort(arrays) // 思路1:讲子数组所有元素添加到一个数组中,对数组使用快排
fmt.Println(res)
res = MergeArraysByMergeSort(arrays) // 思路2:对相邻的子数组使用归并,逐渐合并成大的有序子数组
fmt.Println(res)
}
func MergeArraysByQuickSort(arrays [][]int)[]int{
if len(arrays) == 0{
return []int{}
}
var mergeArrRes []int
for _, arr := range arrays{
mergeArrRes = append(mergeArrRes,arr...)
}
QuickSort(&mergeArrRes)
return mergeArrRes
}
func QuickSort(arr *[]int){
if len(*arr) == 0{
return
}
quick(arr,0,len(*arr)-1)
}
//挖坑填数法,选择一个基数(一般是第一个),两个指针指向头尾,
//比基数小的放在基数的左边,比基数大的放在基数的右边,
func quick(arr *[]int,left,right int){
low,high := left,right
pivot := (*arr)[low]
for low < high{
for low pivot{
high --
}
if low < high{
(*arr)[low] = (*arr)[high]
low++
}
for low 1{
quick(arr,left,low-1)
}
if right-low > 1{
quick(arr,low+1,right)
}
}
func MergeArraysByMergeSort(arrays [][]int)[]int{
if len(arrays) == 0{
return []int{}
}
var res []int
for _,array := range arrays{
res = merge(res,array)
}
return res
}
func merge(arr1,arr2 []int)[]int{
var brr []int
var (
i = 0
j = 0
len1 = len(arr1)
len2 = len(arr2)
)
for i
知乎二面
从项目出发,为什么用redis的set集合,set底层数据结构,插入查找的时间效率,设置过期时间的命令,定期删除的策略;为什么使用beanstalk,遇到过消息丢失吗?如何保证的?丢失了怎么办?mysql如何保证消息不丢失?redolog,undolog写在哪里?写一个SQL查询某字段中包含A B C?
mysql undo log位置_mysql binlog、redo log、undo log_zweig123的博客-CSDN博客
知乎一面(再投!)
算法:做一道二分查找的题,用循环和递归两种方法
package main
import (
"fmt"
)
/*
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。
*/
func FindTargetByArray(nums []int, target int)int{
if len(nums) == 0 || target < nums[0] || target > nums[len(nums)-1]{
return - 1
}
var start, mid, end = 0, 0, len(nums)-1
for start <= end {
mid = (start + end) / 2
if nums[mid] == target{
return mid
}
if nums[mid] > target{
end = mid - 1
}
if nums[mid] < target{
start = mid + 1
}
}
return -1
}
func FindTarget(nums []int, target int)int{
if len(nums) == 0 || target < nums[0] || target > nums[len(nums)-1]{
return - 1
}
var FindTargetByDigui func(int, int)int
FindTargetByDigui = func(start int,end int)int{
var mid int
var res = -1
if start <= end{
mid = (start + end) / 2
if nums[mid] == target{
return mid
}
if nums[mid] > target{
res = FindTargetByDigui(start,mid-1)
}
if res == -1 && nums[mid] < target{
res = FindTargetByDigui(mid+1,end)
}
}
return res
}
res := FindTargetByDigui(0,len(nums)-1)
return res
}
func TestFindTarget(){
var nums = []int{-1,0,3,5,9,12}
target := 9
fmt.Println(FindTarget(nums,target))
target = 2
fmt.Println(FindTargetByArray(nums,target))
}
func main(){
TestFindTarget()
}
go: 如果slice作为形参是值拷贝还是引用拷贝,(会对slice对象拷贝,但是slice结构体内部数组指针仍然指向原地址,没有拷贝数组本身) map的底层和扩容,sync.map和map的区别,做了什么优化,channel的底层,具体的读写过程,net包与gin的区别
golang sync.Map 原理以及性能分析_惜暮-CSDN博客_golang sync.map原理
深入理解 Go map:赋值和扩容迁移_QQ1528884535的专栏-CSDN博客
redis的持久化,RMQ持久化,与Kafka的区别
mysql 深翻页,这条sql的执行过程
select * from table_a where a = 1 and b = 2 limit 100000, 10
知乎二面:
redis 布隆过滤器
算法题:实现一个并发安全的map,PUT GET方法,并且在Get方法中,如果读不到,阻塞直到有值返回,10s超时返回err
package main
import (
"errors"
"sync"
"time"
)
/*
map 并法安全,get (a),阻塞直到有值,超时返回err
put // channel
get //
*/
type SafeMap struct {
MyMap map[interface{}]interface{}
MyMutex sync.Mutex
MyChanMap map[interface{}]chan interface{}
}
func CreateMap() *SafeMap{
var sm SafeMap
sm.MyMap = make(map[interface{}]interface{})
sm.MyChanMap = make(map[interface{}]chan interface{})
return &sm
}
func(m *SafeMap) Put(key interface{}, value interface{}){
m.MyMap[key] = value
if _, exist := m.MyChanMap[key]; exist{
m.MyChanMap[key] <- value
close(m.MyChanMap[key])
}
}
func(m *SafeMap) Get(key interface{})(interface{},error){
if value,exist := m.MyMap[key]; exist{
return value,nil
}
if _, exist := m.MyChanMap[key]; !exist{
m.MyChanMap[key] = make(chan interface{})
}
time.After(10*time.Second)
select {
case value := <-m.MyChanMap[key]:return value,nil
}
// timeout
return nil,errors.New("time out!")
}
func main(){
}
旷视科技一面:
Go: GC具体回收哪里的对象(堆);堆和栈的区别?内存逃逸?说一说slice,底层?说一说map;struct{}占多大内存?(0)怎么使用?(当占位符用,管道中不存储实际数据,只用作信号使用时)用过pprof吗?平时用过什么库?以下代码有什么问题,如何修改?
func main() {
var slice = []int{100, 200, 300, 400, 500}
wg := sync.WaitGroup{}
for i, s := range slice {
go func() {
wg.Add(1)
defer wg.Done()
fmt.Println("[", i, "]", ":", s)
}()
}
wg.Wait()
}
//不会打印任何东西主进程直接结束,修改:
func main() {
var slice = []int{100, 200, 300, 400, 500}
wg := sync.WaitGroup{}
wg.Add(len(slice))
for i, s := range slice {
go func(i,s int) {
defer wg.Done()
fmt.Println("[", i, "]", ":", s)
}(i,s)
}
wg.Wait()
}
解释rocket MQ工作机制?如何解决Redis内存满的情况?Redis的持久化?
mysql:说一说索引及B+树,什么时候建索引?怎么调优?用过expire吗?
场景题:现在有100000个Goruntine,同一时间如何保证最多只有100个Goruntine在运行?(使用一个长度为100的channel,携程内部往里写数据,协程退出前读数据,由于读写channel是原子性,可以保证只有100个协程正在运行,其余会被阻塞住)
Linux上运行的服务器挂了,一般会怎么排查?查看日志的命令?(tail -f 实时查看,cat |grep过滤查看)
请用面向对象的编程方式找出数组中和=target的两个数字
package main
import (
"errors"
"fmt"
"sync"
)
func main() {
Test()
}
type ArrayInter interface {
FindTwoNums()(int,int,error)
}
type ArraySum struct {
Array []int
Target int
}
func(as *ArraySum)FindTwoNums()(int,int,error){
if len(as.Array) == 0{
return -1,-1,errors.New("数组中没有值!")
}
var myMap = make(map[int]int) // 差值:index
for index,num := range as.Array{
if anaIndex,exist:=myMap[num];exist{
return anaIndex,index,nil
}
myMap[as.Target-num] = index
}
return -1,-1,errors.New("没有符合要求的数!")
}
func Test(){
var myStruct = ArraySum{[]int{1,3,5,2,4,6},11}
var myInter ArrayInter = &myStruct
index1,index2,err := myInter.FindTwoNums()
if err != nil{
fmt.Println(index1,index2,err.Error())
}else{
fmt.Println(index1,index2,nil)
}
var myStruct2 = ArraySum{[]int{1,3,7,2,5,15},11}
var myInter2 ArrayInter = &myStruct2
index1,index2,err = myInter2.FindTwoNums()
if err != nil{
fmt.Println(index1,index2,err.Error())
}else{
fmt.Println(index1,index2,nil)
}
var myStruct3 ArraySum = ArraySum{[]int{},11}
var myInter3 ArrayInter = &myStruct3
index1,index2,err = myInter3.FindTwoNums()
if err != nil{
fmt.Println(index1,index2,err.Error())
}else{
fmt.Println(index1,index2,nil)
}
}
旷视二面&三面:
场景题,API中需要调用其他微服务,并五分钟超时返回,如何设计?
项目中遇到什么情况需要用到什么数据结构?
TCP 长连接和短链接区别?
你觉得gorm 有哪些地方设计不合理? (0值问题)
shopee一面:
讲项目:详细讲mysql查询过程的耗时,以及为什么用了redis就快?
做了两道题:找两个节点的最近公共父节点;将二叉搜索树转换成二叉累加树;
(这个公司我不理解啊,两道算法题都写出来了,为什么一面后就没消息了?!)
地平线一面:
项目:使用的是master-worker模式,是否遇到过数据过多,消费者来不及消费的情况?(manager根据一定负载均衡策略增加或减少worker)使用beanstalk作为分布式消息队列,为什么这样选型?那如何使用redis完成分布式消息队列?(我说list),如果想在10000个数据中查找出100个数据呢?(zset) zset的底层数据结构(hash+跳跃表)
sso机制,(什么是单点登录(SSO), jwt与cookie的区别?http请求方法,响应码,
Go:slice的扩容,底层,内存泄漏的情况,(未等待协程执行完毕)如何预防?(wait group)如何检测(pprof)进程线程协程的区别,GMP模型
进程:进程是系统进行资源分配的基本单位,有独立的内存空间。
线程:线程是 CPU 调度和分派的基本单位,线程依附于进程存在,每个线程会共享父进程的资源。
协程:协程是一种用户态的轻量级线程,协程的调度完全由用户控制,协程间切换只需要保存任务的上下文,没有内核的开销。
docker: build,push,run,load,save,如何减小镜像的大小?(使用&符号将多个RUN命令连接在一起?)
mysql:InnoDB什么锁? 对于商品表的库存字段现在有高并发的读写请求问我怎么办?(将库存拆成多行,减少对一个行锁的并发量)
口述快排;
请用工厂模式设计一个能返回不同类型的方法?
package main
import (
"encoding/json"
"encoding/xml"
)
type ReturnSt interface {
output ()interface{}
}
type JsonOutPut struct {
Data string `json:"data"`
}
type XmlOutPut struct {
Data string
}
func (jt *JsonOutPut)output()interface{}{
res, err := json.Marshal(jt)
if err != nil{
return nil
}
return res
}
func (xt *XmlOutPut)output()interface{}{
res, err := xml.Marshal(xt)
if err != nil{
return nil
}
return res
}
func ReturnApi(DataType string)interface{}{
var res interface{}
var myInterface ReturnSt
switch DataType {
case "json":{
var jt = JsonOutPut{"hello world"}
myInterface = &jt
}
case "xml":{
var xt = XmlOutPut{"hello world"}
myInterface = &xt
}
}
myInterface.output()
return res
}
地平线二面:
说了一系列场景问我怎么从日志中定位出请求,想让我回答链路监控
redis内存满的情况,我回答LRU和横向扩容
集群如何保证高可用? 我回答AOF RDB 哨兵
Mysql 可以不设主键创建表吗?主键的目的?什么情况会死锁?
写代码:大文件读,文件中每一行是用户ID,一个已知的RPC接口是根据ID获取Mail,输出ID文件对应的Mail文件
package main
import (
"bufio"
"errors"
"os"
"sync"
)
func GetMailById(id string)string{
return ""
}
func readDoc(p int64, wg *sync.WaitGroup, myChan *chan string)error{
defer wg.Done()
file, err := os.Open("./userid")
file.Seek(p,1)
//mailfile ,err := os.Open("./mail"+string(p)+".txt")
if err != nil{
return errors.New("open file error")
}
defer file.Close()
buf := bufio.NewReader(file)
for{
id ,_, err := buf.ReadLine() ///
if err != nil{
return errors.New("open file error")
}
//mail := GetMailById(string(id))
//mailfile.Write([]byte(mail))
*myChan <- string(id)
}
}
func GetMail(){
var wg sync.WaitGroup
wg.Add(10)
var myChan = make(chan string)
for i:=0;i<100000;i+=10000{
go readDoc(int64(i),&wg,&myChan)
}
wg.Wait()
}
地平线三面:
讲项目,职业规划,介绍他们公司业务场景,问是不是我期望岗位,做一道算法题,
package main
import (
"fmt"
"os"
"sort"
"sync"
)
/*
M个有序数组求交集
编写函数,M个有序数组求交集
array1 = [1,2,4,5,6,...........,10000];
array2 = [32,55,64,65,66,68,69,988];
array3 = [64,65,67,68,99,688];
...
arrayM = [...]
*/
func MergeArray(arrays [][]int)[]int{
if len(arrays) == 0 || len(arrays[0]) == 0{
return []int{}
}
var MyMap = make(map[int]int)
for _,array := range arrays{
for _, num := range array{
if times, exist := MyMap[num];exist{
MyMap[num] = times + 1
}else{
MyMap[num] = 1
}
}
}
lenArr := len(arrays)
var res []int
for _, num := range MyMap{
if MyMap[num] == lenArr{
res = append(res, num)
}
}
sort.Ints(res)
return res
}
// m file
func MergeFile(files []string){
if len(files) == 0{
return
}
}
func Merge(files []string) string{
var lens = len(files)
if lens < 2{
return ""
}
firstLen := lens/2
var resFiles []string
var wg sync.WaitGroup
wg.Add(2)
go func(){
var resFile = files[0]
for i:=1;i<=firstLen;i++{
resFile = MergeJiao(resFile,files[i])
}
resFiles = append(resFiles,resFile)
wg.Done()
}()
go func(){
var resFile = files[firstLen+1]
for i:=firstLen+1;i
百度一面:
Go:讲一下map,是并发安全的吗?那如何做到并发安全?(我答使用sync.map或者加锁控制)常用什么锁?读写锁的工作机制?一种情况:大量协程对一个对象加读锁,导致写锁加不上的情况如何处理?协程线程的区别?创建的开销都包括什么?defer关键字的特性?一种情况:在一个函数内部创建了协程,协程中引发Panic,外层函数能否捕获?(捕获不到啊!)map和slice是值传递吗?slice扩容机制?go run命令执行时都发生什么了?
//测试 值传递
package main
import "fmt"
func main(){
var mymap = make(map[int]int,1)
var myChan = make(chan int,1)
var mySlice = make([]int,4)
var s ="chenchen"
var mystruct = struct {
Name *string
Age int
}{&s,16}
mySlice = append(mySlice,-1)
test(mymap,myChan,mySlice,mystruct)
fmt.Println(mymap[1])
fmt.Println(<-myChan)
fmt.Println(mySlice)
fmt.Println(*mystruct.Name,mystruct.Age)
}
func test(myMap map[int]int,myChan chan int,mySlice []int,myStruct struct{Name *string
Age int}){
myMap[1] = 1
myChan <- 1
mySlice[0] = 1
*myStruct.Name = "hhhhhh"
myStruct.Age = 24
}
package main
import "fmt"
func expe (){
var myChan chan int
close(myChan)
myChan <- 1
}
func main(){
defer fmt.Print("主函数退出前")
defer func() {
if r := recover(); r != nil {
fmt.Printf("捕获到的错误:%s\n", r)
}
}()
go expe()
}
redis: 说一下数据结构,zset底层?跳表的插入,查找时间复杂度?zset的插入,查找时间复杂度?redis雪崩,击穿,穿透的情况和预防方法?(穿透:在接口中对参数进行校验)那ID很大这种非法参数如何校验?(用一个计数器存放ID的最大值,计数器存在redis当中)
Redis命令时间复杂度查询表 - liuxinyu123 - 博客园
聊聊Mysql索引和redis跳表 ---redis的有序集合zset数据结构底层采用了跳表原理 时间复杂度O(logn)(阿里) - aspirant - 博客园
https说一下,具体的证书验签过程?能说一下CSRF攻击吗?
Linux:awk命令用过吗?如何查找日志中某个IP的PV?
Linux服务器问题排查思路及常用命令 - 晓呆 - 博客园
代码实现:一个生产者,每次从【-50,50】中获取一个随机数,两个消费者并发去读,一个只消费正数,一个只消费负数。(这题写的稀碎)
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
func CreateRandom()int{
res := rand.Int31n(50)
zf := rand.Int31n(2)
switch zf {
case 0: res = 0 - res
}
return int(res)
}
type Producer struct{}
type Consumer struct {
}
func (p *Producer)Produce(zhengChan *chan int,fuChan *chan int){
data := CreateRandom()
if data >= 0 {
*zhengChan <- data
}else{
*fuChan <- data
}
}
func (c *Consumer)ConsumeZheng(zhengChan * chan int,wg *sync.WaitGroup){
for data := range *zhengChan{
fmt.Println("consumer zheng:", data)
wg.Done()
}
}
func (c *Consumer)ConsumeFu(fuChan * chan int,wg *sync.WaitGroup){
for data := range *fuChan{
fmt.Println("consumer fu:", data)
wg.Done()
}
}
func main(){
var p Producer
var zhengChan = make(chan int,100)
var fuChan = make(chan int,100)
var wg sync.WaitGroup
wg.Add(100)
var c Consumer
go c.ConsumeZheng(&zhengChan,&wg)
go c.ConsumeFu(&fuChan,&wg)
rand.Seed(time.Now().Unix())
for i:=0;i<100;i++{
//time.Sleep(time.Second*1)
p.Produce(&zhengChan,&fuChan)
}
wg.Wait()
close(zhengChan)
close(fuChan)
}
头条一面(再投字节!
讲项目,模块设计
mysql 的锁,mvcc机制,具体什么场景用什么锁
共享锁(S锁):共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。
如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。
排他锁(X锁):用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。
如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。
redis 底层数据结构,sds为什么这么设计,redis的主从同步过程,是谁主动的?
在 C 语言中,字符串采用的是一个 char 数组(柔性数组)来存储字符串,而且字符串必须要以一个空字符串 \0 来结尾。而且字符串并不记录长度,所以如果想要获取一个字符串的长度就必须遍历整个字符串,直到遇到第一个 \0 为止(\0 不会计入字符串长度),故而获取字符串长度的时间复杂度为 O(n)。
正因为 C 语言中是以遇到的第一个空字符 \0 来识别是否到了字符串末尾,因此其只能保存文本数据,不能保存图片,音频,视频和压缩文件等二进制数据,否则可能出现字符串不完整的问题,所以其是二进制不安全的。
Redis 中为了实现二进制安全的字符串,对原有 C 语言中的字符串实现做了改进。如下所示就是一个旧版本的 sds 字符串的结构定义:
struct sdshdr{
int len;//记录buf数组已使用的长度,即SDS的长度(不包含末尾的'\0')
int free;//记录buf数组中未使用的长度
char buf[];//字节数组,用来保存字符串
}
经过改进之后,如果想要获取 sds 的长度不用去遍历 buf 数组了,直接读取 len 属性就可以得到长度,时间复杂度一下就变成了 O(1),而且因为判断字符串长度不再依赖空字符 \0,所以其能存储图片,音频,视频和压缩文件等二进制数据,不用担心读取到的字符串不完整。
RMQ如何保证消息可靠的?内部如何实现持久化?
写一个算法,求最长子串,子串中每个字符出现的次数不能超过两次
package main
import (
"fmt"
"strings"
)
func FindSubStr(s string) string{
if len(s) == 0 {
return ""
}
var myMap = make(map[rune]int)
var maxSubStr = s
var tempSubStr = "" //aabc
var maxLen = 0
for _, ch := range s{ //aab cbccgfded
// maxSubStr += string(ch)
if times,exist := myMap[ch]; exist{
myMap[ch] = times + 1
}else{
myMap[ch] = 1
}
if myMap[ch] > 2{
splStr := strings.SplitN(maxSubStr,string(ch),2) //aab bcc
for _,subCh := range splStr[0]{
myMap[subCh] = myMap[subCh] - 1
}
myMap[ch] = myMap[ch] - 1
if len(splStr[0])+1 >= len(splStr[1]) {
if len(splStr[0])+1 > maxLen{
maxLen = len(splStr[0]) + 1
tempSubStr = splStr[0] + string(ch) // aab
}
}else{
if len(splStr[1])-1 > maxLen{
maxLen = len(splStr[1]) - 1
tempSubStr = splStr[1]
}
}
if len(splStr) > 1 {
maxSubStr = splStr[1] //bc cgfdedc
fmt.Println("111:",maxSubStr,tempSubStr)
}
}
}
return tempSubStr
}
func main(){
res := FindSubStr("aabcbccgfdedc")
fmt.Println(res)
}
头条二面:
讲项目-》redis与mysql的数据一致性如何保证-〉(先写redis,后写DB,如果DB失败,redis回滚)那回滚失败呢?(程序中将redis的回滚写到文件中,redis的持久化靠AOF RDB 保证)
package main
/*
标题
某游戏战力排行榜设计
题目描述
功能:
1. 显示某区服所有玩家的战力排行情况
2. 以及我自己的战力排行情况。
*/
import (
"container/list"
"fmt"
)
/*
标题
蛇形打印二叉树
题目描述
```
5
/ \
4 8
/ / \
11 13 1
/
7
```
==> 5, 4, 8, 1, 13, 11, 7
*/
type TreeNode struct{
Data int
Left *TreeNode
Right *TreeNode
}
func SnakePrintTree(root *TreeNode)[]int{
if root == nil{
return []int{}
}
var que = list.New()
que.PushBack(root)
var levelPrint = [][]int{}
for que.Len() != 0{
var temp = []int{}
var tempNode = []*TreeNode{}
for que.Len() != 0{
queNode := que.Front()
que.Remove(queNode)
node := queNode.Value.(*TreeNode)
tempNode = append(tempNode, node)
}
for _, node := range tempNode{
temp = append(temp,node.Data)
if node.Left != nil{
que.PushBack(node.Left)
}
if node.Right != nil{
que.PushBack(node.Right)
}}
levelPrint = append(levelPrint, temp)
}
fmt.Println(levelPrint)
var res []int
for i:=0;i=0;j--{
res = append(res,levelPrint[i][j])
}
}else{
for _,j:= range levelPrint[i]{
res = append(res,j)
}
}
}
return res
}
头条三面:
https的具体过程,http状态码,http2.0 有什么优化,TCP的拥塞控制,DNS协议;
写一道算法找最近公共父节点:
func FindParents(root,node,parent *TreeNode)*TreeNode{
if root == nil || node == nil{
return nil
}
if parent != nil && (parent.Left == node || parent.Right == node){
return parent
}
var res *TreeNode = nil
if root.Left != nil{
res = FindParents(root,node,root.Left)
}
if res == nil && root.Right != nil{
res = FindParents(root,node,root.Right)
}
return res
}
func FindAns(root,node1,node2 *TreeNode)*TreeNode{
var ans1,ans2 = []*TreeNode{node1}, []*TreeNode{node2}
for ans := node1; ans != root && ans != nil;{
ans = FindParents(root,ans,nil)
ans1 = append(ans1,ans)
}
for ans := node2; ans != root && ans != nil;{
ans = FindParents(root,ans,nil)
ans2 = append(ans2,ans)
}
for _, n1 := range ans1{
for _,n2 := range ans2{
if n1 == n2{
return n1
}
}
}
return nil
}
func TestFindParent() {
node := TreeNode{Data: 7, Left: nil, Right: nil}
var root = TreeNode{Data: 1,
Left: &TreeNode{Data: 4, Left: nil, Right: nil},
Right: &node}
res := FindParents(&root, &node, nil)
if res != nil {
fmt.Println(res.Data)
} else {
fmt.Println("not found")
}
}
func main() {
var root = TreeNode{Data: 5,
Left:&TreeNode{Data: 4,
Left:&TreeNode{Data: 11,Left:nil,Right:nil},
Right:nil},
Right:&TreeNode{Data: 8,Left:&TreeNode{Data: 13,Left:nil,Right:nil},
Right:&TreeNode{Data: 1,Left:nil,Right:nil}}}
res := SnakePrintTree(&root)
fmt.Println(res)
}
头条交叉面:
问了很多基础知识,mysql事务,隔离级别,存储引擎特点,redis数据类型,底层,go协程,TCP建立连接,可靠性,https,等等,没有深问,做了一道算法题,旋转数组(没做出来
package main
import "fmt"
func VolArray(arr *[][]int){
if len(*arr) == 0 || len((*arr)[0]) == 0{
return
}
var row,col = len((*arr)),len((*arr)[0])
for i:=0;i 0{
(*arr)[i][j] = (*arr)[row-j-1][i]
(*arr)[row-j-1][i] = (*arr)[i][row-j-1]
(*arr)[i][row-j-1] = (*arr)[row-j-1][i]
(*arr)[row-j-1][i] = ori
}
fmt.Println(*arr)
}
}
}
func TestVolArray(){
arr := [][]int{{1,2,3},{4,5,6},{7,8,9}} // -》 {{7,4,1},{8,5,2},{9,6,3}}
VolArray(&arr)
fmt.Println(arr)
}
func main() {
// var a int
// fmt.Scan(&a)
TestVolArray()
}