Help us understand the problem. What is going on with this article?

GO gorm DB作成 INSERT JSONUnmarshal Mysql

こんにちは! GO学習中です!

今回はgormでinsertしてみたいと思います!

データは前回getしたapi
のデータを使用します。

DB自体をGOから作成した記事はこちらです。

では始めていきたいと思います。

mysql.go

// root/app/models/fgi.go
package mysql

import (
    "database/sql"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jinzhu/gorm"
)

// SQLConnect DB接続
func SQLConnect() (database *gorm.DB, err error) {
    DBMS := "mysql"
    USER := "root"
    PASS := ""
    PROTOCOL := "tcp(localhost:3306)"
    DBNAME := "テーブル名"

    CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=true&loc=Asia%2FTokyo"
    return gorm.Open(DBMS, CONNECT)
}

ここではDBはすでに作成しているものとします。
gormとはGOのORMパッケージです。

SQLConnect()の関数ではDBの情報を宣言して、

return gorm.Open(DBMS, CONNECT)

とすることでdbと接続しています。
DB情報はConfigなどにまとめたほうが良いかもしれません。今回はルートユーザーで行なっていきます。

fgi/fgi.go

こちらは冒頭紹介した記事
でgetしているapiのファイルです。上記の記事ではgetしただけでしたが、こちらでは
json.Unmarshalをすることで、用意した構造体に格納しています。

構造体はこちらの json-to-go
というサイトで簡単に用意できます。

左側にapiのjsonを貼り付けるとコード内のstructを用意してくれます。

package fgi

import (
    "encoding/json"
    "io/ioutil"
    "log"
    "net/http"
)

// APIClientFgi api情報格納
type APIClientFgi struct {
    key        string
    host       string
    httpClient *http.Client
}

// New struct生成
func New(key, host string) *APIClientFgi {
    fgiClient := &APIClientFgi{key, host, &http.Client{}}
    return fgiClient
}

// StructFgi fgi格納
type StructFgi struct {
    Fgi struct {
        Current struct {
            Value     int    `json:"value"`
            ValueText string `json:"valueText"`
        } `json:"now"`
        PreviousClose struct {
            Value     int    `json:"value"`
            ValueText string `json:"valueText"`
        } `json:"previousClose"`
        OneWeekAgo struct {
            Value     int    `json:"value"`
            ValueText string `json:"valueText"`
        } `json:"oneWeekAgo"`
        OneMonthAgo struct {
            Value     int    `json:"value"`
            ValueText string `json:"valueText"`
        } `json:"oneMonthAgo"`
        OneYearAgo struct {
            Value     int    `json:"value"`
            ValueText string `json:"valueText"`
        } `json:"oneYearAgo"`
    } `json:"fgi"`
}

// GetFgi api実行
func (fgi *APIClientFgi) GetFgi() (StructFgi, error) {

    url := "https://fear-and-greed-index.p.rapidapi.com/v1/fgi"

    req, _ := http.NewRequest("GET", url, nil)

    req.Header.Add("x-rapidapi-host", fgi.host)
    req.Header.Add("x-rapidapi-key", fgi.key)

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        return StructFgi{}, nil
    }

    defer res.Body.Close()

    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        return StructFgi{}, nil
    }

    var fgiStruct StructFgi
    if err := json.Unmarshal(body, &fgiStruct); err != nil {
        log.Fatal(err)
    }

    return fgiStruct, nil
}

json-to-goで生成したstructを呼び出しjson.Unmarshalでstructに格納しています。

models/fgi.go

このファイルでは上記でstructに格納したapi情報を展開してDBにINSERTしていきます。

package models

import (
    "fmt"
    "index-indicator-apis/mysql"
    "time"

    "index-indicator-apis/config"
    "index-indicator-apis/fgi"
)

const (
    tableNameFgis = "fgis"
)

// Fgis 日足格納
type Fgis struct {
    CreatedAt time.Time `json:"created_at,omitempty"`
    NowValue  int       `json:"now_value,omitempty"`
    NowText   string    `json:"now_text,omitempty"`
    PcValue   int       `json:"pc_value,omitempty"`
    PcText    string    `json:"pc_text,omitempty"`
    OneWValue int       `json:"one_w_value,omitempty"`
    OneWText  string    `json:"one_w_text,omitempty"`
    OneMValue int       `json:"one_m_value,omitempty"`
    OneMText  string    `json:"one_m_text,omitempty"`
    OneYValue int       `json:"one_y_value,omitempty"`
    OneYText  string    `json:"one_y_text,omitempty"`
}

//initFgis マイグレーション
func initFgis() {
    var err error
    db, err := mysql.SQLConnect()
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()
    db.AutoMigrate(&Fgis{})
}

// NewFgis fgi.StructFgiを受け取り、Fgisに変換して返す


func NewFgis(f fgi.StructFgi) *Fgis {
    createdAt := time.Now()
    nowValue := f.Fgi.Current.Value
    nowText := f.Fgi.Current.ValueText
    pcValue := f.Fgi.PreviousClose.Value
    pcText := f.Fgi.PreviousClose.ValueText
    oneWValue := f.Fgi.OneWeekAgo.Value
    oneWText := f.Fgi.OneWeekAgo.ValueText
    oneMValue := f.Fgi.OneMonthAgo.Value
    oneMText := f.Fgi.OneMonthAgo.ValueText
    oneYValue := f.Fgi.OneYearAgo.Value
    oneYText := f.Fgi.OneYearAgo.ValueText

    return &Fgis{
        createdAt,
        nowValue,
        nowText,
        pcValue,
        pcText,
        oneWValue,
        oneWText,
        oneMValue,
        oneMText,
        oneYValue,
        oneYText,
    }
}

// Create NewFgisをsaveする
func (f *Fgis) Create() error {
    db, err := mysql.SQLConnect()
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()
    db.Create(&f)
    return err
}

// CreateNewFgis migration後にapiを叩きdbに保存する
func CreateNewFgis() error {
    // initFgis() migration
    fgiClient := fgi.New(config.Config.FgiAPIKey, config.Config.FgiAPIHost)
    f, err := fgiClient.GetFgi()
    if err != nil {
        return err
    }
    fgi := NewFgis(f)
    fmt.Println(fgi)
    fmt.Println(fgi.Create())
    return err
}

initFgis()ではgormのメソッドをつかってマイグレーションしています。
apiの情報を先ほどstructに格納したので、それを展開してさらに展開したvalueを格納するstructを用意するということですね。
db.AutoMigrate(&Fgis{}) こちらがgormのメソッド AutoMigrateメソッドです。
事前に用意した構造体の名前をテーブル名としてマイグレーションしてくれます。この場合だと
fgisというテーブルがmysqlに作成されます。

func NewFgis(f fgi.StructFgi) *Fgis{}
こちらではapiのデータを格納している StructFgiの中身を展開してINSERTするために用意した構造体(マイグレーションした)の中に格納してます。

func (f *Fgis) Create() error {}
こちらのメソッドではmysqlファイルで作成した関数のSQLConnect()でdbと接続後に

db.Create(&f)
とすることでINSERTを実現しています。 .Createがgormのメソッドです。 .Create(&struct)とすることでテーブル名と対応しているstructの情報をINSERTしてくれます。

最後にCreateNewFgis()で用意した関数とメソッドを実行しています。

この関数をmain.goから呼び出せば無事に実行されることができました。

  • gormでは主キーとなるIDは自動で生成されるので宣言する必要はありません。

以上です!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away