Golang面试题(一)

题目

1 写出以下逻辑,要求每秒钟调用一次proc并保证程序不退出

package main

func main() {
    go func() {
        // 1 在这里需要你写算法
        // 2 要求每秒钟调用一次proc函数
        // 3 要求程序不能退出
    }()

    select {}
}

func proc() {
    panic("ok")
}

2 下面代码写法有什么问题?

package main
import (
    "fmt"
)
type Stduent struct {
    Age int
}
func main() {
    kv := map[string]Stduent{"menglu": {Age: 21}}
    kv["menglu"].Age = 22
    s := []Stduent{{Age: 21}}
    s[0].Age = 22
    fmt.Println(kv, s)
}

3.写出以下打印结果,并解释下为什么这么打印的。

package main
import (
    "fmt"
)
func main() {
    str1 := []string{"a", "b", "c"}
    str2 := str1[1:]
    str2[1] = "new"
    fmt.Println(str1)
    str2 = append(str2, "z", "x", "y")
    fmt.Println(str1)
}

4.为sync.WaitGroup中Wait函数支持WaitTimeout功能( )

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    wg := sync.WaitGroup{}
    c := make(chan struct{})
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(num int, close <-chan struct{}) {
            defer wg.Done()
            <-close
            fmt.Println(num)
        }(i, c)
    }

    if WaitTimeout(&wg, time.Second*5) {
        close(c)
        fmt.Println("timeout exit")
    }
    time.Sleep(time.Second * 10)
}

func WaitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
    // 要求手写代码
    // 要求sync.WaitGroup支持timeout功能
    // 如果timeout到了超时时间返回true
    // 如果WaitGroup自然结束返回false
}

答案

1.写出以下逻辑,要求每秒钟调用一次proc并保证程序不退出

func main() {
	go func() {
		for {
			time.Sleep(time.Second)
			func() {
				defer func() {
					if err := recover(); err != nil {
						fmt.Println("捕获异常:", err)
					}
				}()
				proc()
			}()
		}
	}()

	select {}
}

func proc() {
	panic("ok")
}

2 kv["menglu"].Age = 22会报错,不能修改Age,cannot assign to struct field kv["menglu"].Age in map
map中struct不能修改值的原因是struct类型是值类型。考虑以下情况:

stu1 := Student{Name:"Mike", Age: 21}
kv := map[string]Student{"Mike": stu1}

我们定义了一个map,这个map的主要作用就是可以通过人的名字来直接取得该名字对应的个人信息。现在我们要修改stu1的年龄,但是由于struct是值类型,也就是在赋值给kv的时候进行了值拷贝,存在kv中的只是stu1的一份拷贝,所以通过修改kv中的对象,并不能达到修改stu1的目的。
题外话:关于struct值传递有另外一个坑就是,对于声明了指针接收者方法的结构体,是不能直接赋值给接口的。

3.基础题目:搞明白切片是不是值类型而是引用类型就好。所以str2str1底层数据指向的是同一个地方。但是当str2使用append进行插入操作的时候,如果底层数组的长度不够会进行扩容,也就是重新申请一块新的长度为原底层数组长度两倍的新数组,将原底层数组的数据复制到新的数组,在新的数组插入新的数据,然后将str2的指针指向新的数组。而str1还是指向原先的底层数组,所以str1保持不变。

func WaitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
	wgChan := make(chan struct{})
	go func() {
		wg.Wait()
		wgChan <- struct{}{}
	}()
	select {
	case <-wgChan:
		return false
	case <- time.After(2 * time.Second):
		return true
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章