为什么Go的结果相同?

When i review a Golang project, i found some code like this, now is Unix timestap. Call this function once every second:

//main.go
func PrevSlot(now int64) int64 {
    // now = time.Now().Unix()
    var blockInterval = int64(10)

    result := int64((now-1)/blockInterval) * blockInterval // why result is same ?
    plog.Println("PrevSlot:", int64(result), int64((now-1)/blockInterval), now)
    return result
}


func main() {
    ticker := time.NewTicker(1 * time.Second)
    for {
        <-ticker.C

        now := time.Now().Unix()
        PrevSlot(now)
    }

}

Output:

2019-01-16 10:58:31.668597 I | dpos.go: PrevSlot: 1547607510 154760751 1547607511
2019-01-16 10:58:32.668649 I | dpos.go: PrevSlot: 1547607510 154760751 1547607512
2019-01-16 10:58:33.668568 I | dpos.go: PrevSlot: 1547607510 154760751 1547607513
2019-01-16 10:58:34.668572 I | dpos.go: PrevSlot: 1547607510 154760751 1547607514
2019-01-16 10:58:35.668547 I | dpos.go: PrevSlot: 1547607510 154760751 1547607515

The result is same. Why is this, what is the principle?

Actually,

int64((now - 1)/blockInterval * blockInterval

does not return the same result all the time. You will notice it changing every 10 seconds.

This is caused by integer division in Go. If you apply integer division to any two numbers, then the fractional part of the result (remainder) is dropped. For example, int(12 / 10) = 1. In your specific case - dividing by ten, the code will drop the remainders from 1 until 9, and only increment the value when you get to the next 10.

If you'd like to increase the precision of your operations, then you can force floating point division like so float64(12)/float64(10).

Your problem is here:

result := int64((now-1)/blockInterval) * blockInterval

time.Now().Unix() returns the current Unix time in seconds. So, for consecutive iterations, time.Now().Unix() would be:

1257894001
1257894002
1257894003

But in your function, you are subtracting 1, then dividing by ten, so each of the above becomes the following because the fractional portion is dropped.

125789400
125789400
125789400

Then when you multiply by blockInterval (10), they all become:

1257894000
1257894000
1257894000

So, result ends up being the same. If you let it run for longer than ten seconds, you'll see result change after 10 seconds:

https://play.golang.org/p/LgPtHwjwlC1