Skip to main content

Gin Route Parameters

Introduction

When building web applications, you often need to create URLs that contain dynamic parts. For example, when displaying a user profile, you might want a URL like /users/123 where 123 is the user's ID. In Gin, these dynamic parts of a URL are called route parameters or path parameters.

Route parameters allow you to extract values from the URL path and use them in your handlers. This creates cleaner, more intuitive URLs and enables you to build RESTful APIs and dynamic web applications.

In this tutorial, we'll explore how to define, access, and use route parameters in the Gin web framework.

Defining Route Parameters

In Gin, route parameters are defined by prefixing a path segment with a colon (:). The segment name after the colon becomes the parameter name that you can access in your handler function.

Basic Syntax

go
// The basic syntax for defining a route parameter
router.GET("/users/:id", func(c *gin.Context) {
// Handler logic
})

This route will match URLs like /users/1, /users/abc, or /users/john. The value after /users/ will be captured as the id parameter.

Accessing Route Parameters

To access the values of route parameters in your handler function, you use the c.Param() method provided by Gin's context.

Example: Basic Parameter Access

go
package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

func main() {
router := gin.Default()

router.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{
"message": "User details",
"id": id,
})
})

router.Run(":8080")
}

Output: When you make a request to /users/123, you'll get:

json
{
"message": "User details",
"id": "123"
}

Multiple Route Parameters

You can define multiple route parameters in a single path. Each parameter is treated separately and can be accessed individually.

Example: Multiple Parameters

go
package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

func main() {
router := gin.Default()

router.GET("/users/:userId/posts/:postId", func(c *gin.Context) {
userId := c.Param("userId")
postId := c.Param("postId")

c.JSON(http.StatusOK, gin.H{
"userId": userId,
"postId": postId,
})
})

router.Run(":8080")
}

Output: When you make a request to /users/123/posts/456, you'll get:

json
{
"userId": "123",
"postId": "456"
}

Working with Parameter Types

By default, all route parameters are captured as strings. If you need a parameter as a different type (like an integer), you'll need to convert it manually.

Example: Converting Parameters

go
package main

import (
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)

func main() {
router := gin.Default()

router.GET("/products/:id", func(c *gin.Context) {
idStr := c.Param("id")

// Convert id to integer
id, err := strconv.Atoi(idStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid product ID",
})
return
}

c.JSON(http.StatusOK, gin.H{
"message": "Product details",
"id": id,
"type": "This is an integer, not a string",
})
})

router.Run(":8080")
}

Output: When you make a request to /products/789, you'll get:

json
{
"message": "Product details",
"id": 789,
"type": "This is an integer, not a string"
}

Optional Parameters with Wildcards

Sometimes you might want to match paths that may or may not have additional segments. Gin provides a wildcard parameter syntax using * for such cases.

Example: Using Wildcards

go
package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

func main() {
router := gin.Default()

router.GET("/files/*filepath", func(c *gin.Context) {
filepath := c.Param("filepath")
// Note: filepath will include the leading slash

c.JSON(http.StatusOK, gin.H{
"message": "File access request",
"filepath": filepath,
})
})

router.Run(":8080")
}

Output: When you make a request to /files/documents/report.pdf, you'll get:

json
{
"message": "File access request",
"filepath": "/documents/report.pdf"
}

Real-World Application: RESTful API

Let's build a simple RESTful API for a blog application using route parameters.

go
package main

import (
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)

type Post struct {
ID int `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Author string `json:"author"`
}

// Mock database
var posts = []Post{
{ID: 1, Title: "Introduction to Gin", Content: "Gin is a web framework...", Author: "John"},
{ID: 2, Title: "Route Parameters", Content: "Route params are useful...", Author: "Jane"},
{ID: 3, Title: "Middleware in Gin", Content: "Middleware provides...", Author: "Bob"},
}

func main() {
router := gin.Default()

// Get all posts
router.GET("/posts", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"posts": posts,
})
})

// Get a specific post
router.GET("/posts/:id", func(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.Atoi(idStr)

if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid post ID",
})
return
}

// Find the post
for _, post := range posts {
if post.ID == id {
c.JSON(http.StatusOK, post)
return
}
}

// Post not found
c.JSON(http.StatusNotFound, gin.H{
"error": "Post not found",
})
})

// Get posts by author
router.GET("/authors/:name/posts", func(c *gin.Context) {
authorName := c.Param("name")
var authorPosts []Post

for _, post := range posts {
if post.Author == authorName {
authorPosts = append(authorPosts, post)
}
}

if len(authorPosts) == 0 {
c.JSON(http.StatusNotFound, gin.H{
"error": "No posts found for this author",
})
return
}

c.JSON(http.StatusOK, gin.H{
"author": authorName,
"posts": authorPosts,
})
})

router.Run(":8080")
}

This example demonstrates three endpoints:

  • /posts - Returns all blog posts
  • /posts/:id - Returns a specific post by its ID
  • /authors/:name/posts - Returns all posts by a specific author

Important Considerations

  1. Order Matters: Gin matches routes in the order they are defined. If you have routes that could match the same URL pattern, place the more specific routes first.
go
// More specific route first
router.GET("/users/admin", adminHandler)

// More general route second
router.GET("/users/:id", userHandler)
  1. Parameter Validation: Always validate parameters, especially when converting them to other types or using them for database queries.

  2. Parameter Names: Choose clear, descriptive parameter names that reflect their purpose.

Summary

Route parameters in Gin are a powerful feature that lets you create dynamic routes and build RESTful APIs easily. In this tutorial, you've learned:

  • How to define route parameters using the :paramName syntax
  • How to access parameter values with c.Param()
  • How to handle multiple parameters in a single route
  • How to convert parameters to appropriate types
  • How to use wildcard parameters with *
  • How to build a RESTful API using route parameters

By mastering route parameters, you can create cleaner, more intuitive URLs for your web applications and APIs, making them more user-friendly and easier to understand.

Exercises

  1. Create a simple API for a movie database that allows you to get movies by ID, genre, and director.
  2. Build a user management system with routes for user profiles, user posts, and user settings.
  3. Implement a route that accepts a wildcard parameter to serve static files from different directories.
  4. Create an API endpoint that supports both optional and required parameters.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)