校招——Golang

Go Micro是一个插件式的RPC框架。它用于分布式系统开发。

Go Micro抽象出分布式系统的细节。以下是主要功能。

  • 服务发现 - 通过服务发现自动注册和名称解析
  • 负载平衡 - 基于发现构建的服务的智能客户端负载平衡
  • 同步通信 - 基于RPC的通信,支持双向流
  • 异步通信 - 为事件驱动架构内置的Pub/Sub接口
  • 消息编码 - 基于带有protobuf和json的内容类型的动态编码
  • 服务接口 - 所有功能都打包在一个简单的高级界面中,用于开发微服务

 oroutine是Go并行设计的核心。goroutine说到底其实就是协程,它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goroutine之间的内存共享。执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩。也正因为如此,可同时运行成千上万个并发任务。goroutine比thread更易用、更高效、更轻便。

一般情况下,一个普通计算机跑几十个线程就有点负载过大了,但是同样的机器却可以轻松地让成百上千个goroutine进行资源竞争。

多线程容易存在的问题:

安全性问题:在单线程系统上正常运行的代码,在多线程环境中可能会出现意料之外的结果。

活跃性问题:不正确的加锁、解锁方式可能会导致死锁or活锁问题。

性能问题:多线程并发即多个线程切换运行,线程切换会有一定的消耗并且不正确的加锁。

go struct能不能比较go defer(for defer)

如果结构体的所有成员变量都是可比较的,那么结构体就可比较
如果结构体中存在不可比较的成员变量,那么结构体就不能比较,
map和切片不能比较,所以结构体实例也不能比较
defer代码块函数会在函数return之后增加一个函数调用,通常 defer用来释放函数内部变量
defer是先进后出,压入defer中的数据不会随后续代码中更改而更改
和直接调用相比,defer的执行存在着额外的开销,例如defer会对其后需要的参数进行内存拷贝,还需要对defer结构进行压栈出栈操作。所以在循环for中定义defer可能导致大量的资源开销

select可以用于什么
break关键字可跳出select的执行。

go的调度问题

context包的用途
 ctx.Done()返回一个channel,当context关闭后,Done()返回一个被关闭的管道,关闭的管理仍然是可读的,据此goroutine可以收到关闭请求; 当context还未关闭时,Done()返回nil

主协程如何等其余协程完再操作
1.channel进行通信
2.context包 使用context中cancel函数,这种模式是主线程去通知子线程结束,select
3.sync.WaitGroup模式

slice,len,cap,共享,扩容,实现set实现消息队列(多生产者,多消费者)

大文件排序基本排序
golang实现各种排序算法
https://blog.csdn.net/mrs_len/article/details/54094390

哪些是稳定的http get跟headhttp 401,403http keep-alivehttp能不能一次连接多次请求,不等后端返回
从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间

tcp与udp区别,udp优点,适用场景,time-wait的作用,数据库如何建索引孤儿进程,僵尸进程死锁条件,如何避免

new和make区别
内建函数 new 用来分配内存,它的第一个参数是一个类型,不是一个值,它的返回值是一个指向新分配类型零值的指针
make它的定义比 new 多了一个参数,返回值也不同, make 用来为 slice,map 或 chan 类型分配内存和初始化一个对象(注意:只能用在这三种类型上),make 返回类型的引用而不是指针

slice怎么判断相等
slice相等是长度相等,每个元素也相等
1.reflect.DeepEqual
2.循环遍历

golang包管理,比如值传递

进程与线程的区别是什么,协程和线程的区别是什么
对于用户层面来说,进程就是一块运行起来的程序,线程就是程序里的一些并发的功能。对于操作系统层面来说,标准回答是“进程是资源分配的最小单位,线程是cpu调度的最小单位”。
虽然线程比进程要轻量级,但是每个线程依然占有1M左右的空间,在高并发场景下非常吃机器内存,比如构建一个http服务器,如果每来一次请求分配一个线程,请求数暴增容易OOM,而且线程切换的开销也是不可忽视的。同时,线程的创建与销毁同样是比较大的系统开销,因为是由内核来做的,解决方法也有,可以通过线程池或协程来解决。
协程是用户态的线程,比线程更加的轻量级,操作系统对其没有感知,之所以没有感知是由于协程处于线程的用户栈能感知的范围,是由用户创建的而非操作系统
如一个进程可拥有以有多个线程一样,一个线程也可以拥有多个协程。协程之于线程如同线程之于cpu,拥有自己的协程队列,每个协程拥有自己的栈空间,在协程切换时候只需要保存协程的上下文,开销要比内核态的线程切换要小很多。

golang并发模型GMP调度过程,M的大小,P的数量 (golang的协程调度机制–GMP)
golang为什么这么快?归功于go的GMP调度模型
golang为并发而生
Goroutine非常轻量,主要体现在以下方面:

上下文切换代价小,Goroutine的上下文切换只涉及到三个寄存器(PC/SP/DX)的值的修改,而线程的切换需要涉及 模式转换,以及16个寄存器的刷新。
内存占用少,线程栈空间一般是2M,而goroutine只需要2k;

golang 的 gc,groutine的底层实现
golang中的gc采用三色标记法。在讲三色标记法之前,先了解一下Mark and Sweep算法,因为Mark and Sweep算法是三个标记法的一个改进版。
Mark and Sweep算法: 停止运行程序,遍历所有被引用的变量,被引用的对象被标记为“被引用”,没有被标记的进行回收。内存单元并不会立刻回收对象,而是将其标记为“不可达”状态。直到到达某个阈值或者到达某个时间间隔后,对其进行垃圾回收。算法分为两部分:标记(Mark)和清理(Sweep)。挂起程序,对所有存活的内存单元进行扫描,标记,确定哪些可以清除。优点是解决了相互引用的缺点,不足是会停止应用程序,当内存单元变量过多时,扫描清除会花很长时间,甚至几百毫秒。
三色标记法:属于标记清除法的一个改进版。起初所有内存对象都在白色的,从根出发标记所有的对象,标记为灰色,并放入一个队列。然后再将灰色队列中的对象取出,将其引用对象标记为黑色。重复此步骤,待灰色对象队列为空时,所有白色对象既为垃圾。最后白色区域内存对象被释放,黑色区域标记为白色,等待下一阶段GC再次扫描。

三色标记法触发有两个条件:第一个是阀值,就是内存扩大一倍时启动GC。第二个是每隔两分钟GC一次。

defer的问题
1.即时的参数传递
2.调用os.Exit() 时defer不会被执行(程序会立刻终止)
3.defer与return的先后顺序
a.定义defer时传入的参数,是作为拷贝传递的。
也就是说,如果原来的变量值发生变化,不会影响传给defer的参数。
b.当发生panic时,defer会被执行,但是当调用os.Exit()方法退出程序时,defer并不会被执行。
c.return是分为两步执行的,第一步赋值给返回值,第二步真正的返回到函数外部。而defer是在第一步之后执行。所以return是包裹着defer运行的
关键字defer向函数注册退出调用,即主函数退出时,defer后的函数才被调用。defer语句的作用是不管程序是否出现异常,均在函数退出时自动执行相关代码。
在函数中,程序员经常需要创建资源(比如:数据库连接、文件句柄、锁等) ,为了在函数执行完 毕后,及时的释放资源,Go 的设计者提供 defer (延时机制)。

Go 语言参数传递是值传递还是引用传递
值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
golang中函数的参数默认为 按值传递,即在函数内部修改传入参数的值是函数外部传入值的 拷贝。
如果想要使用引用传递,需要将传入的参数设置为 指针类型

go make的底层了解吗

分布式ID了解吗
几乎所有的业务系统,都有生成一个记录标识的ID,这个记录标识往往就是数据库中的唯一主键

内存池了解吗
go提供的sync.Pool是为了
对象的复用,如果某些对象的创建比较频繁,就把他们放入Pool中缓存起来以便使用,这样重复利用内存,减少GC的压力

nsq中topic和channel有什么区别
topic:一个可供订阅的话题。
channel:属于topic的下一级,一个topic可以有多个channel。
nsq里可以只订阅某一个channel的信息。这样的话,一个topic下无关的channel就不会发过来。
如果一个channel有多个订阅者,NSQ会使用负载均衡的策略,给其它订阅者发消息

goroutine的实现原理
GMP模型

go 分布式raft协议,一致性hash协议

map并发安全、slice与array区别,map的原理
map的并发安全:并发使用map:
1.一般情况下通过读写锁sync.RWMutex实现对map的并发访问控制,将map和sync.RWMutex封装一下,可以实现对map的安全并发访问。
2.go1.9之后加入了支持并发安全的Map sync.Map。sync.Map 通过一份只使用原子操作的数据和一份冗余了只读数据的加锁数据实现一定程度上的读写分离,使得大多数读操作和更新操作是原子操作,写入新数据才加锁的方式来提升性能。
slice和array区别

一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址。长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。通过len和cap函数分别返回slice的长度和容量。


进程间通信有哪些
1.管道 --概念:在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,一般使用fork函数实现父子进程的通信。
2,消息队列–在内核中创建一队列,队列中每个元素是一个数据报,不同的进程可以通过句柄去访问这个队列。消息队列提供了⼀个从⼀个进程向另外⼀个进程发送⼀块数据的⽅法。每个数据块都被认为是有⼀个类型,接收者进程接收的数据块可以有不同的类型值
3,信号量-- 在内核中创建一个信号量集合(本质是个数组),数组的元素(信号量)都是1,使用P操作进行-1,使用V操作+1
4,共享内存
概念:将同一块物理内存一块映射到不同的进程的虚拟地址空间中,实现不同进程间对同一资源的共享。 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形
Go适合用来做什么
在这里插入图片描述

在这里插入图片描述 有 10 万个数,我们要找出最大的 1000 个数,如何做?(因为只要 1000 个数,甚至不关心它们的顺序,可以用比 nlogn 排序更快的方法,因为可以不用对 10 万个数全都排序) 面试官提示,可以用小根堆,取出前 1000 个数组成一个小根堆,后面不断跟 root 比较,小的抛弃,大的插入堆,并替换 root。

inux命令

查看cpu负载,内存占用: top
如何发送信号给一个进程:kill命令
golang slice切片(动态数组)

数组是类型相同的元素的集合

var variable_name [SIZE] variable_type 声明数组 var a [3]int 或者 a := [3]int{12, 78, 50}

golang 提供简单的遍历数组的方式 for i, v := range a

切片(slice)是建立在数组之上,切片并不存储任何元素而只是对现有数组的引用。切片本身不包含任何数据。它仅仅是底层数组的一个上层表示。对切片进行的任何修改都将反映在底层数组中。

通过 a[start:end] 这样的语法创建了一个从 a[start] 到 a[end -1] 的切片

内置函数 func make([]T, len, cap) []T 可以用来创建切片,该函数接受长度和容量作为参数

切片是动态的,可以使用内置函数 append 添加元素到切片。append(s []T, x …T) []T
golang数组与切片的区别

golang Context包作用

golang可以很方便创建协程goruntine,但是怎么控制这些协程呢?通过context包,当这个请求超时或者被终止的时候,context优雅地退出所有衍生的 goroutine,并释放资源
流程

context包函数

Done 要配合 select 语句使用
有两种方法创建根Context:context.Background() context.TODO()根 context 不会被 cancel。这两个方法只能用在最外层代码中,一般使用 Background() 方法创建根 context。
一个 Context 被 cancel,那么它的派生 context 都会收到取消信号(表现为 context.Done() 返回的 channel 收到值)。
有四种方法派生 context :

select可以用于什么
golang 的 select 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作
每个case语句里必须是一个IO操作,确切的说,应该是一个面向channel的IO操作

golang是强类型弱类型

静态类型:编译时就确定类型,java/C/C++/golang

动态类型:运行时确定 python/PHP

强类型:类型是定义好的,无法改变它的类型了,但是向C语言,虽然定义了一个short,还是可以当成char来用的,因为可以直接操作内存。

弱类型:类型之间可以自由转换
 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值