Author Archives: yoheimiyamoto

angular material テーマ

テンプレート読み込み

選択可能なcss

deeppurple-amber.css
indigo-pink.css
pink-bluegrey.css
purple-green.css

bukatsu_report/angular-app/src/styles.css

@import "~@angular/material/prebuilt-themes/purple-green.css";

テンプレート利用

html

primary, accent, warn から選択可能

<mat-toolbar class="mat-elevation-z4" color="primary">
</mat-toolbar>

参考

https://material.angular.io/guide/theming

bigquery クエリ

コード

SELECT
  record_id,
  amount,
  if(amount > 100000, 1, 0) as flag1,
  if(REGEXP_EXTRACT(string(amount), '(.{3}$)') = '000', 1, 0) as flag2
FROM
  [{プロジェクト名}:{データセット名}.{テーブル名}]
SELECT
  code,
  user_id,
  count(*) as count
FROM
  [{プロジェクト名}:{データセット名}.{テーブル名}]
WHERE
  // 直近7日間(日本時間に変更するために9時間足している)
  date(transaction_date) >= DATE(DATE_ADD(DATE_ADD(CURRENT_TIMESTAMP(), 9, 'HOUR'), -7, 'DAY'))
GROUP BY
  code,
  user_id
having
  count >= 2

参考

https://qiita.com/wapa5pow/items/afb32ee83d3a47355008

ファイルの保存

コード

package main

import (
    "html/template"
    "io"
    "net/http"
    "os"
)

func main() {
    http.HandleFunc("/", newHandler)
    http.HandleFunc("/create", createHandler)
    http.HandleFunc("/save", saveHandler)
    http.HandleFunc("/save2", saveHandler2)
    http.ListenAndServe(":8080", nil)
}

func newHandler(w http.ResponseWriter, r *http.Request) {
    var templatefile = template.Must(template.ParseFiles("form.html"))
    templatefile.Execute(w, "form.html")
}

func createHandler(w http.ResponseWriter, r *http.Request) {
    reader, err := r.MultipartReader()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    for {
        part, err := reader.NextPart()
        if err == io.EOF {
            break
        }

        //ファイル名がない場合はスキップする
        if part.FileName() == "" {
            continue
        }

        uploadedFile, err := os.Create("" + part.FileName())
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            uploadedFile.Close()
            return
        }

        _, err = io.Copy(uploadedFile, part)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            uploadedFile.Close()
            return
        }
    }
}

// フォームから受け取ったデータをファイルに保存する
func saveHandler(w http.ResponseWriter, r *http.Request) {
    url := "http://placekitten.com/g/640/340"

    response, err := http.Get(url)
    if err != nil {
        panic(err)
    }
    defer response.Body.Close()

    file, err := os.Create("save.jpg")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    io.Copy(file, response.Body)
}

// httpで受け取った画像データをファイルに出力
func saveHandler2(w http.ResponseWriter, r *http.Request) {
    url := "http://placekitten.com/g/640/340"

    res, err := http.Get(url)
    if err != nil {
        panic(err)
    }
    defer res.Body.Close()

    pin, pout := io.Pipe()

    go func() {
        _, err = io.Copy(pout, res.Body)
        if err != nil {
            panic(err)
        }
        if err != nil {
            pout.CloseWithError(err)
        } else {
            pout.Close()
        }
    }()

    file, err := os.Create("save2.jpg")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    io.Copy(file, pin)
}

参考

https://qiita.com/D3vel0pper/items/ea9f943c5e5d22a13fb6
http://kitak.hatenablog.jp/entry/2014/10/19/175133

並行処理

並行処理を行わないケース

完了まで6秒かかる

package main

import (
    "log"
    "time"
)

func main() {
    log.Print(get())
    log.Print(get())
}

func get() string {
    time.Sleep(3 * time.Second)
    return "hello"
}

並行処理を使うケース

方法1

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        log.Print(get())
    }()
    wg.Add(1)
    go func() {
        defer wg.Done()
        log.Print(get())
    }()
    wg.Wait()
}

func get() string {
    time.Sleep(3 * time.Second)
    return "hello"
}

方法2

方法1をfor文でまとめると以下

package main

import (
    "log"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 2; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            log.Print(get())
        }()
    }
    wg.Wait()
}

func get() string {
    time.Sleep(3 * time.Second)
    return "hello"
}

方法3

チャンネルを使って、最大並列数を設定

package main

import (
    "log"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    c := make(chan int, 2) // 最大並列数を2に設定
    for i := 0; i < 50; i++ {
        wg.Add(1)
        go func() {
            c <- 1 // チャンネルが一杯の場合はここで待機する
            defer func() {
                wg.Done()
                <-c
            }()
            log.Print(get())
        }()
    }
    wg.Wait()
}

func get() string {
    time.Sleep(3 * time.Second)
    return "hello"
}

angular gae デプロイ

ソースツリー

project/
├ backend
│ ├ dist/
│ ├ app.go
│ └ app.yaml

└ angular-app

app.yaml

application: {アプリ名}
version: 1
runtime: go
api_version: go1.8

handlers:
- url: /(.*\.(gif|png|jpeg|jpg|css|js|ico))$
  static_files: dist/\1
  upload: dist/(.*)
- url: /(.*)
  static_files: dist/index.html
  upload: dist/index.html

app.go

package main

import "net/http"

func init() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    })
}

設定ファイル変更

angular-gae-app/.angular-cli.json

// 変更前
"outDir": "dist",

// 変更後
"outDir": "../backend/dist",

自動ビルド

angularを更新すると自動で再度ビルドされ、gae backendにdistをコピーしてくれる

ng build --prod --watch

// サブディレクトリにビルドする場合は以下
ng build --prod --deploy-url=/{ディレクトリ名}/ --watch

参考

https://qiita.com/nirasan/items/68ccb9808f3739a9c999
http://mycoderepository.org/?p=3606