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}