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

Go中gqlgen实现GraphQL订阅失败:Playground提示不支持订阅

问题:gqlgen实现GraphQL订阅后Playground提示不支持Subscription类型

我用Go语言的gqlgen实现GraphQL API的订阅功能,完成了以下步骤:定义返回布尔值的Subscription类型、执行generate命令生成自动代码、在schemaresolvers.go中用goroutine实现订阅逻辑、在main.go配置服务器传输方式与WebSocket。但Playground无法检测到订阅功能,尝试执行订阅时会报错:Schema does not support operation type "subscription".,更换另一种WebSocket配置方案后问题仍未解决。


相关代码

导入包

"github.com/99designs/gqlgen/graphql/handler/transport"

main.go中的GraphQL Handler创建代码

func NewGraphQLHandler(dbInstance *gorm.DB) (http.Handler, error) {
    c := generated.Config{
        Resolvers: &graph.Resolver{
            DB: dbInstance,
        },
    }
    c.Directives.Auth = directives.Auth
    srv := handler.NewDefaultServer(generated.NewExecutableSchema(c))
    // 添加websocket,但Playground检测不到订阅
    srv.AddTransport(&transport.Websocket)

    return srv, nil
}

main.go中的路由配置

func registerHandlers(lifecycle fx.Lifecycle, router *mux.Router, graphqlHandler http.Handler) {
    router.Handle("/", playground.Handler("GraphQL playground", "/query"))
    router.Handle("/query", graphqlHandler)
    router.Handle("/subscriptions", graphqlHandler)

schemaresolvers.go中的订阅解析逻辑

func (r *subscriptionResolver) ServerEvents(ctx context.Context) (<-chan bool, error) {
    // 创建channel
    result := make(chan bool)

    // goroutine
    go func() {
        // 每5秒发送一次ping到channel
        ticker := time.NewTicker(5 * time.Second)
        defer ticker.Stop()

        for {
            select {
            case <-ticker.C:
                result <- true // 发送true到channel
            case <-ctx.Done():
                // 客户端断开时关闭
                close(result)
                fmt.Println("订阅已关闭")
                return
            }
        }
    }()
    return result, nil
}

GraphQL Schema定义

type Subscription {
    serverEvents: Boolean!
}

尝试过的替代WebSocket配置

srv := handler.New(generated.NewExecutableSchema(c))

srv.AddTransport(websocket.Transport{
    InitFunc: func(ctx context.Context, payload websocket.InitPayload) (context.Context, error) {
        return ctx, nil
    },
    Upgrader: websocket.Upgrader{
        CheckOrigin: func(r *http.Request) bool {
            return true
        },
    },
})

可能的解决方向

  1. 检查生成代码完整性
    执行go run github.com/99designs/gqlgen generate时确保无报错,查看generated/schema.go中是否包含Subscription相关的类型定义与根解析器引用。如果生成代码遗漏订阅逻辑,需检查schema文件路径是否正确,或gqlgen.yml配置是否禁用了订阅。

  2. 完善传输方式配置
    使用handler.NewDefaultServer时,需同时添加HTTP与WebSocket传输,避免单独配置WebSocket导致schema检测异常:

    srv.AddTransport(transport.Options{})
    srv.AddTransport(transport.GET{})
    srv.AddTransport(transport.POST{})
    srv.AddTransport(&transport.Websocket{})
    
  3. 调整Playground订阅端点
    Playground默认使用主GraphQL端点(/query)尝试订阅,若单独配置了/subscriptions,需在Playground设置中修改订阅端点为ws://localhost:<端口>/subscriptions;或简化路由,仅保留/query的handler映射,避免端点混淆。

  4. 确认Resolver注册
    检查graph/resolver.go中是否存在Subscription()方法,确保订阅解析器被正确注册到根Resolver:

    type Resolver struct {
        DB *gorm.DB
    }
    
    func (r *Resolver) Subscription() subscriptionResolver {
        return &subscriptionResolver{r}
    }
    

    该方法缺失会导致gqlgen无法识别订阅解析逻辑。

  5. 检查gqlgen.yml配置
    确保配置文件中未禁用订阅功能,默认配置无需额外设置,若有自定义配置需确认disable_subscriptions未设为true。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 15:23:10