go基础面试题

超时控制带来的内存泄漏

利用缓存chan,来解决,不然函数停止,select 无法再执行接收数据。job中的协程就泄漏了。

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"runtime"
 7	"time"
 8)
 9
10func job(ctx context.Context, num int) {
11	ctx, cancel := context.WithTimeout(ctx, time.Second)
12	defer cancel()
13	//var chan1 = make(chan struct{}) //造成内存泄漏
14	var chan1 = make(chan struct{}, 1)
15	go func() {
16		time.Sleep(time.Second * 2)
17		//干完了
18		chan1 <- struct{}{}
19		return
20	}()
21	select {
22	case <-chan1:
23		return
24	case <-ctx.Done():
25		fmt.Println("job", num, "超时了")
26		return
27	}
28}
29
30func main() {
31	ctx := context.Background()
32	for i := 0; i < 50; i++ {
33		go func(num int) {
34			job(ctx, num)
35		}(i)
36	}
37	for {
38		fmt.Println(runtime.NumGoroutine())
39		time.Sleep(time.Second)
40	}
41}

go中struct的指针方法和非指针方法有什么区别

其实go底层会帮我们传自身对象进去,作为函数的第一个参数。

指针方法是传的地址的值

非指针方法传的是 自身的值,发生值copy

 1package main
 2
 3import "fmt"
 4
 5type User struct {
 6	Name string `json:"name"`
 7}
 8
 9func (this *User) PrintName() {
10	fmt.Printf("%p\n", this)
11	fmt.Println(this.Name)
12}
13
14func (this User) SetName(name string) {
15	fmt.Println(this)
16	this.Name = name
17	fmt.Printf("%p\n", &this)
18}
19
20func (this *User) SetName2(name string) {
21	this.Name = name
22}
23
24/*
25func(main.User, string)
26func(*main.User)
27func(*main.User, string)
28{cr1}
290xc000010260
300xc000010250
31cr1
320xc000010250
33crmao
34
35*/
36func main() {
37	fmt.Printf("%T\n", User.SetName)      // func(main.User, string)
38	fmt.Printf("%T\n", (*User).PrintName) // func(*main.User)
39	fmt.Printf("%T\n", (*User).SetName2)  // func(*main.User, string)
40	var u = User{
41		Name: "cr1",
42	}
43	User.SetName(u, "crmao") //{cr1}  0xc000010260
44	(*User).PrintName(&u)    //  0xc000010250  cr1
45	(*User).SetName2(&u, "crmao")
46	(*User).PrintName(&u) // 0xc000010250  crmao
47}

指针方法和非指针方法混用造成死锁

如果一个结构体有指针方法,也有非指针方法,并且里面套了锁。

其实他里面的锁 不是同一把锁,可能会造成死锁

遍历切片放入 map值是指针中的坑

工作中没注意,真实案例。自测的时候发现的。

 1
 2func GetUserUnFinishOrder(tx *gorm.DB, tableName string, userId int64) []UserOrder {
 3    var r []UserOrder
 4    tx.Table(tableName).Where("user_id", userId).Where("status", StatusIng).Find(&r)
 5    return r
 6}
 7
 8orderList := user_order_model.GetUserUnFinishOrder(session, orderTable, userId)
 9
10
11
12
13// 这里是错误的
14for _, v := range orderList {
15    authResult.Orders[v.Id] = &v  // 这里会变成所有都是最后一条
16}
17
18
19// 	Orders map[int32]*user_order_model.UserOrder 
20// 正确写法
21for _, v := range orderList {
22    tmp := v
23    authResult.Orders[v.Id] = &tmp
24}