四、面向对象
如何理解面向对象编程?
- 1.万物皆对象,任何事物 在代码中都可以用 对象 表达出来。
- 2.对象包含自己的 属性 和 行为。编程的过程:就是创建对象的描述,设计对象的行为。
- 3.面向对象编程三大特性 -- 封装、继承、多态。点击查看
Go语言里如何实现面向对象 (实现三大特性)?
structinterface
封装:
type Animal struct {
name string
}
func (p *Animal) SetName(name string) {
p.name = name
}
func (p *Animal) GetName() string {
return p.name
}
复制代码
继承:
type Animal struct {
Name string
}
type Cat struct {
Animal
FeatureA string
}
type Dog struct {
Animal
FeatureB string
}
复制代码
多态:
type AnimalSounder interface {
say()
}
func (c *Cat) say() {
fmt.Println("喵喵喵~")
}
func (c *Dog) say() {
fmt.Println("汪汪汪·~")
}
// 攻击函数,传入 Animal 对象
func attack(animalSounder AnimalSounder) {
animalSounder.say()
}
func main() {
c1 := Cat{}
d1 := Dog{}
attack(c1)
attack(d1)
}
复制代码
简述一下Go语言里的 interface?
Interface
简述一下 空接口 (null interface)?空接口的应用?
空接口 (null interface)interface{}
Go语言中 2 个 interface 可以比较吗 ?
==!=
Go语言中 2 个 stuct 可以比较吗 ?
reflect.DeepEqual
说几个常用的设计模式?
简单说说 静态代理 和 动态代理 (简单说说 代理模式)?
代理类委托类静态代理动态代理
// 动态代理的关键: 位于代理类与委托类之间的中介类,这个中介类被要求实现 InvocationHandler接口
/**
当我们调用代理类对象的方法时,这个 "调用" 会转送到invoke方法中,
代理类对象作为 proxy参数 传入,参数 method 标识了我们具体调用的是代理类的哪个方法,args为这个 方法的参数。
*/
/**
这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,
这样我们可以在 invoke方法 中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)。
*/
// 调用处理程序
public interface InvocationHandler {
Object invoke(Object proxy, Method method, Object
}
// 中介类
public class DynamicProxy implements InvocationHandler {
//obj为委托类对象;
private Object obj;
public DynamicProxy(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = method.invoke(obj, args);
System.out.println("after"); return result;
}
}
复制代码
五、语言类库
Go语言中 Context 定义?
Context
简单说一下 Go语言 的 unsafe包?
unsafe包unsafe.Pointer
简单说一下 reflect.DeepEqual函数?
==reflectDeepEqual
反射 的作用?
TypeOfValueOfValueOfInterface()
六、并发编程(协程)
线程 和 进程 的区别?
进程线程
协程 (goroutine) 和 线程的区别?
线程协程
说说 Go语言 中的 协程 (goroutine)?
go关键字channel
谈谈你对 CSP并发模型 的理解?
CSP并发模型 的核心: 不要以 共享内存 的方式来 通信,而是要通过 通信 来 共享内存。
- 【什么是: 以 共享内存 的方式来 通信】: 构建一个 全局共享变量,通过 加锁机制 来保证 共享数据 在 并发环境 下的 线程安全,从而实现并发线程间的 通信。
- 【什么是: 通过 通信 来 共享内存】: 协程 之间通过 channel 进行通信, 协程只需要关注两件事情: 1.往channel中发送数据, 2.从channel中取出数据, 而不用关注另一个 并发实体,这使得并发实体间实现了 完全解耦,这两个并发原语之间没有 从属关系。
浅谈一下GMP (Go语言的调度模型)?
Goroutine(G)PMGMPP
Select 有什么作用?
Go语言 中的 select 的作用就是: 监听 针对 channel 的 读写操作。
浅谈一下 Select 机制?
点击查看 --- 查看案例
select{}
说说 channel 特性?
panic
channel 使用场景?
channel协程goroutine通信定时任务超时处理控制并发数任务队列、结果队列
缓冲 channel 和 无缓冲 channel 的区别?
无缓冲 channel<-chch<-缓冲 channel
nil channel有什么用?
nil channelpanic
channel 如何关闭?
close(ch1)
什么情况会导致 Goroutine 发生阻塞?
- 对一个 nil channel 进行 读写操作,造成永远阻塞。
- 死锁。多个协程由于竞争资源导致死锁。
如果 Goroutine 一直占用资源怎么办,GMP模型怎么处理这个问题?
如果有一个 Goroutine 一直占用资源的话,GMP模型 会从 正常模式 转为 饥饿模式,强制让前面的 Goroutine 去分配使用。
如何优雅的关闭一个 Goroutine?
channelContextLOOP + ctx.Done()
谈一下 Go语言中的 WaitGroup?
WaitGroup
Go语言中有哪几种锁?
MutexRWMutex
说说go语言的 同步锁 (锁)?
MutexRWMutexRWMutex
谈谈 Go语言 中的 原子操作,和加锁实现有什么区别?
atomic
说说你对 Go语言 中 panic 和 recover 的理解?
panicrecoverrecoverdeferpanicdefer
defer语句 的常见使用场景?
通信连接数据库连接文件资源
defer、return 的执行顺序?
defer
defer 能否修改 return 的值?
- 匿名返回值 (int): 不会影响返回值。
- 命名返回值 (res int) : 会影响返回值。
七、IO
八、通信/网络
八、内存分配、垃圾回收
简述一下 Go语言中的 栈内存 (也称调用栈)?
栈内存函数函数goroutine
简述一下 Go语言中的 堆内存?
内存管理堆内存堆内存分配器垃圾收集器
简述 堆 和 栈 有什么区别?
性能
- 栈内存 性能好:栈内存 的 分配 与 释放 非常高效的。
- 堆内存 性能差:堆内存回收 需要通过 标记清除阶段,例如 三色标记法。
加锁
- 栈 不需要加锁:栈内存 是每个 goroutine 独有的,所以 栈内存 中的 操作 不需要加锁。
- 堆 有时需要加锁:堆内存 有时需要 加锁 防止 多线程冲突。
什么是逃逸分析?
逃逸分析
逃逸分析的原则 (了解原则后, 尽量写分配到 栈 上的代码)?
- Go的 逃逸分析 是在 编译期 完成的:编译期 无法确定的参数类型 必定放到堆中;
- 如果变量在 函数外部存在引用,则必定放在 堆 中, 否则放到 栈 中
- 如果变量 占用内存较大 时,则优先放到 堆 中;
简述垃圾回收(GC)方法-三色标记法?
- 第一步: 新创建的对象, 默认标记为 白色。
- 第二步: GC回收 开始, 从 根节点 遍历所有对象,把遍历到的对象从 白色集合 放入 灰色集合。
- 第三步: 遍历 灰色集合,将 灰色对象 引用的对象从白色集合放入 灰色集合,之后将此 灰色对象 放入 黑色集合。
- 第四步: 重复第三步, 直到灰色集合中无任何对象。
- 第五步: 回收所有的 白色标记 的对象. 也就是回收垃圾。
三色标记法的优缺点?
STW
Go语言 的 内存模型,为什么小对象多了会造成gc压力。
通常 小对象 过多会导致 GC三色法 消耗过多的 GPU。优化思路是,减少对象分配。