22年春天的一部分面经

 竹云科技一二三面:

讲项目(看到我安全开发较多,延伸到)企业或者服务的安全隐患有哪些?(我答外部黑客攻击,漏洞及社工泄密;总结到内部隐患更大)-》安全防护措施有什么?-〉(面试官指出预防工作更重要,引出)零信任体系(我面的岗就是做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()
}

你可能感兴趣的:(linq,golang,microsoft)