Yes, using Go's standard library makes it easy to build REST APIs without relying on third-party frameworks. 1. Create the project structure and initialize the module: create main.go, handlers.go, models.go and go.mod files, and run go mod init myapi. 2. Define the data model: Define the User structure in models.go, including ID, Name, Email fields and corresponding json tags. 3. Write HTTP processor functions: implement getUsers, getUser and createUser functions in handlers.go, respectively, process the acquisition of all users, obtaining a single user according to the ID, and creating a new user request, set the correct content type and perform JSON encoding. 4. Configure the route and start the server: Use http.NewServeMux to register GET /users, POST /users and GET /users/{id} routes in main.go. Go 1.22 supports path parameters {id}, and finally start the service through http.ListenAndServe. 5. Test API: Use the curl command to send POST and GET requests to verify the interface function. In addition, third-party frameworks such as Gin are optional for more powerful routing, middleware and error handling capabilities. In actual projects, you also need to connect to the database, use context, add input verification and write tests, but the standard library is fast enough to build a lightweight REST API, which is simple and efficient in design, small code volume and superior performance.
Building a REST API in Go is straightforward thanks to Go's built-in net/http
package and its clean, minimal design. You don't need a heavy framework — though popular ones like Gin or Echo exist — to get a production-ready API up and running.

Here's how to build a basic REST API in Go using only the standard library, step by step.
1. Set Up Your Project Structure
Start with a simple project layout:

myapi/ ├── main.go ├── handlers.go ├── models.go └── go.mod
Initialize your module:
go mod init myapi
2. Define Your Data Model
In models.go
, define a struct to represent your data (eg, a User
):

// models.go package main type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` }
3. Create HTTP Handlers
In handlers.go
, write functions to handle HTTP requests. These functions must match the http.HandlerFunc
signature.
// handlers.go package main import ( "encoding/json" "net/http" ) var users []User var nextID = 1 // GET /users - Return all users func getUsers(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(users) } // GET /users/{id} - Return a single user func getUser(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") // Go 1.22 supports named path parameters // For older versions, parse from r.URL.Path manually w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]string{"message": "Get user " id}) } // POST /users - Create a new user func createUser(w http.ResponseWriter, r *http.Request) { var user User if err := json.NewDecoder(r.Body).Decode(&user); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) Return } user.ID = nextID nextID users = append(users, user) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(user) }
?? Note:
r.PathValue()
requires Go 1.22 . For earlier versions, extract the ID fromr.URL.Path
manually usingstrings.Split
.
4. Set Up Routes in main.go
// main.go package main import ( "net/http" "log" ) func main() { mux := http.NewServeMux() // Register routes mux.HandleFunc("GET /users", getUsers) mux.HandleFunc("POST /users", createUser) mux.HandleFunc("GET /users/{id}", getUser) log.Println("Server starting on :8080") log.Fatal(http.ListenAndServe(":8080", mux)) }
Go 1.22 supports pattern matching in ServeMux
, so you can use {id}
as a placeholder.
5. Test Your API
Run the server:
go run main.go
Now test with curl
:
# Create a user curl -X POST http://localhost:8080/users \ -H "Content-Type: application/json" \ -d '{"name":"Alice","email":"alice@example.com"}' # Get all users curl http://localhost:8080/users
Optional: Use a Router (Like Gorilla Mux or Gin)
For more complex routing, use a third-party router.
Example with Gin :
go get github.com/gin-gonic/gin
package main import ( "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/users", getUsers) r.POST("/users", createUser) r.Run(":8080") }
Gin provides better error handling, middleware, and performance.
Key Points to Remember
- Use
json
tags in structs for proper serialization. - Always set
Content-Type: application/json
. - Validate input and handle errors gracefully.
- Avoid global variables in production — use dependency injection.
- Add middleware for logging, auth, CORS, etc.
For a real-world API, you'd also:
- Connect to a database (eg, PostgreSQL with
pgx
orgorm
) - Use context for timeouts and cancellation
- Implement proper error responses
- Add input validation
- Write tests using
net/http/httptest
But for a simple REST API, Go's standard library is more than enough to get started.
Basically, it's clean, fast, and doesn't require much code.
The above is the detailed content of How do you build a REST API in Go?. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Go's switch statement will not be executed throughout the process by default and will automatically exit after matching the first condition. 1. Switch starts with a keyword and can carry one or no value; 2. Case matches from top to bottom in order, only the first match is run; 3. Multiple conditions can be listed by commas to match the same case; 4. There is no need to manually add break, but can be forced through; 5.default is used for unmatched cases, usually placed at the end.

AruneinGoisaUnicodecodepointrepresentedasanint32,usedtocorrectlyhandleinternationalcharacters;1.Userunesinsteadofbytestoavoidsplittingmulti-byteUnicodecharacters;2.Loopoverstringswithrangetogetrunes,notbytes;3.Convertastringto[]runetosafelymanipulate

Using bufio.Scanner is the most common and efficient method in Go to read files line by line, and is suitable for handling scenarios such as large files, log parsing or configuration files. 1. Open the file using os.Open and make sure to close the file via deferfile.Close(). 2. Create a scanner instance through bufio.NewScanner. 3. Call scanner.Scan() in the for loop to read line by line until false is returned to indicate that the end of the file is reached or an error occurs. 4. Use scanner.Text() to get the current line content (excluding newline characters). 5. Check scanner.Err() after the loop is over to catch possible read errors. This method has memory effect

To import local packages correctly, you need to use the Go module and follow the principle of matching directory structure with import paths. 1. Use gomodinit to initialize the module, such as gomodinitexample.com/myproject; 2. Place the local package in a subdirectory, such as mypkg/utils.go, and the package is declared as packagemypkg; 3. Import it in main.go through the full module path, such as import "example.com/myproject/mypkg"; 4. Avoid relative import, path mismatch or naming conflicts; 5. Use replace directive for packages outside the module. Just make sure the module is initialized

The answer is: Go applications do not have a mandatory project layout, but the community generally adopts a standard structure to improve maintainability and scalability. 1.cmd/ stores the program entrance, each subdirectory corresponds to an executable file, such as cmd/myapp/main.go; 2.internal/ stores private code, cannot be imported by external modules, and is used to encapsulate business logic and services; 3.pkg/ stores publicly reusable libraries for importing other projects; 4.api/ optionally stores OpenAPI, Protobuf and other API definition files; 5.config/, scripts/, and web/ store configuration files, scripts and web resources respectively; 6. The root directory contains go.mod and go.sum

Routing in Go applications depends on project complexity. 1. The standard library net/httpServeMux is suitable for simple applications, without external dependencies and is lightweight, but does not support URL parameters and advanced matching; 2. Third-party routers such as Chi provide middleware, path parameters and nested routing, which is suitable for modular design; 3. Gin has excellent performance, built-in JSON processing and rich functions, which is suitable for APIs and microservices. It should be selected based on whether flexibility, performance or functional integration is required. Small projects use standard libraries, medium and large projects recommend Chi or Gin, and finally achieve smooth expansion from simple to complex.

BuildconstraintsinGoarecommentslike//go:buildthatcontrolfileinclusionduringcompilationbasedonconditionssuchasOS,architecture,orcustomtags.2.TheyareplacedbeforethepackagedeclarationwithablanklineinbetweenandsupportBooleanoperatorslike&&,||,and

Go's flag package can easily parse command line parameters. 1. Use flag.Type() to define type flags such as strings, integers, and booleans; 2. You can parse flags to variables through flag.TypeVar() to avoid pointer operations; 3. After calling flag.Parse(), use flag.Args() to obtain subsequent positional parameters; 4. Implementing the flag.Value interface can support custom types to meet most simple CLI requirements. Complex scenarios can be replaced by spf13/cobra library.
