 
1、写出下面代码的输出结果,并给出原因和修正。
| 1 | func main() { | 
解答:v 的地址是不会变化的,但是 goroutine 的运行又是不可预期的,当循环执行完后goroutine才开始执行,此时v的值为c, 然后3次goroutine都会打印c。
| 1 | c | 
如果要输出 a b c得这样修正, goroutine 的时候将参数传入到匿名函数中,即使是这样,abc的顺序也是不可预期的,打印多次都是乱序。
| 1 | func main() { | 
2、下面代码有问题吗?应该如何修复?
| 1 | var stringList []string | 
slice非线程安全的,goroutine的运行不可预测,所以stringList里面是乱序且元素不一定是0~4的全集合
非线程安全的可以加锁,但是元素也不是有序的
| 1 | var stringList []string | 
3、下面这段代码有什么输出?
| 1 | type People struct{} | 
showA
showB
teacher showB
4、下面这段代码会输出什么,如何修复?
| 1 | func test0() { | 
解答:
jsonBlob:  {“name”: “Platypus”, “order”:”Monotremata”, “id”: 1}
animals: {id:0 name: order:}
反序列号的时候对应的结构体需要是导出的,将结构体改为导出字段即可
| 1 | func test0() { | 
5、输出的结果为?为什么?
func Testlface() {
    s := make([]int, 5)
    s = append(s, 1, 2, 3)
    fmt.Println(s)
    var (
        data  *int
        eface interface{}
    )
    eface = data
    fmt.Println(data == nil)
    fmt.Println(eface == nil)
}
[0 0 0 0 0 1 2 3]
true
falseeface 不是 nil 的原因是它是一个接口类型,被赋值为 *int 类型的指针。即使指针 data 没有被初始化并且是 nil,接口 eface 仍然持有一个 *int 类型的值,因此不是 nil。当一个接口被赋值为特定类型的值时,它包含两个组件 - 值的类型和值的指针。在这种情况下,eface 持有一个 *int 类型的值,这意味着它包含一个指向整数值的指针(即使该指针当前为 nil)
6、下面代码是否有错?为什么?
| 1 | func Testlface2() { | 
不能将slice转为接口类型切片,应该直接转为接口类型就可以了,修改为
| 1 | func Testlface2() { | 
7、下面的代码会有什么问题?
| 1 | func main() { | 
读取关闭的chan会返回空值,所以输出0~9后会不断的输出0
8、下面代码会怎么样?为什么?
| 1 | func main() { | 
这段代码会导致运行时错误,因为在 go 协程中创建的切片 s 没有被初始化,所以它的长度为 0,无法访问或设置其索引为 0 的元素。这会导致 panic,并且程序会崩溃。
会输出 panic: runtime error: index out of range [0] with length 0
9、假设有100个[]int切片,现在要计算这些切片元素的总和,并且要求最大只有10个goroutine同时在计算。
| 1 | func main() { | 
10、给出LRU-Cache的伪代码(数据结构及大致思路)。cache支持协程安全,支持get、put操作,每次get、put更新key的存活时间。
以下是一个简单的LRU-Cache的伪代码,该cache支持协程安全,支持get、put操作,每次get、put更新key的存活时间。
数据结构:
- 双向链表:用于维护key的访问顺序,最近访问的key放在链表头部,最少访问的key放在链表尾部。
- 哈希表:用于快速查找key对应的节点。
伪代码:
| 1 | type Node struct { | 
在这个伪代码中,我们首先定义了一个 Node 结构体,用于表示链表中的节点。每个节点包含一个 key、一个 value、一个 prev 指针、一个 next 指针和一个 time 时间戳,用于表示该节点的存活时间。
然后,我们定义了一个 LRUCache 结构体,用于表示LRU-Cache。每个 LRUCache 包含一个容量 capacity、一个大小 size、一个链表头部 head、一个链表尾部 tail、一个哈希表 cache 和一个互斥锁 mutex,用于协程安全。
在 LRUCache 中,我们定义了 NewLRUCache、Get、Put、addToHead、removeNode、moveToHead 和 removeTail 等方法。其中,NewLRUCache方法用于创建一个新的 LRUCache` 实例,需要传入一个容量参数。
Get 方法用于获取指定key对应的value。首先,我们使用互斥锁进行协程安全保护。然后,我们从哈希表中查找key对应的节点,如果找到了节点,则更新节点的存活时间,并将节点移动到链表头部,表示该节点是最近访问的节点。最后,返回节点的value和true。如果没有找到节点,则返回0和false。
Put 方法用于插入一个新的key-value对或更新一个已有的key的value。首先,我们使用互斥锁进行协程安全保护。然后,我们从哈希表中查找key对应的节点,如果找到了节点,则更新节点的存活时间和value,并将节点移动到链表头部,表示该节点是最近访问的节点。如果没有找到节点,则创建一个新的节点,并将节点加入到链表头部。如果插入新节点后超过了容量,则删除链表尾部的节点。最后,更新哈希表和大小。
addToHead 方法用于将指定节点插入到链表头部。
removeNode 方法用于从链表中删除指定节点。
moveToHead 方法用于将指定节点移动到链表头部。
removeTail 方法用于删除链表尾部的节点,并返回被删除的节点。
在这个伪代码中,我们使用了一个双向链表和一个哈希表来实现LRU-Cache。在链表中,最近访问的节点放在链表头部,最少访问的节点放在链表尾部。在哈希表中,key对应的value是链表中的节点。使用双向链表和哈希表可以实现快速的访问和插入/删除操作,时间复杂度为O(1)。同时,使用互斥锁可以保证并发访问的安全性。
 
        