使用gqlgen + Gorm时,对于Uint类型会引发错误

请用中文回答以下问题:

这次的话题是什么?

当使用gqlgen + Gorm时,返回Uint类型的列值时会出现类型错误,无法成功获取数据,因此在这里记录解决方法。

定義模型的结构体

package db_model

import (
    _ "github.com/jinzhu/gorm/dialects/mysql"
    "time"
)

type User struct {
    ID        uint32    `gorm:"primary_key;AUTO_INCREMENT;"`
    Name      string    `gorm:"size:255"`
    Password  string    `gorm:"size:255"`
    Email     string    `gorm:"size:255"`
    CreatedAt time.Time `gorm:"column:created_at;type:datetime;"`
    UpdatedAt time.Time `gorm:"column:updated_at;type:datetime;"`
    Items     []Item    `gorm:"foreignkey:ID"`
}

type Item struct {
    ID        uint32 `gorm:"primary_key;AUTO_INCREMENT;"`
    Name      string
    UserID    uint32
    CreatedAt time.Time `gorm:"column:created_at;type:datetime;"`
    UpdatedAt time.Time `gorm:"column:updated_at;type:datetime;"`
}

根据这个进行Gorm的AutoMigrate操作来创建表。

自前的标量的定义

由于gqlgen不支持Uint系列的类型,所以您需要自己准备标量。
在我的研究中,我发现已经有了一个很棒的解决方案,所以我借用了它。

package model

import (
    "encoding/json"
    "fmt"
    "io"
    "strconv"

    "github.com/99designs/gqlgen/graphql"
)

func MarshalUint(t uint) graphql.Marshaler {
    return MarshalUint64(uint64(t))
}

func UnmarshalUint(v interface{}) (uint, error) {
    i, err := UnmarshalUint64(v)
    return uint(i), err
}

func MarshalUint64(t uint64) graphql.Marshaler {
    return graphql.WriterFunc(func(w io.Writer) {
        _, err := io.WriteString(w, strconv.FormatUint(t, 10))
        if err != nil {
            return
        }
    })
}

func UnmarshalUint64(v interface{}) (uint64, error) {
    switch t := v.(type) {
    case string:
        return strconv.ParseUint(t, 10, 64)
    case int:
        return uint64(t), nil
    case int64:
        return uint64(t), nil
    case json.Number:
        i, err := t.Int64()
        return uint64(i), err
    case float64:
        return uint64(t), nil
    }

    return 0, fmt.Errorf("unable to unmarshal uint64: %#v %T", v, v)
}

func MarshalUint32(t uint32) graphql.Marshaler {
    return graphql.WriterFunc(func(w io.Writer) {
        _, err := io.WriteString(w, strconv.FormatUint(uint64(t), 10))
        if err != nil {
            return
        }
    })
}

func UnmarshalUint32(v interface{}) (uint32, error) {
    switch t := v.(type) {
    case string:
        u, err := strconv.ParseUint(t, 10, 32)
        return uint32(u), err
    case int:
        return uint32(t), nil
    case int64:
        return uint32(t), nil
    case json.Number:
        i, err := t.Int64()
        return uint32(i), err
    case float64:
        return uint32(t), nil
    }

    return 0, fmt.Errorf("unable to unmarshal uint32: %#v %T", v, v)
}

gqlgen.yml 请将以下内容用中文进行释义:

定义了一个附加的标量

...略
models:
  ID:
    model:
      - github.com/99designs/gqlgen/graphql.ID
      - github.com/99designs/gqlgen/graphql.Int
      - github.com/99designs/gqlgen/graphql.Int64
      - github.com/99designs/gqlgen/graphql.Int32
  Int:
    model:
      - github.com/99designs/gqlgen/graphql.Int
      - github.com/99designs/gqlgen/graphql.Int64
      - github.com/99designs/gqlgen/graphql.Int32
  User:
    model: "github.com/bb3104/gqlgen_gorm_sample/db_model.User"
  Item:
    model: "github.com/bb3104/gqlgen_gorm_sample/db_model.Item"
-------- ここから追加 ---------
  Uint:
    model: "github.com/bb3104/gqlgen_gorm_sample/graph/model.Uint"
  Uint32:
    model: "github.com/bb3104/gqlgen_gorm_sample/graph/model.Uint32"
  Uint64:
    model: "github.com/bb3104/gqlgen_gorm_sample/graph/model.Uint64"

GraphQL的模式结构

type User {
  id: Uint32! <- 最初はここにID!を定義してた為、Graphqlクエリのレスポンス結果がエラーになった。
  name: String!
  password: String!
  email: String!
  items: [Item!]
  createdAt: Time!
  updatedAt: Time!
}

type Item {
  id: Uint32!
  name: String!
  createdAt: Time!
  updatedAt: Time!
}

type Query {
  users: [User!]!
}

scalar Time
scalar Uint32 <- 追加

通过这样,在 Gorm 中创建的 ID 列的类型和在模式结构中定义的 ID 的类型将相等,问题得到成功解决!

请查看上述内容在Github的源代码,如果方便的话,请务必去看一下。
https://github.com/bb3104/gqlgen_gorm_sample

参考来源的网站 de

以下是中文的原生概述,请选择其中一种选项:

1. 源代码链接:https://gist.github.com/JonLundy/ad750704b83aebec69749f98ba48dcdc
2. gqlgen链接:https://github.com/99designs/gqlgen
3. GORM官方文档链接(日文):https://gorm.io/ja_JP/docs/index.html

广告
将在 10 秒后关闭
bannerAds