You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go开发API在Postman正常,JavaScript调用报跨域错误

解决Go API跨域问题:预检请求Access-Control-Allow-Origin为null错误

嘿,这个问题我太熟了——这就是浏览器的**跨域资源共享(CORS)**限制在搞鬼!Postman这类工具不会像浏览器那样严格执行CORS规则,所以你的API在Postman里能正常跑,但前端JS调用时,浏览器会先发送一个OPTIONS类型的「预检请求」,检查你的API是否允许跨域访问。如果你的API没正确处理这个预检请求,或者没返回正确的CORS响应头,就会弹出这个错误。

下面给你两种靠谱的解决办法:

方法1:手动写个CORS中间件

自己写个简单的中间件,给所有请求加上必要的CORS响应头,还能直接处理OPTIONS预检请求:

package main

import (
    "encoding/json"
    "github.com/gorilla/mux"
    "log"
    "net/http"
    "strconv"
)

type Calculate struct {
    Operand1 string `json:"Operand1,omitempty"`
    Operand2 string `json:"Operand2,omitempty"`
    Operator string `json:"Operator,omitempty"`
}

type Answer struct {
    Res float64 `json:"Res,omitempty"`
}

// CORS中间件,给请求加跨域头
func corsMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 允许的源,生产环境别用*,换成你的前端域名比如"http://localhost:3000"
        w.Header().Set("Access-Control-Allow-Origin", "*")
        // 允许的请求方法
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        // 允许的请求头,比如Content-Type是POST请求必须的
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
        
        // 处理浏览器的OPTIONS预检请求,直接返回200就行
        if r.Method == "OPTIONS" {
            w.WriteHeader(http.StatusOK)
            return
        }
        
        // 继续走后续的业务逻辑
        next.ServeHTTP(w, r)
    })
}

func calculateHandler(w http.ResponseWriter, r *http.Request) {
    var calc Calculate
    err := json.NewDecoder(r.Body).Decode(&calc)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    res := 0.0
    switch calc.Operator {
    case "+":
        op1, _ := strconv.ParseFloat(calc.Operand1, 64)
        op2, _ := strconv.ParseFloat(calc.Operand2, 64)
        res = op1 + op2
    // 这里可以加其他操作符的逻辑,比如-、*、/
    }

    json.NewEncoder(w).Encode(Answer{Res: res})
}

func main() {
    r := mux.NewRouter()
    // 给所有路由加上CORS中间件
    r.Use(corsMiddleware)
    r.HandleFunc("/calculate", calculateHandler).Methods("POST")

    log.Fatal(http.ListenAndServe(":8080", r))
}

方法2:用gorilla官方的handlers包处理CORS

不想自己写中间件?直接用gorilla官方提供的handlers包,配置更灵活:

  1. 先安装这个包:
go get github.com/gorilla/handlers
  1. 修改你的main函数,用CORS包装路由:
package main

import (
    "encoding/json"
    "github.com/gorilla/mux"
    "github.com/gorilla/handlers"
    "log"
    "net/http"
    "strconv"
)

// 结构体和calculateHandler函数和上面一样...

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/calculate", calculateHandler).Methods("POST")

    // 配置CORS规则
    corsConfig := handlers.CORS(
        handlers.AllowedOrigins([]string{"*"}), // 生产环境替换为你的前端域名
        handlers.AllowedMethods([]string{"POST", "OPTIONS"}),
        handlers.AllowedHeaders([]string{"Content-Type"}),
    )

    // 用CORS中间件包装路由后启动服务
    log.Fatal(http.ListenAndServe(":8080", corsConfig(r)))
}

最后提醒下:

  • 生产环境绝对不要用*作为允许的源,一定要指定具体的前端域名,比如"https://your-frontend-app.com",避免安全风险。
  • 必须确保你的API能处理OPTIONS请求,因为浏览器的预检请求就是OPTIONS类型的,如果路由只允许POST,没处理OPTIONS,预检肯定失败。

内容的提问来源于stack exchange,提问作者Priya S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:39:52