程序上产生分页

时间:2017-02-07 15:34:49

标签: html go pagination

我正在尝试用Go创建分页,但我有点困惑。这是我第一次创建分页,因为我还在使用PHP时使用laravel的帮助类。

我尝试过这样的事情:

var totalPages = int(math.Ceil(float64(totalRecords) / float64(recordsPerPage)))

for i := 0; i < totalPages; i++ {
    pages[i] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, i+1, limit, i+1)
}

这显示了所有页面,我想创建一些看起来像的东西:

< 1 2 ... 20 24 25 26 27 ... 200 201 >

25是当前页面,201是最后一页。

我还尝试了类似下面的内容但在某些情况下很古怪,比如页面是接近开头还是结尾:

// pages[0] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, 1, limit, 1)
// pages[1] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, 2, limit, 2)
// pages[2] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, 3, limit, 3)
// pages[3] = `<li><a class="more">&hellip;</a></li>`
// pages[4] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, page, limit, page)
// pages[5] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, page+1, limit, page+1)
// pages[6] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, page+2, limit, page+2)
// pages[7] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, page+3, limit, page+3)
// pages[8] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, page+4, limit, page+4)
// pages[9] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, page+5, limit, page+5)
// pages[10] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, page+6, limit, page+6)
// pages[11] = `<li><a class="more">&hellip;</a></li>`
// pages[12] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, totalPages-1, limit, totalPages-1)
// pages[13] = fmt.Sprintf(`<li><a href="?page=%d&limit=%d">%d</a></li>`, totalPages, limit, totalPages)

所以问题是,我该如何实现这一目标?有图书馆吗?什么是正确的逻辑?

2 个答案:

答案 0 :(得分:2)

打破你的问题你会得到它。

你想要的是计算邻居。

package main

import (
    "fmt"
)

func main() {
    pages(8, 2, 13)
}

func pages(n int, around int, count int) {
    first := n - around
    if first < 1 {
        first = 1
    }
    last := n + around
    if last > count {
        last = count
    }

    if first > 1 {
        for i := 1; i <= 2 && i < first; i++ {
            fmt.Println(i)
        }
        if 3 < first {
            fmt.Println("...")
        }
    }

    for i := first; i <= last; i++ {
        fmt.Println(i)
    }

    if last < count {
        if last <= count-3 {
            fmt.Println("...")
        }
        end := count - 1
        if end <= last {
            end = last + 1
        }
        for i := end; i <= count; i++ {
            fmt.Println(i)
        }

    }
}

改进:编号&#34;前缀&#34;和&#34;后缀&#34;页面变量; - )

请参阅:https://play.golang.org/p/wOOO9GmpNV

添加了缩短版本:

package main

import (
    "fmt"
)

func main() {
    pages(10, 3, 20)
}

func pages(n int, around int, count int) {
    var i int
    for i = 1; i <= 2 && i<=count; i++ {
        fmt.Println(i)
    }

    if i < n-around {
        fmt.Println("...")
        i = n - around
    }

    for ; i <= n+around && i<=count; i++ {
        fmt.Println(i)
    }

    if i < count-1 {
        fmt.Println("...")
        i = count - 1
    }

    for ; i <= count; i++ {
        fmt.Println(i)
    }
}

我们可以通过提供回调轻松包装。请注意,频道非常慢。

package main

import (
    "fmt"
)

func main() {
    pages(10, 3, 20, func(i int) {
        if i < 0 {
            fmt.Println("...")
            return
        }
        fmt.Println(i)
    })
}

func pages(n int, around int, count int, render func(int)) {
    var i int
    for i = 1; i <= 2 && i <= count; i++ {
        render(i)
    }

    if i < n-around {
        render(-1)
        i = n - around
    }

    for ; i <= n+around && i <= count; i++ {
        render(i)
    }

    if i < count-1 {
        render(-1)
        i = count - 1
    }

    for ; i <= count; i++ {
        render(i)
    }
}

包含所有内容的最新版本(除非错误):

package main

import (
    "fmt"
)

func main() {
    pages(10, 3, 21,4,4, func(i int) {
        if i < 0 {
            fmt.Println("...")
            return
        }
        fmt.Println(i)
    })
}

func pages(n int, around int, count int,start int, end int, render func(int)) {
    var i int
    for i = 1; i <= start && i <= count; i++ {
        render(i)
    }

    if i < n-around {
        render(-1)
        i = n - around
    }

    for ; i <= n+around && i <= count; i++ {
        render(i)
    }

    if i < count-end+1 {
        render(-1)
        i = count - end+1
    }

    for ; i <= count; i++ {
        render(i)
    }
}

请参阅:https://play.golang.org/p/KfTORNuHY_

这有多好?

  • 不要占用参数和当前页面所需的内存。
  • 每次检查都会完成一次。
  • 如果被要求记下分页,它会遵循人类的行为。 (自然逻辑)
  • 来电方只需要专注于当前页面或分隔符的渲染。
  • 快!瓶颈就是回调。

注意,如果需要一个数组,可以通过闭包来完成。与渠道相同。

答案 1 :(得分:2)

这是一个简短的实现,它返回您需要呈现的页码:

func pages(cur, max, around int) (r []int) {
    for i := cur - around; i <= cur+around; i++ {
        if i >= 1 && i <= max {
            r = append(r, i)
        }
    }
    for i := 1; i <= around; i++ {
        if i < cur-around {
            r = append(r, i)
        }
        if max+1-i > cur+around {
            r = append(r, max+1-i)
        }
    }
    sort.Ints(r)
    return
}

您需要传递当前页面(cur),最大页码(max)以及要在当前页面和列表中列出的邻居数量(around)列表的末尾

如果彼此相邻的2个页码有差异&gt; 1,您还需要在它们之间呈现...

测试它:

fmt.Println(pages(1, 1, 2))
fmt.Println(pages(1, 2, 2))
fmt.Println(pages(1, 3, 2))
fmt.Println(pages(1, 4, 2))
fmt.Println(pages(1, 5, 2))
fmt.Println(pages(1, 9, 3))
fmt.Println(pages(25, 201, 2))

ps := pages(25, 201, 3)
for i, page := range ps {
    if i > 0 && ps[i-1]+1 < page {
        fmt.Print("... ")
    }
    fmt.Print(page, " ")
}

输出(在Go Playground上尝试):

[1]
[1 2]
[1 2 3]
[1 2 3 4]
[1 2 3 4 5]
[1 2 3 4 7 8 9]
[1 2 23 24 25 26 27 200 201]
1 2 3 ... 22 23 24 25 26 27 28 ... 199 200 201 

消除sort.Ints()

sort.Ints()的目的是按递增顺序返回页码。这是必需的,因为第二个循环不按顺序添加数字。

如果我们可以更改它以便第二个循环保持顺序,则不再需要排序。

第二个循环负责从列表的末尾添加页码(开头和结尾)。追加结尾很好(只需要向上),我们将开头添加到另一个切片,其余部分将附加到其中。

这是:

func pages(cur, max, around int) (r []int) {
    for i := cur - around; i <= cur+around; i++ {
        if i >= 1 && i <= max {
            r = append(r, i)
        }
    }
    r2 := make([]int, 0, len(r)+4)
    for i := 1; i <= around; i++ {
        if i < cur-around {
            r2 = append(r2, i)
        }
        if max-around+i > cur+around {
            r = append(r, max-around+i)
        }
    }
    return append(r2, r...)
}

测试和输出是一样的。请在Go Playground上尝试此变体。

同时指定末尾的页数

如果你想在末尾有不同数量的页面,你可以添加1个额外的参数并使用它添加0复杂度:

func pages(cur, max, around, edge int) (r []int) {
    for i := cur - around; i <= cur+around; i++ {
        if i >= 1 && i <= max {
            r = append(r, i)
        }
    }
    r2 := make([]int, 0, len(r)+2*edge)
    for i := 1; i <= edge; i++ {
        if i < cur-around {
            r2 = append(r2, i)
        }
        if max-around+i > cur+around {
            r = append(r, max-around+i)
        }
    }
    return append(r2, r...)
}

Go Playground上尝试此变体。