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

Golang后端对接Next.js前端API序列化错误及数据获取问题

问题解决及优化方案

一、核心问题定位

报错的直接原因是前端getServerSideProps返回的username为undefined,Next.js要求序列化props时不能存在undefined,必须替换为null或直接省略。而根源是后端接口返回内容不符合预期,前端无法获取有效数据。

二、后端代码修复

1. 修正data.go的GetData函数

当前GetData获取到Pokemon API数据后仅打印,却返回空字符串,导致后端接口无有效数据输出。修改如下:

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
)

func GetData() string {
    response, err := http.Get("http://pokeapi.co/api/v2/pokedex/kanto/")
    if err != nil {
        fmt.Print(err.Error())
        os.Exit(1)
    }
    // 关闭响应体,避免资源泄漏
    defer response.Body.Close()

    responseData, err := io.ReadAll(response.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(responseData))
    // 返回实际获取到的数据
    return string(responseData)
}

2. 修正Main.go的/username接口逻辑

原代码同时使用json.NewEncoder(rw).Encode(resp)和rw.Write(resp),导致重复输出且格式错误,修改后:

package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        rw.Header().Set("Content-Type", "application/json")
        
        if req.URL.Path == "/status" {
            resp := []byte(`{"status": "ok"}`)
            rw.Header().Set("Content-Length", fmt.Sprint(len(resp)))
            rw.Write(resp)
        } else if req.URL.Path == "/username" {
            data := GetData()
            rw.Header().Set("Content-Length", fmt.Sprint(len(data)))
            rw.Write([]byte(data))
        } else {
            rw.WriteHeader(http.StatusNotFound)
            rw.Write([]byte(`{"error": "not found"}`))
            return
        }
    })

    log.Println("Server is available at http://localhost:8000")
    log.Fatal(http.ListenAndServe(":8000", handler))
}

注:原代码中json.NewEncoder会把字节数组再次JSON编码,导致返回内容是字符串形式的字节数组,而非预期的Pokemon API JSON结构,因此必须移除该行。

三、前端代码修复

1. 处理undefined序列化问题

后端返回的是Pokemon图鉴数据,无username字段,前端解构会得到undefined,需设置默认值为null,同时删除无效代码:

export async function getServerSideProps() {
  const statusResp = await fetch("http://localhost:8000/status").then(x => x.json());
  // 捕获接口错误,避免页面崩溃
  const pokedexData = await fetch("http://localhost:8000/username")
    .then(x => x.json())
    .catch(() => null);
  
  return {
    props: {
      status: statusResp.status || null,
      // 用图鉴名称作为username展示,避免undefined
      username: pokedexData?.name || null,
    }
  }
}

export default function Home({status, username}: {status: string | null, username: string | null}) {
  return (
    <div className="">
      <main className="">
        <h1 className="">
          Welcome to Next.js!
        </h1>
        <div>Status is: {status}, your username is: {username}</div>
      </main>
    </div>
  )
}

四、优化建议

后端优化

  • 使用Go 1.16+推荐的io.ReadAll替代ioutil.ReadAll
  • 增强错误处理:Pokemon API请求失败时,返回友好的错误JSON,而非直接终止进程
  • 拆分路由逻辑,避免单个handler中过多if-else判断,提升代码可维护性
  • 添加CORS配置,避免跨域问题(若前后端部署在不同域名)

前端优化

  • 为fetch添加完整的错误捕获逻辑,避免接口失败导致页面崩溃
  • 明确类型定义,放弃any类型,使用string | null这类具体类型
  • 将API请求封装为独立函数,便于复用和统一维护
  • 考虑使用SWR或React Query实现数据缓存和自动刷新,提升用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:18:16