Go面试题目

本文解析了Go语言中关于WaitGroup的使用误区、defer语句与返回值同步、以及并发锁导致的死锁问题。通过实例演示,深入探讨了关键概念并提供实用技巧。

原文地址:元旦快乐~(Go面试题目)

1、以下代码会输出什么?请简要说明。

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        time.Sleep(time.Millisecond)
        wg.Done()
        wg.Add(1)
    }()
    
    wg.Wait()
}

上述代码会发生panic恐慌,因为WaitGroup在调用Wait()之后是不能再调用Add()方法的。

2、以下代码会输出什么?请简要说明。

func main() {
    fmt.Println(doubleScore(0))    
    fmt.Println(doubleScore(20.0)) 
    fmt.Println(doubleScore(50.0)) 
}

func doubleScore(source float32) (score float32) {
    defer func() {
        if score < 1 || score >= 100 {
            score = source
        }
    }()
    
    return source * 2
}

上述代码会输出0 40 50,主要考的是defer语句与返回值相关内容,其次就是函数的return value操作它不是原子操作,而是在编译器中分解为两部分,分别是返回值赋值和return。

3、以下代码会输出什么?请简要说明。

var mu sync.RWMutex
var count int

func main() {
    go A()
    time.Sleep(2 * time.Second)
    mu.Lock()
    defer mu.Unlock()
    count++
    fmt.Println(count)
}

func A() {
    mu.RLock()
    defer mu.RUnlock()
    B()
}

func B() {
    time.Sleep(5 * time.Second)
    C()
}

func C() {
    mu.RLock()
    defer mu.RUnlock()
}

上述代码会输出fatal error,因为当写锁阻塞时,新的读锁是无法申请的(有效防止写锁饥饿),上述操作会导致死锁。

至此,本次分享就结束了,后期会慢慢补充。

以上仅为个人观点,不一定准确,能帮到各位那是最好的。

好啦,到这里本文就结束了,喜欢的话就来个三连击吧。

扫码关注公众号,获取更多优质内容。

 

### Golang 面试题目及解答 #### 基础语法与特性 在 Go 语言中,`defer`语句用于安排函数的执行,在周围函数返回之前调用该函数。这通常用来确保资源释放操作被执行[^1]。 ```go func main() { defer fmt.Println("world") fmt.Println("hello") } ``` 这段代码会先打印 "hello" 后打印 "world"。 #### 并发编程 Go 的并发模型基于 goroutine 和 channel。goroutine 是轻量级线程,由 Go 运行时调度;channel 则提供了 goroutine 之间的通信机制。 ```go package main import ( "fmt" ) func sum(a, b int, ch chan int) { ch <- a + b // 将结果发送到通道 } func main() { ch := make(chan int) go sum(3, 4, ch) result := <-ch // 接收来自通道的结果 fmt.Println(result) } ``` 此程序创建了一个新的 goroutine 来计算两个整数之和,并通过通道将结果传递给主线程。 #### 错误处理 Go 中错误不是异常,而是作为最后一个返回值的一部分来表示。因此,编写健壮的应用程序意味着总是要检查这些返回值中的错误情况。 ```go file, err := os.Open("test.txt") if err != nil { log.Fatal(err) } defer file.Close() fmt.Println(file.Name(), "opened successfully.") ``` 上述例子展示了如何打开文件并验证是否有任何错误发生。如果存在错误,则终止程序运行并记录日志消息。 #### 数据结构 关于切片(slice),这是动态数组的一种实现方式,支持长度可变的操作。可以通过内置函数 `make()` 或者直接声明初始化一个 slice。 ```go s := []int{2, 3, 5, 7, 11, 13} printSlice(s) // append works on nil slices. var s2 []int printSlice(s2) s = append(s, 17, 19, 23, 29) printSlice(s) s2 = append(s2, 2) printSlice(s2) ``` 这里定义了一些简单的 slice 操作实例,包括向现有 slice 添加新元素以及展示其内容的方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值