How to handler segment uri?

hi everyone, today i try to create rest api in golang use standart library. in thise case i want to get data user by id from database. so pattern uri like

/user/{idUser}

but before that, i want to test the handler can work well. in function handler will be shown text “work”. my problem is if access to http://localhost:9393/user/1 should be shown text is work! (function GetUserId) but shown is the even HomeHandler.

mycode main.go :

package main

import (
“database/sql”
“encoding/json”
“fmt”
“net/http”

github.com/muhfaris/goFun/basic_serialdata/01_go_mysql_rest/database

_ “github.com/go-sql-driver/mysql
)

type ServeMux struct {
// contains filtered or unexported fields
}

// DB initialize of sql.DB
var DB *sql.DB

func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", HomeHandler)
mux.HandleFunc("/users", GetUsers)
mux.HandleFunc("/user/{id}", GetUserId)
http.ListenAndServe(":9393", mux)
}

func HomeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, Access Data To Get all User : /users Get User by Id : /user/{id})
}

func GetUsers(w http.ResponseWriter, r *http.Request) {
dbdata := database.GetDataUsers()
json.NewEncoder(w).Encode(dbdata)
}

func GetUserId(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, “Work!”)
}

database.go :
package database

import (
“database/sql”
“fmt”
)

const (
username = "surname"
password = ""
dbname = "database"
server = "localhost"
port = 3306
)

// User for get user from db
type User struct {
Id int
Name string
Email string
}

func Connect() (*sql.DB, error) {
dbtext := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", username, password, server, port, dbname)
db, err := sql.Open(“mysql”, dbtext)

if err == nil {

}
return db, nil
}

func GetDataUsers() (data []*User) {
DB, err := Connect()
var u User
defer DB.Close()
if err == nil {
// Read data
readdb, _ := DB.Query(“select * from user”)
for readdb.Next() {
readdb.Scan(&u.Id, &u.Name, &u.Email)
data = append(data, &User{
Id: u.Id,
Name: u.Name,
Email: u.Email,
})
}
} else {
panic(err.Error())
}
return
}

Standard library mux (net.http) doesn’t support parameterized routes, so this won’t work:

mux.HandleFunc("/user/{id}", GetUserId)

You can use some other mux, for example gorilla:

By the way, you should always use plural for resources:

/users/{id}

oh, wow, … i don’t know if its not support for parameterized routers, yeah i new in golang.

thanks @acim, i will try

1 Like

You can easily get the user ID using the standard library like this:

mux.HandleFunc("/users/", GetUsers) // Notice the extra "/" in /users/.

func GetUsers(w http.ResponseWriter, r *http.Request) {
    id := r.URL.Path[strings.LastIndex(r.URL.Path, "/")+1:]
    ...
}
1 Like

I agree with the idea to use stdlib as much as possible, but for beginners and people comming from other languages it can be quite difficult to use net.http and start parsing URL path manually. This may dissapoint them and lead to forget about learning Go.

At least I suggested to use idiomatic mux :slight_smile:

thanks @nstratos , it’s work !

1 Like

@acim don’t worry … i’m not them :grin:, im seriously to build my first project with standart library

1 Like