0
0

More than 1 year has passed since last update.

gormを使ってみた

Posted at

はじめに

WebカメラのサイトのサムネイルのURLを格納しているテーブルを参照し、それぞれの画像をダウンロードして保存するプログラムを作成した。テーブルの参照、更新はgormを使用したが、思ったより使うのがしんどかった。

環境

  • go 1.17 → go 1.20
  • Windows 10
  • PostgreSQL 14

golangのバージョンアップ

プログラムを作る以前にgormのインポートからうまくいかず。
gorm.io/driver/postgresをインポートしようとして、go getしようとしたが、エラー。1.17から1.20にアップデートして解消した。

go get gorm.io/driver/postgres  
C:\Users\xxxx\go\pkg\mod\github.com\jackc\pgx\v5@v5.3.1\pgtype\builtin_wrappers.go:9:2: package net/netip is not in GOROOT 
(C:\Program Files\Go\src\net\netip)

問題なく作業できるかと思ったら、VS Codeでデバッガ起動したときにエラーが出力されて動かず。

Failed to launch:Version of Delve is too old for Go version 1.20.5(maximum supported version 1.18 suppress 
this error with --check-go-version=false)

なので、delveをアップデートした。

go get -u github.com/go-delve/delve/cmd/dlv

プログラムの作成

使用したテーブル名は、thumbnail_linkという名前で、以下のような形式。今思えば、更新するなら、IDくらいつけとけばよかったように思う。

列名 データ型
 link varchar(100)
download_flag integer

テーブル自体は以前作ったもので、もとのデータは、Webカメラのサイトからとってきたもの。

linkのデータは、次のようなthumbnailのURLが設定されている。
https://images-webcams.windy.com/92/1177842892/current/thumbnail/1177842892.jpg
donload_flagは、未ダウンロード:0 ダウンロード済:1で、ダウンロードした後1に更新する。

テーブルに合わせてモデルを定義した。一文字目を大文字にしないと検索しても値が入ってこない。

type thumbnail_link struct {
	Link          string
	Download_flag int
}

モデルをthumbnail_linkに定義した場合、生成されるSQLのテーブル名は、デフォルトでは複数形のthumbnail_linksになってしまうため、テーブル名をカスタマイズする関数を定義した。TableName()Gorm ライブラリで使用されるメソッド。

func (o thumbnail_link) TableName() string {
	return "thumbnail_link"
}

後から知ったが、db.Table("<テーブル名>")でもテーブルを指定することができるとのこと。

download_flagが0のもののみ取得して、ループしてダウンロードを実行した。

	var link []thumbnail_link
	db.Where("download_flag = ?", "0").Find(&link)
	for _, v := range link {
		downloadImage(v, db)
	}

画像は、http.Getで取得し、取得できたものに対してdownload_flagに1を設定した。

func downloadImage(v thumbnail_link, db *gorm.DB) {
	fmt.Println(v.Link)
	resp, err := http.Get(v.Link)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
    
    <保存処理>  
  
    db.Model(&v).Where("link = ?", v.Link).Update("download_flag", 1)

【コード全文】

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"

	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

type thumbnail_link struct {
	Link          string
	Download_flag int
}

func (o thumbnail_link) TableName() string {
	return "thumbnail_link"
}

func downloadImage(v thumbnail_link, db *gorm.DB) {
	fmt.Println(v.Link)
	resp, err := http.Get(v.Link)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	lastSlashIndex := strings.LastIndex(v.Link, "/")
	if lastSlashIndex == -1 {
		fmt.Println("スラッシュが見つからなかった")
		return
	}
	// スラッシュの後ろの文字列を取得
	fileName := v.Link[lastSlashIndex+1:]
	savefile, _ := os.Create("c:/temp/" + fileName)
	defer savefile.Close()

	image, _ := ioutil.ReadAll(resp.Body)
	data := []byte(image)
	savefile.Write(data) // 画像書き込み

	db.Model(&v).Where("link = ?", v.Link).Update("download_flag", 1)
}

func main() {
	dsn := "host=localhost user=user1 password=pass dbname=postgres port=5432 sslmode=disable TimeZone=Asia/Tokyo"
	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	var link []thumbnail_link
	db.Where("download_flag = ?", "0").Find(&link)
	for _, v := range link {
		downloadImage(v, db)
	}
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0