Golang中如何创建可接受任意类型的结构体
Golang中如何创建可接受任意类型的结构体 大家好,
我想让从 database.go 中的函数返回的 Response 能够自定义。
例如,在领域层文件中,我有这个函数:
UserLogin(userCredential Credentials, password string) (*Response, error)
我希望这个函数的响应返回一个
token: "user-generated-token"。
而在另一个函数中,我希望返回类似这样的消息作为响应:
RegisterUser(input User) (*Response, error)
message: "User created"
在另一个从数据库函数返回的函数中,返回一个 JSON 对象或 JSON 数组。
然后将来自 database.go 的响应放入这个函数的 payload 参数部分:
func RespondJSON(w http.ResponseWriter, status int, result bool, message string, payload interface{}) {
response, err := json.Marshal(&domain.BaseEndPoint{
Success: result,
Message: message,
Response: payload,
})
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
w.Write([]byte(response))
}
为每个响应都创建一个结构体是不合理的。我该如何创建一个能够接受任何类型和键值对的结构体?这是我目前的结构体:
type Response struct {
Result interface{} `json:"result"`
}
在 Postman 中的结果:
"success": true,
"message ": "welcome .....",
"response": {
"result": {
"mobile": "+1 123456",
"password": "123456"
}
}
}
我需要一种方法,在这种情况下只移除 result,这样一切就都正常了。
附注:在领域层中为结果使用以下类型是否可以?
[]map[string]string
但我想当我需要返回产品列表或用户列表时会遇到问题。[]map 可能不适用。这样对吗?
或者我们可能根本不需要一个名为 Response 的结构体?而只是在领域层中创建我们需要的返回类型?
更多关于Golang中如何创建可接受任意类型的结构体的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我不完全确定你的问题。但是,你可以直接使用一个空接口,而不是使用一个内部包含空接口的结构体。
var Response interface{}
你可以使用它来代替:
type Response struct {
Result interface{} `json:"result"`
}
希望这能解答你的问题。
在Golang中创建可接受任意类型的结构体,通常使用interface{}或any类型。从你的代码看,你已经接近解决方案了,只需要调整结构体设计。
解决方案
1. 使用泛型结构体(推荐Go 1.18+)
// 通用响应结构体
type Response[T any] struct {
Success bool `json:"success"`
Message string `json:"message"`
Data T `json:"data,omitempty"`
}
// 使用示例
func UserLogin(userCredential Credentials, password string) (*Response[string], error) {
token := "user-generated-token"
return &Response[string]{
Success: true,
Message: "Login successful",
Data: token,
}, nil
}
func RegisterUser(input User) (*Response[string], error) {
return &Response[string]{
Success: true,
Message: "User created",
Data: "",
}, nil
}
func GetUsers() (*Response[[]User], error) {
users := []User{
{ID: 1, Name: "John"},
{ID: 2, Name: "Jane"},
}
return &Response[[]User]{
Success: true,
Message: "Users retrieved",
Data: users,
}, nil
}
2. 使用interface{}类型
type Response struct {
Success bool `json:"success"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
// 使用示例
func UserLogin(userCredential Credentials, password string) (*Response, error) {
token := "user-generated-token"
return &Response{
Success: true,
Message: "Login successful",
Data: token,
}, nil
}
func GetProducts() (*Response, error) {
products := []Product{
{ID: 1, Name: "Product A"},
{ID: 2, Name: "Product B"},
}
return &Response{
Success: true,
Message: "Products retrieved",
Data: products,
}, nil
}
3. 针对你的具体问题
修改你的RespondJSON函数:
func RespondJSON(w http.ResponseWriter, status int, success bool, message string, data interface{}) {
response := map[string]interface{}{
"success": success,
"message": message,
}
if data != nil {
response["response"] = data
}
jsonResponse, err := json.Marshal(response)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
w.Write(jsonResponse)
}
// 使用示例
func handleLogin(w http.ResponseWriter, r *http.Request) {
// ... 处理逻辑
token := map[string]string{
"token": "user-generated-token",
}
RespondJSON(w, http.StatusOK, true, "Login successful", token)
}
func handleUsers(w http.ResponseWriter, r *http.Request) {
// ... 处理逻辑
users := []User{
{ID: 1, Name: "John", Email: "john@example.com"},
{ID: 2, Name: "Jane", Email: "jane@example.com"},
}
RespondJSON(w, http.StatusOK, true, "Users retrieved", users)
}
4. 关于[]map[string]string的问题
// 不推荐使用 []map[string]string,因为:
// 1. 类型不安全
// 2. 性能较差
// 3. 难以维护
// 推荐使用具体类型
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Mobile string `json:"mobile,omitempty"`
}
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
}
// 这样可以直接返回
func GetUsers() ([]User, error) {
// ... 数据库查询
return users, nil
}
5. 完整示例
package main
import (
"encoding/json"
"net/http"
)
// 领域层结构体
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
type LoginResponse struct {
Token string `json:"token"`
ExpiresIn int `json:"expires_in"`
}
// 通用响应包装器
type ApiResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
// 领域层函数
func UserLogin(credentials Credentials) (*ApiResponse, error) {
// ... 验证逻辑
loginData := LoginResponse{
Token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
ExpiresIn: 3600,
}
return &ApiResponse{
Success: true,
Message: "Login successful",
Data: loginData,
}, nil
}
func GetUserList() (*ApiResponse, error) {
users := []User{
{ID: 1, Name: "John Doe", Email: "john@example.com"},
{ID: 2, Name: "Jane Smith", Email: "jane@example.com"},
}
return &ApiResponse{
Success: true,
Message: "Users retrieved successfully",
Data: users,
}, nil
}
// HTTP处理器
func loginHandler(w http.ResponseWriter, r *http.Request) {
response, err := UserLogin(credentials)
if err != nil {
// 错误处理
errorResponse := ApiResponse{
Success: false,
Message: err.Error(),
}
json.NewEncoder(w).Encode(errorResponse)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
这样设计可以:
- 移除多余的
result包装层 - 保持类型安全
- 支持任意类型的响应数据
- 提供一致的API响应格式

