とある子育てパパの日記

とある子育てパパの日記です

tomlファイルをgolangから読み込む

以下のpackageを使用して、golangプログラムからtomlファイルを読み込んでみる。

github.com

コード

  • 実行ファイル
package main

import (
    "fmt"
    "os"
    "io/ioutil"
    "github.com/BurntSushi/toml"
)

//Config 設定ファイル
type Config struct {
    User UserConfig
}

//UserConfig 設定ファイルのユーザ部分
type UserConfig struct {
    Name string
    Age  int
}

var config Config

func main() {

    _, err := toml.DecodeFile("./config.toml", &config)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(config.User.Name)
}
  • tomlファイル
// config.toml
[User]
name  = "misuzu"
age     = 0

とっても簡単♪

goqueryでスクレイピング / golang

goqueryというライブラリを使ってgolangスクレイピングをやってみた。

下記のコードを実行するとhttp://techblog-sokuhou.com内のページtitleと記事一覧を取得します。

ちなみにhttp://techblog-sokuhou.comは、私が運営(放置に近いけど)しているテックブログのまとめサイトになります。

package main

import (
    "fmt"

    "github.com/PuerkitoBio/goquery"
)

func main() {
    url := "http://techblog-sokuhou.com"

    doc, err := goquery.NewDocument(url)
    if err != nil {
        fmt.Println(err)
    }

    title := doc.Find("title").Text()
    fmt.Println(title)

    doc.Find(".article").Each(func(i int, s *goquery.Selection) {

        link := s.Find("a")
        linkText := link.Text()
        linkHtml, _ := link.Html()
        linkUrl, _ := link.Attr("href")

        fmt.Println(linkText, linkUrl, linkHtml, "------------")
    })
}

詳細な利用方法はこちら github.com

godoc.org

2つの画像を重ねる / golang

画像にサイトロゴ画像を重ねる必要が出てきたので書いてみた。

やりたいこと

オリジナル画像にサイトロゴを重ねて合成する。

(まとめサイトなどに盗用されても出どころがわかるようにね。)

コード

package main

import (
    "fmt"
    "image"
    "os"

    "image/draw"
    "image/jpeg"
)

func main() {

    originImagePath := "/hogehoge/オリジナル画像.jpg"
    logoImagePath := "/hogehoge/ロゴ画像.jpg"
    saveImagePath := "/hogehoge/合成された画像.jpg"

    originFile, err := os.Open(originImagePath)
    if err != nil {
        fmt.Println(err)
    }
    logoFile, err := os.Open(logoImagePath)
    if err != nil {
        fmt.Println(err)
    }

    originImg, _, err := image.Decode(originFile)
    if err != nil {
        fmt.Println(err)
    }
    logoImg, _, err := image.Decode(logoFile)
    if err != nil {
        fmt.Println(err)
    }

    //オリジナル画像上のどこからlogoイメージを重ねるか
    //これだと左上
    startPointLogo := image.Point{0, 0}

    logoRectangle := image.Rectangle{startPointLogo, startPointLogo.Add(logoImg.Bounds().Size())}
    originRectangle := image.Rectangle{image.Point{0, 0}, originImg.Bounds().Size()}

    rgba := image.NewRGBA(originRectangle)
    draw.Draw(rgba, originRectangle, originImg, image.Point{0, 0}, draw.Src)
    draw.Draw(rgba, logoRectangle, logoImg, image.Point{0, 0}, draw.Over)

    out, err := os.Create(saveImagePath)
    if err != nil {
        fmt.Println(err)
    }

    var opt jpeg.Options
    opt.Quality = 100

    jpeg.Encode(out, rgba, &opt)
}

以上。

macで作ったgolangプログラムをcentOS7向けにコンパイル

golangで作ったツールを開発サーバで動かす際に調べたのでもめ。

簡単、これだけでいけた。

GOOS=linux GOARCH=amd64 go build main.go
  • 詳細はこちらをご確認

Installing Go from source - The Go Programming Language

画像をリサイズしてDBへ保存する / golang

時間がかかったのでメモ

やりたいこと

  • 画像からサムネイルを作成する(300*300のサイズに収まるようにリサイズ)
  • 作成したサムネイルをDBへ保存する

環境など

  • Mac(キャピタン)
  • go version go1.7 darwin/amd64
  • gorm というormマッパーを使用 github.com
  • resizeという画像リサイズをしてくれるパッケージを使用 github.com
  • DBはMySQL5.5.42
  • テーブル定義は下記の通り/ images f:id:dempatow:20161117123633p:plain

コード

//main.go

package main

import (
    "bytes"
    "image/jpeg"
    "log"
    "os"
    "time"

    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
    "github.com/nfnt/resize"
)

// テーブル定義
type Images struct {
    //  gorm.Model
    Id          int
    Source      []uint8
    Description string
    Created_at  time.Time
    Updated_at  time.Time
}

// DB接続情報
const (
    dbUser     = "hogehoge"
    dbPassword = "hogehoge"
    dbName     = "hogehoge"
)

func main() {

    // 画像読み込み
    file, err := os.Open("test.jpg")
    if err != nil {
        log.Fatal(err)
    }

    img, err := jpeg.Decode(file)
    if err != nil {
        log.Fatal(err)
    }
    file.Close()

    // 300*300に収まるようにリサイズした画像を取得
    imgThumb := resize.Thumbnail(300, 300, img, resize.Lanczos3)

    // ファイル保存
    out, err := os.Create("thumbnail.jpg")
    if err != nil {
        log.Fatal(err)
    }
    defer out.Close()
    jpeg.Encode(out, imgThumb, nil)

    // データベースへの保存
    buffer := new(bytes.Buffer)
    if err := jpeg.Encode(buffer, imgThumb, nil); err != nil {
        log.Println("unable to encode image.")
    }
    imageBytes := buffer.Bytes()

    db, err := gorm.Open("mysql", dbUser+":"+dbPassword+"@/"+dbName+"?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        panic("failed to connect database")
    }

    insertRow := Images{Source: imageBytes, Description: "テスト画像"}
    db.Create(&insertRow)
    defer db.Close()
}
  • test.jpgを同じファイルに置いてから実行すると、リサイズ画像をDBへ保存し、thumbnail.jpgがローカルへ保存される。

Rails 5.0.0.1で404/エラーページを動的に出力する

結構調べたのでメモ

やりたいこと

  • 404ページとその他のエラーページを動的に表示させるようにする。
  • エラーページ出力時にSlackへエラーを通知する。

いじったファイル

# config/initializers/exceptions_app.rb

Rails.configuration.exceptions_app = ->(env) { ErrorsController.action(:show).call(env) }
# app/controllers/errors_controller.rb

class ErrorsController < ApplicationController
  SERVER_ERROR_VIEW_NAME = '5xx'

  def show
    status_cd = request.env['PATH_INFO'].delete!("/")

    if Rack::Utils::SYMBOL_TO_STATUS_CODE[:not_found].to_s === status_cd
      # 404
      view = status_cd
    else
      # 404以外
      view = SERVER_ERROR_VIEW_NAME

      ####################################
      # ここでSlackなどへエラーの通知をすればいいと思う
      # request.env['PATH_INFO'] => ステータスコード
      # request.env['action_dispatch.exception'].to_s => エラーの内容
      # request.env['action_dispatch.original_path'].to_s => リクエストパス
      ####################################

    end

    render view, layout: false, status: status_cd
  end
<!-- app/views/errors/5xx.html.erb -->
<h1>ページの表示に失敗しました</h1>
<!-- app/views/errors/404.html.erb -->
<h1>お探しのページが見つかりませんでした</h1>

補足

  • 開発環境では下記の設定をしないと404とエラーページが表示されないので注意
# config/environments/development.rb

config.consider_all_requests_local = false
  • 作成したErrosController内でlib/配下にあるSlack通知用のクラスを呼び出す為に下記の設定が必要だった。これはハマったconfig.autoload_paths << Rails.root.join("lib")だけじゃだめだった
# config/application.rb

config.eager_load_paths << Rails.root.join("lib")