Golang中如何获取带查询参数的当前URL

Golang中如何获取带查询参数的当前URL 你好

我想获取包含查询字符串的当前URL。

原因是这样的……

我想在Golang前端实现分页功能。我的思路如下: 首先,我需要获取当前的URL。然后解析它。将分页参数添加到URL中,再将其发送到模板。

如何获取这个URL呢? 我需要从 *http.Request 构建它吗? 还是说它已经可以直接获取了?

21 回复

用于身份验证以及维护状态的会话

更多关于Golang中如何获取带查询参数的当前URL的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


为什么需要会话?目的是什么?

func main() {
    fmt.Println("hello world")
}

如果你实现了无限滚动功能,请在此处发布。这会很有帮助。

现在我明白你为什么要问是哪种会话了。 看来这将是一项大工程。

HTTP是无状态的。我们不知道在页面刷新时哪个用户已经登录。为了追踪用户及其角色。

是的。我需要根据登录用户进行授权和控制菜单。 有些用户只能查看,而有些用户可以发帖。

对——这就是我提到的客户端方面。你完全可以在服务器端渲染,然后返回一段HTML给客户端,并将其附加到DOM中的一个元素上。

既然你无法在服务器端进行滚动操作,

但我可以通过JavaScript获取“滚动值”,然后根据这个值调用Go服务器。不过正如我所说,这只是我的设想…… 🙂

非常感谢。我有一个不相关的问题,请指导我。

Go语言没有内置的会话管理器。您有什么建议?我需要自己创建一个吗?还是使用第三方库?您使用并推荐哪个库?

Mahesh_Kumar1:

Golang 没有内置的会话管理器。你有什么建议?我必须自己创建一个吗?还是使用第三方库?你使用并推荐哪个库?

我们讨论的是认证形式的“会话”吗?还是数据库的连接池会话?

我想获取包含查询字符串的当前URL。

要获取查询字符串参数,可以按照以下方式操作:

// 假设 r 的类型是 *http.Request
page := r.URL.Query().Get("page")

另请参阅:

url package - net/url - Go Packages

Package url parses URLs and implements query escaping.

Sibert:

我的目标是实现服务器端的无限滚动。我不知道这是否可能,但我想尝试一下。

既然你无法在服务器端进行滚动,那么这其中必然需要一个客户端组件。客户端代码实际上并不那么复杂。在过去,由于浏览器兼容性是个噩梦(这也是我们使用jQuery之类工具的原因),所以很麻烦,但如今这已经相对简单了。搜索一下“纯JavaScript无限滚动”,你应该能找到许多可以借鉴的例子。

为了追踪用户及其角色。

用户和角色。对我来说,这意味着身份验证(你是谁?)和授权(你被允许做什么?)。

但追踪用户的话,一个 session_id 可能就足够了。我正在尝试使用 3 个服务器来实现这一点。

  1. 身份验证服务器(你是谁?)(设置 session_id 并追踪用户)
  2. REST API 服务器(与数据库通信)
  3. 网络服务器(页面等的端点)。

添加角色(授权)是另一层。因为它可能涉及不同级别的访问权限。你需要这个吗?

我在HTML表格中显示用户列表(使用Go模板和range循环)。

我想为其添加分页功能。 我只想实现“下一页”和“上一页”按钮。

URL有时已经包含查询字符串,有时是普通URL。 那么我应该添加 <a href="?page=4"> 还是 <a href="&page=4"> 呢?

我如何知道URL是否已经包含一些查询字符串? 我在想,如果我能获取当前URL,就可以解析它并添加 values.add("page", "2")

我的想法对吗?

简单来说,我只想让“下一页”按钮指向下一页,“上一页”按钮指向上一页。

想要获取包含查询字符串的当前URL。

提供更多上下文会更有帮助。以下是我尝试理解您问题的代码(一种猜测):

func endpoint(w http.ResponseWriter, r *http.Request) {
	module, mode, val := getpath(r.URL.Path)
}

// 分割URL
func getpath(path string) (module, mode, val string) {
	parts := strings.Split(path, "/")
	switch len(parts) {
	case 4:
		val = parts[3]
		fallthrough
	case 3:
		mode = parts[2]
		fallthrough
	case 2:
		module = parts[1]
	}
	return // 使用了命名返回值,因此直接返回即可
}

传递下一页的完整URL

类似这样(伪代码,未经测试)。我认为你也可以使用JavaScript将当前页码存储在sessionStorage中。在我看来,递增后的页码应该由浏览器发送。

<button><a href="https://site.org?page=sessionStorage.page-1">Previous</a>s</button>
<button><a href="https://site.org?page=sessionStorage.page+1">Next</a></button>

或者,发送给一个函数,该函数一步处理递增和存储:

<button onclick="prev()">Previous</button>
<button onclick="next()">Next</button>

是的。我使用上述代码获取了查询字符串。 但是

page := r.URL.Query().Get("page")

我将 page 转换为整数。

// 假设总是存在一个包含整数值的 page 查询字符串
pageInt, _ := strconv.Atoi(page)
// 确认 pageInt 确实是一个整数后。
// 为简化起见,假设总是存在下一页
nextPage := pageInt + 1

在模板页面中

// 我现在应该使用哪个 URL?
<a href="?page={{.Next}}">Next</a>
// 这不是一个好主意。如果 URL 已经包含一些查询字符串,那么它看起来会像这样
// http://someurl.com/somepage?somequery=somevalue?page=2

<a href="&page={{.Next}}">Next</a>
// 这也不对,
// 如果 URL 没有查询字符串,那么它会是这样的
// http://someuser.com/somepage&page=2

所以我必须从 Go 代码中为“下一页”按钮传递完整的 URL。对吗? 或者有没有更简单的方法来做到这一点?

Mahesh_Kumar1: 我想为此添加分页功能。 我只想实现“下一页”和“上一页”按钮。

我一有时间就会亲自实现这个功能。不过我打算使用“无限滚动”来代替(这与分页类似,但会自动加载页面)。目前我还不知道具体怎么做。除了使用agGrid或类似的JavaScript库,它们内置了这些功能。但我不太喜欢JavaScript,所以我会尝试用Go的方法来实现。

我的目标是实现服务器端的无限滚动。我不知道这是否可行,但我想试一试。

也许几周后,我能给你一个更好的答案。

目前,我会先让Go获取所有记录并在页面加载时渲染。对于几百条记录来说,这应该足够了。

那么,我该如何添加类似 <a href="?page=4" 的代码呢?

我猜你只需要以某种方式将其添加到“下一页”按钮上。但我想你可能需要将“当前”页码存储在sessionStorage中,然后递增它或进行类似操作。例如 sessionStorage.page+1

关于身份验证的会话

这有点复杂。如果你问10个人,可能会得到10种不同的答案。我可以肯定,其他人会有不同的看法。我也很期待听到他们的意见 🙂 但以下是我对会话处理的理解:

  1. 使用一个身份验证服务器,生成一个UUID作为session_id,并将其在数据库中存储有限的时间(例如几天)。
  2. 获取这个session_id,并以某种缓存形式存储在Web服务器上。类似 cache2go 这样的工具。将缓存设置为在X小时后过期。
  3. 在浏览器中创建一个会话Cookie,其过期时间与服务器缓存相同。
  4. 当用户向Web服务器发送URL时,检查该Cookie是否存在于缓存中。
  5. 根据此会话Cookie,从身份验证服务器或已存储在会话缓存中的数据中检索必要的信息。

我的观点是,将session_id存储在浏览器中是无害的。因为所有其他流程都由Web服务器和/或身份验证服务器处理。如果会话Cookie被篡改,会话将会失败,因为新的Cookie与Web服务器中缓存的版本不匹配。

通过使用缓存的session_id,可以减少与身份验证服务器之间的数据传输。

在Go中获取包含查询参数的当前URL,可以直接从*http.Request对象构建。以下是几种常见方法:

方法1:使用Request.URL(推荐)

func handler(w http.ResponseWriter, r *http.Request) {
    // 获取完整的URL(包含查询参数)
    currentURL := r.URL.String()
    
    // 或者获取绝对URL(包含协议和主机)
    scheme := "http"
    if r.TLS != nil {
        scheme = "https"
    }
    fullURL := fmt.Sprintf("%s://%s%s", scheme, r.Host, r.URL.String())
    
    fmt.Fprintf(w, "当前URL: %s", fullURL)
}

方法2:使用url.URL结构体构建

func handler(w http.ResponseWriter, r *http.Request) {
    // 构建完整的URL
    url := &url.URL{
        Scheme:   "http",
        Host:     r.Host,
        Path:     r.URL.Path,
        RawQuery: r.URL.RawQuery,
    }
    
    if r.TLS != nil {
        url.Scheme = "https"
    }
    
    currentURL := url.String()
    fmt.Fprintf(w, "当前URL: %s", currentURL)
}

方法3:用于分页的完整示例

func paginationHandler(w http.ResponseWriter, r *http.Request) {
    // 解析现有查询参数
    query := r.URL.Query()
    
    // 添加或修改分页参数
    query.Set("page", "2")
    query.Set("limit", "20")
    
    // 重新构建URL
    r.URL.RawQuery = query.Encode()
    
    // 获取完整URL
    scheme := "http"
    if r.TLS != nil {
        scheme = "https"
    }
    
    nextPageURL := fmt.Sprintf("%s://%s%s", scheme, r.Host, r.URL.String())
    
    // 在模板中使用
    data := struct {
        CurrentURL string
        NextPageURL string
    }{
        CurrentURL: fmt.Sprintf("%s://%s%s", scheme, r.Host, r.URL.Path),
        NextPageURL: nextPageURL,
    }
    
    tmpl.Execute(w, data)
}

方法4:使用r.URL.RequestURI()

func handler(w http.ResponseWriter, r *http.Request) {
    // 获取路径和查询参数(不包含协议和主机)
    requestURI := r.URL.RequestURI()
    
    // 如果需要完整URL
    scheme := "http"
    if r.TLS != nil {
        scheme = "https"
    }
    fullURL := fmt.Sprintf("%s://%s%s", scheme, r.Host, requestURI)
    
    fmt.Fprintf(w, "RequestURI: %s\n完整URL: %s", requestURI, fullURL)
}

对于分页场景,通常需要:

  1. 获取当前URL和查询参数
  2. 解析查询参数
  3. 修改分页相关参数
  4. 重新构建URL用于模板渲染

r.URL已经包含了当前请求的路径和查询参数信息,可以直接使用。

回到顶部