浅谈Go与习题(二十一)

103 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情

今天来学习下Go常见的习题问题(二十一),也是面试中可能会遇到的,让我们来一起学习吧~

切片派生

观察下列代码,判断会不会引发panic?

func main() {
    x := make([]int, 2, 10)
    _ = x[6:10]
    _ = x[6:]
    _ = x[2:]
}

参考答案:会发生异常,错误信息为:panic: runtime error: slice bounds out of range [6:2],错误出现在_ = x[6:],这里涉及到切片的截取操作,通过使用截取符号[i:j],如果 j 省略,默认是原切片或者数组的长度,原切片len(x)为2,所以最后转换的形式变为[6:2],下标low大于下标high,所以会发生panic异常,如果要在子切片表达式中省略若干下标,需要遵守以下这些规则:

  • 如果下标low为零,则它可被省略
  • 如果下标high等于len(baseSlice),则它可被省略
  • 三下标形式中的下标max在任何情况下都不可被省略
//以下子切片表达式都是等价的
baseSlice[0 : len(baseSlice)]
baseSlice[: len(baseSlice)]
baseSlice[0 :]
baseSlice[:]
baseSlice[0 : len(baseSlice) : cap(baseSlice)]
baseSlice[: len(baseSlice) : cap(baseSlice)]

同步

观察下列代码,判断输出结果是否符合预期?

type data struct {
    sync.Mutex
}

func (d data) test(s string)  {
    d.Lock()
    defer d.Unlock()

    for i:=0;i<5 ;i++  {
        fmt.Println(s,i)
        time.Sleep(time.Second)
    }
}


func main() {

    var wg sync.WaitGroup
    wg.Add(2)
    var d data

    go func() {
        defer wg.Done()
        d.test("read")
    }()

    go func() {
        defer wg.Done()
        d.test("write")
    }()

    wg.Wait()
}

参考答案:输出预期不符,输出结果为:write 0 read 0 ..,这里发生了锁失效,将 Mutex 作为匿名字段时,相关的方法必须使用pointer-receiver,否则会导致锁机制失效,这里需要receiver类型改为*data后正常,也可以使用嵌入*Mutex来避免复制问题,但是需要专门的初始化,如下所示:

//指针修复法
func (d *data) test(s string) {
	d.Lock()
	defer d.Unlock()

	for i := 0; i < 5; i++ {
		fmt.Println(s, i)
		time.Sleep(time.Second)
	}
}
func main() {

	var wg sync.WaitGroup
	wg.Add(2)
        //添加mutex的初始化
	var d data = data{new(sync.Mutex)}

	go func() {
		defer wg.Done()
		d.test("read")
	}()

	go func() {
		defer wg.Done()
		d.test("write")
	}()

	wg.Wait()
}

总结

今天浅谈了Go的习题(二十一),主要介绍了GO面试中会出现的问题,接下来会继续分享其他的习题的相关知识,对于一个刚入门的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!