Q : 2  interface 可以比较吗 

不能直接比较,只有同时为nil且类型相同才可以比较。

可能不等。interface在运行时绑定值,只有值为nil接口值才为nil,但是与指针的nil不相等。举个例子:

    var p *int = nil
    var i interface{} = nil if(p == i){
    fmt.Println("Equal")
}

两者并不相同。总结:两个nil只有在类型相同时才相等

标记开始时,先将所有对象加入白色集合(需要STW)。首先将根对象标记为灰色,然后将一个对象从灰色集合取出,遍历其子对象,放入灰色集合。同时将取出的对象放入黑色集合,直到灰色集合为空。  最后的白色集合对象就是需要清理的对象。

这种方法有一个缺陷,如果对象的引用被用户修改了,那么之前的标记就无效了。因此Go采用了写屏障 技术,当对象新增或者更新会将其着色为灰色。

一次完整的GC分为四个阶段:

  1. 准备标记(需要STW),开启写屏障。
  2. 开始标记
  3. 标记结束(STW),关闭写屏障
  4. 清理(并发)

基于插入写屏障和删除写屏障在结束时需要STW来重新扫描栈,带来性能瓶颈。混合写屏障分为以下四步:

  1. GC开始时,将栈上的全部对象标记为黑色(不需要二次扫描,无需STW);
  2. GC期间,任何栈上创建的新对象均为黑色
  3. 被删除引用的对象标记为灰色
  4. 被添加引用的对象标记为灰色

总而言之就是确保黑色对象不能引用白色对象,这个改进直接使得GC时间从 2s降低到2us。

这一点和C++不同,在Go里面返回局部变量的指针是安全的。因为Go会进行逃逸分析,如果发现局部变量的作用域超过该函数则会把指针分配到堆区,避免内存泄漏。

rune是int32的别名,用来区分字符值和整数值。比如utf-8汉字占3个字节,按照一般方法遍历汉字字符串得到的是乱码,这个时候要将字符串转换为rune:

    sample := " 我 爱 GO" 
    runeSamp := []rune(sample)
 runeSamp[0] = '你'

fmt.Println(string(runeSamp))

Q : 如何判断 map 中是否包含某个 key 


var sample map[int]int
if _, ok := sample[10];ok{

}else{

}

int8占1个字节,int16占2个字节,int32占4个字节,int64占8个字节。

对于无缓冲区channel,一直是阻塞的;有缓冲区channel只有缓冲区满之后才会阻塞。     有缓冲的channel是异步的,而无缓冲channel是同步的。