热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Golang开发面经】滴滴(三轮技术面)

文章目录写在前面笔试一面进程间通信方式栈上分配内存快还是堆上,为什么?channel底层七层模型tcp、udpredis持久化的方式以及使用场景如何实现线程池


文章目录

  • 写在前面
  • 笔试
  • 一面
    • 进程间通信方式
    • 栈上分配内存快还是堆上,为什么?
    • channel 底层
    • 七层模型
    • tcp、udp
    • redis持久化的方式以及使用场景
    • 如何实现线程池?
    • 算法:二叉树俯视图
  • 二面
    • 怎么判断给定ip是否在给定ip区间内?
    • 如何优化慢SQL?
    • 什么情况不建议使用索引
    • 线程池的几种拒绝策略及其应用场景
    • http与tcp区别
    • 长连接与短连接
    • 讲讲tcp的挥手?
    • time wait,过多怎么办
    • 算法:忘了...
  • 三面


写在前面


滴滴面试感觉还行吧,挺注重基础的,很多时间都花在了挖项目上面,所以大家一定要很熟悉自己的项目!面试官水平也很高。不过也感叹这个曾经的大厂现在变成这个样子,唉。。



笔试


一面


进程间通信方式

管道、消息队列、信号量、共享内存


栈上分配内存快还是堆上,为什么?

显然从栈上分配内存更快,因为从栈上分配内存仅仅就是栈指针的移动而已


  1. 操作系统会在底层对栈提供支持,会分配专门的寄存器存放栈的地址
  2. 栈的入栈出栈操作也十分简单,并且有专门的指令执行,所以栈的效率比较高也比较快。
  3. 堆的生长空间向上,地址越来越大,栈的生长空间向下,地址越来越小。

channel 底层

type hchan struct {qcount uint // channel 里的元素计数dataqsiz uint // 可以缓冲的数量,如 ch := make(chan int, 10)。 此处的 10 即 dataqsizelemsize uint16 // 要发送或接收的数据类型大小buf unsafe.Pointer // 当 channel 设置了缓冲数量时,该 buf 指向一个存储缓冲数据的区域,该区域是一个循环队列的数据结构closed uint32 // 关闭状态sendx uint // 当 channel 设置了缓冲数量时,数据区域即循环队列此时已发送数据的索引位置recvx uint // 当 channel 设置了缓冲数量时,数据区域即循环队列此时已接收数据的索引位置recvq waitq // 想读取数据但又被阻塞住的 goroutine 队列sendq waitq // 想发送数据但又被阻塞住的 goroutine 队列lock mutex...
}

在这里插入图片描述


七层模型

从上而下分别是 应用层,表示层,会话层,传输层,网络层,数据链路层,物理层等等…


tcp、udp

TCP 是可靠传输,面向连接,基于流,占用资源多,效率低。

UDP是尽最大努力交付,基于无连接,基于报文,UDP 占用系统资源较少,效率高。


redis持久化的方式以及使用场景

Redis提供 RDB 和 AOF 两种持久化机制 , 有了持久化机制我们基本上就可以避免进程异常退出时所造成的数据丢失的问题了,Redis能在下一次重启的时候利用之间产生的持久化文件实现数据恢复


  • RDB持久化就是指的讲当前进程的数据生成快照存入到磁盘中,触发RDB机制又分为手动触发与自动触发

  • AOF 持久化是以独立的日志记录每次写命令,重启 Redis 的时候再重新执行AOF文件中命令以达到恢复数据,所以AOF主要就是解决持久化的实时性


如何实现线程池?

线程池有两部分组成:同步队列和线程池。


  • 同步队列:以链表的形式创建一个同步队列,同步队列的主要工作就是通过Put()函数向队列里面添加事务,通过Get()函数从队列里面取出事务。
  • 线程池:主要由线程组(注:线程组里面存放的时 thread 类型 的共享只能指针,指向工作的线程)构成,通过Start()函数向线程组中添加numThreads个线程,并使得每一个线程调用RunThread()函数来获取同步队列的事务并执行事务;通过Stop() 函数停止线程池的工作。

在这里插入图片描述


算法:二叉树俯视图


二面


怎么判断给定ip是否在给定ip区间内?


IP地址可以转换成整数,可以将IP返回化整为整数范围进行排查。


package mainimport ("fmt""strconv""strings"
)func main() {ipVerifyList :&#61; "192.168.1.0-192.172.3.255"ip :&#61; "192.170.223.1"ipSlice :&#61; strings.Split(ipVerifyList, &#96;-&#96;)if len(ipSlice) < 0 {return}if ip2Int(ip) >&#61; ip2Int(ipSlice[0]) && ip2Int(ip) <&#61; ip2Int(ipSlice[1]) {fmt.Println("ip in iplist")return}fmt.Println("ip not in iplist")
}func ip2Int(ip string) int64 {if len(ip) &#61;&#61; 0 {return 0}bits :&#61; strings.Split(ip, ".")if len(bits) < 4 {return 0}b0 :&#61; string2Int(bits[0])b1 :&#61; string2Int(bits[1])b2 :&#61; string2Int(bits[2])b3 :&#61; string2Int(bits[3])var sum int64sum &#43;&#61; int64(b0) << 24sum &#43;&#61; int64(b1) << 16sum &#43;&#61; int64(b2) << 8sum &#43;&#61; int64(b3)return sum
}func string2Int(in string) (out int) {out, _ &#61; strconv.Atoi(in)return
}

如何优化慢SQL&#xff1f;


  1. 查看是否使用到了索引。
  2. 查看 SQL语句 是否符合最左匹配原则。
  3. 对查询进行优化&#xff0c;尽可能避免全表扫描
  4. 字段冗余&#xff0c;减少跨库查询或多表连接操作
  5. 将一些常用的数据结构放在缓冲中&#xff08;部门名字&#xff0c;组织架构之类的&#xff09;&#xff0c;就不需要查数据库了。

什么情况不建议使用索引


  1. 在where条件中&#xff08;包括group by以及order by&#xff09;里用不到的字段不需要创建索引&#xff0c;索引的价值是快速定位&#xff0c;如果起不到定位的字段通常是不需要创建索引的。
  2. 数据量小的表最好不要使用索引&#xff0c;少于1000个
  3. 字段中如果有大量重复数据&#xff08;性别&#xff09;&#xff0c;也不用创建索引
  4. 避免对经常更新的表创建过多的索引。
  5. 不建议使用无序的值作为索引。

线程池的几种拒绝策略及其应用场景

当时都不知道这是个啥…
具体看这篇博客吧 线程池拒绝策略应用场景


http与tcp区别

http 就是基于传输层的 tcp 实现的一个应用层协议。


长连接与短连接

长连接意味着进行一次数据传输后&#xff0c;不关闭连接&#xff0c;长期保持连通状态。

短连接意味着每一次的数据传输都需要建立一个新的连接&#xff0c;用完再马上关闭它。下次再用的时候重新建立一个新的连接&#xff0c;如此反复。


讲讲tcp的挥手&#xff1f;

数据传输完毕之后&#xff0c;通信的双方都可释放连接。现在A和B都处于ESTABLISHED状态。


  1. A的应用进程先向TCP发出连接释放报文段&#xff0c;并停止再发送数据&#xff0c;主动关闭TCP连接。A把链接释放报文段首部的终止控制位FIN置为1&#xff0c;其序号为seq&#61;u&#xff0c;它等于前面以传送过的数据的最后一个字节的序号加1.这时候A进入了FIN-WAIT-1(终止等待1)状态&#xff0c;等待B的确认。

注意&#xff1a;TCP规定&#xff0c;FIN报文段即使不携带数据&#xff0c;他也消耗掉一个序号&#xff01;&#xff01;



  1. B 收到链接释放报文段后即发出确认&#xff0c;确认号是ack &#61; u &#43; 1&#xff0c;而这个报文段自己的序号是v&#xff0c;等于B前面已传送过的数据的最后一个字节的序号加1.然后B就进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程&#xff0c;因而从A到B这个方向的链接就释放了&#xff0c;这时的TCP链接处于半关闭状态&#xff0c;即A已经没有数据要发送了&#xff0c;但B若发送数据&#xff0c;A仍要接收&#xff0c;也就是说&#xff0c;从B到A这个方向的连接并未关闭。这个状态可能要维持一段时间。
  2. A收到来自B的确认后&#xff0c;就进入了FIN-WAIT-2(终止等待2)状态满等待B发出的连接释放报文段。若B已经没有要向A发送的数据&#xff0c;其应用进程就通知TCP释放连接&#xff0c;这时B发出的连接释放报文段必须使FIN &#61; 1&#xff0c;现假定B的序号为w(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号ack &#61; u &#43; 1.这时B就进入LAST-ACK(最后确认)状态&#xff0c;等待A的确认。
  3. A在收到了B的链接释放报文段后&#xff0c;必须对此发出确认。在确认报文段中把ACK置1&#xff0c;确认号ack&#61;w&#43;1&#xff0c;而自己的序号是seq&#61;u&#43;1(根据TCP标准&#xff0c;前面发送过的FIN报文段要消耗一个序号)。然后进入到TIME-WAIT(时间等待)状态。注意&#xff1a; 现在TCP连接还没有还没有释放掉。必须经过时间等待计时器设置的时间2MSL后&#xff0c;A才能进入CLOSED状态。

时间MSL叫做最长报文段寿命&#xff0c;RFC793建议设在两分钟。但是在现在工程来看两分钟太长了&#xff0c;所以TCP允许不同的实现可以根据具体情况使用更小的MSL值。


在这里插入图片描述


time wait&#xff0c;过多怎么办


  1. 修改TIME_WAIT连接状态的上限值
  2. 启动快速回收机制
  3. 开启复用机制
  4. 修改短连接为长连接方式
  5. 由客户端来主动断开连接

算法&#xff1a;忘了…


三面

聊人生…


推荐阅读
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 深度学习中的Vision Transformer (ViT)详解
    本文详细介绍了深度学习中的Vision Transformer (ViT)方法。首先介绍了相关工作和ViT的基本原理,包括图像块嵌入、可学习的嵌入、位置嵌入和Transformer编码器等。接着讨论了ViT的张量维度变化、归纳偏置与混合架构、微调及更高分辨率等方面。最后给出了实验结果和相关代码的链接。本文的研究表明,对于CV任务,直接应用纯Transformer架构于图像块序列是可行的,无需依赖于卷积网络。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • Python实现Redis订阅发布功能
    本文介绍了使用Python实现Redis订阅发布功能的方法,包括创建RedisHelper类、发布消息和订阅消息的操作。通过该功能,可以实现消息的发布和订阅,并在程序中进行相应的处理。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 本文详细介绍了Python中正则表达式和re模块的使用方法。首先解释了转义符的作用,以及如何在字符串中包含特殊字符。然后介绍了re模块的功能和常用方法。通过学习本文,读者可以掌握正则表达式的基本概念和使用技巧,进一步提高Python编程能力。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
author-avatar
v敏0敏v_405_961
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有