go 遇见的问题

1. 在学slice的时候有个地方感到困惑:

unc main() {
    s := []int{2, 3, 5, 7, 11, 13}
    printSlice(s)

    // Slice the slice to give it zero length.
    s = s[:0]
    printSlice(s)

    // Extend its length.
    s = s[:4]
    printSlice(s)
    
    s = s[:2]
    printSlice(s)
    
    s = s[:5]
    printSlice(s)

    // Drop its first two values.
    s = s[2:]
    printSlice(s)
    
    s = s[:5]
    printSlice(s)
}

func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
--------
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=6 [2 3]
len=5 cap=6 [2 3 5 7 11]
len=3 cap=4 [5 7 11]
panic: runtime error: slice bounds out of range [:5] with capacity 4
 

从运行结果看,当end indices小于最大索引5时(s = s[:0]),slice的capacity不变还是6,而且还可以加长,(s = s[:4]),但当start indices大于0时,(s = s[2:]),slice的capacity就变小了。

在https://go.dev/blog/slices-intro,这里介绍了slice的内部机制。

--------------->

Slice internals

A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment).

Our variable s, created earlier by make([]byte, 5), is structured like this:

The length is the number of elements referred to by the slice. The capacity is the number of elements in the underlying array (beginning at the element referred to by the slice pointer). The distinction between length and capacity will be made clear as we walk through the next few examples.

As we slice s, observe the changes in the slice data structure and their relation to the underlying array:

s = s[2:4]

Slicing does not copy the slice’s data. It creates a new slice value that points to the original array. This makes slice operations as efficient as manipulating array indices. Therefore, modifying the elements (not the slice itself) of a re-slice modifies the elements of the original slice:

d := []byte{'r', 'o', 'a', 'd'}
e := d[2:]
// e == []byte{'a', 'd'}
e[1] = 'm'
// e == []byte{'a', 'm'}
// d == []byte{'r', 'o', 'a', 'm'}

Earlier we sliced s to a length shorter than its capacity. We can grow s to its capacity by slicing it again:

s = s[:cap(s)]

A slice cannot be grown beyond its capacity. Attempting to do so will cause a runtime panic, just as when indexing outside the bounds of a slice or array. Similarly, slices cannot be re-sliced below zero to access earlier elements in the array.

------------------------->

从官方的文章可以看到这个原因是因为当start indices大于0时(s = s[2:4]),指针指向了index=2这个位置,The capacity is the number of elements in the underlying array (beginning at the element referred to by the slice pointer),所以capacity变小了。而上例当end indices小于最大索引5时,因为指针位置没变,所以capacity不变。

 

2. package的init()

在调用一个测试时发现会总是调另外一个package下面的init()方法

import (
    "common/log"
    card2 "common/serverComm/card"
    "subGame/zjh/card"
    "subGame/zjh/msg"
    "testing"
)

func TestCalculateCardsScore(t *testing.T) {
    cardInfo :=&msg.TableCardInfo{}
    c1 := &card2.Card{Num:2,Color:1}
    c2 := &card2.Card{Num:1,Color:1}
    c3 := &card2.Card{Num:1,Color:2}
    cards := []*card2.Card{c1,c2,c3}
    cardInfo.Cards = cards
    card.CalculateCardsScore(cardInfo)
    log.Info("card typs is %v",cardInfo.CardType)
    log.Info("card1.num=%v,card1.color%v",cards[0].Num,cards[0].Color)
    log.Info("card2.num=%v,card2.color%v",cards[1].Num,cards[1].Color)
    log.Info("card3.num=%v,card3.color%v",cards[2].Num,cards[2].Color)


}

这个的包是room->internal->logic

但是会调到conf->下面的json.go的init方法,测过就算不import任何包,init方法总是会被调到。conf和room属于同一个module。

 

3.  在做项目的时候发现一段timer.AfterFunc会重复执行。日志如下

2022-03-01 14:13:05.745 [ Info] [gameManager.go:392] 切换牌权日志:{3 20 1 0 0 false 0.1 0 0 0}
2022-03-01 14:13:05.745 [ Info] [robotManager.go:611] onRobotOperate start
2022-03-01 14:13:05.745 [ Info] [gameManager.go:403] 开始等待倒计时操作:6000,3,107
2022-03-01 14:13:05.745 [ Info] [gameManager.go:729] OnBet Unlock
2022-03-01 14:13:07.780 [ Info] [handler.go:99] OnHeartReq
2022-03-01 14:13:09.154 [ Info] [robotManager.go:673] -------- RobotOperate executing -------
2022-03-01 14:13:09.154 [ Info] [gameManager.go:652] OnBet lock
2022-03-01 14:13:09.154 [ Info] [gameManager.go:653] betType is 1
2022-03-01 14:13:09.154 [ Info] [gameManager.go:699] 下注:6000,3
2022-03-01 14:13:09.154 [ Info] [gameManager.go:1264] 停止操作倒计时:6000
userInfo: 2
2022-03-01 14:13:09.154 [ Info] [gameManager.go:2653] chair = 3
2022-03-01 14:13:09.154 [ Info] [gameManager.go:2654] isRobot is true
2022-03-01 14:13:09.154 [ Info] [gameManager.go:2656] g.HandsCard[chair] is {"Cards":[{"Color":3,"Num":1,"Cardid":0},{"Color":2,"Num":12,"Cardid":0},{"Color":3,"Num":9,"Cardid":0}],"Score":"14.18","CardType":0,"ChairID":3,"UserId":107},
2022-03-01 14:13:09.154 [ Info] [gameManager.go:2657] operate is Blind Bet +0.1,
2022-03-01 14:13:09.164 [ Info] [gameManager.go:377] 牌权切换:6000,3,2,true,%!!(MISSING)v(MISSING)
userInfo: 2
2022-03-01 14:13:09.164 [ Info] [gameManager.go:392] 切换牌权日志:{2 20 1 0 0 false 0.1 0 0 0}
2022-03-01 14:13:09.164 [ Info] [robotManager.go:611] onRobotOperate start
2022-03-01 14:13:09.164 [ Info] [gameManager.go:403] 开始等待倒计时操作:6000,2,7
2022-03-01 14:13:09.164 [ Info] [gameManager.go:729] OnBet Unlock
2022-03-01 14:13:09.164 [ Info] [robotManager.go:1014] onRobotOperate end
2022-03-01 14:13:09.164 [ Info] [robotManager.go:673] -------- RobotOperate executing -------
2022-03-01 14:13:09.164 [ Info] [gameManager.go:652] OnBet lock
2022-03-01 14:13:09.164 [ Info] [gameManager.go:653] betType is 1
2022-03-01 14:13:09.164 [Error] [gameManager.go:669] Card right Error!
2022-03-01 14:13:09.164 [ Info] [robotManager.go:1014] onRobotOperate end
2022-03-01 14:13:11.436 [ Info] [gameManager.go:2333] tp robot matching logic begin,tableId=6000,isRobot=%!!(MISSING)v(MISSING)
2022-03-01 14:13:11.436 [ Info] [roomManager.go:213] FindEmptyChart error%!!(MISSING)(EXTRA *errors.errorString=no emtpy chart)
2022-03-01 14:13:11.765 [ Info] [robotManager.go:673] -------- RobotOperate executing -------
2022-03-01 14:13:11.765 [ Info] [gameManager.go:652] OnBet lock
2022-03-01 14:13:11.765 [ Info] [gameManager.go:653] betType is 1
2022-03-01 14:13:11.765 [ Info] [gameManager.go:699] 下注:6000,2
2022-03-01 14:13:11.765 [ Info] [gameManager.go:1264] 停止操作倒计时:6000
userInfo: 2

可以看到RobotOperate executing这段在定时4s后执行的在几个毫秒内重复执行

代码:

    canCompare := pGame.canCompare(cardRight) == 1
    pGame.stopRobotOperateTimer()
    pGame.RobotOperateTimer = time.AfterFunc(time.Millisecond*time.Duration(operateTime), func() {
        log.Info("-------- RobotOperate executing -------")
        //当前桌子空位<=1,该桌牌型分数最小机器人弃牌退出/直接回大厅退出
        if robotsCount > 0 {
            emptyChaireCount := pGame.TableFrame.CalculateEmptyChairCount()
            if emptyChaireCount == 0 {
                chairId, _ := getMinScoreRobotChair(pGame)
                //当前牌权机器人牌分最小,弃牌退出

 

func (g *GameManager) stopRobotOperateTimer() {
    if g.RobotOperateTimer != nil {
        //log.Info("stopOperateTimer2")
        //g.RobotOperateTimer.Reset(0 * time.Second)
        g.RobotOperateTimer.Stop()
        g.RobotOperateTimer = nil
    }
}

原因是pGame.stopRobotOperateTimer()这个方法原来的写法是g.RobotOperateTimer.Reset(0 * time.Second),调这个的时候会重复执行,改成Stop()就好了

 

posted @ 2021-10-29 22:20  zjhgx  阅读(39)  评论(0编辑  收藏  举报