Category Archives: Go

ファイルの保存

コード

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

glide

インストール

brew update
brew install glide

初期化

cd {該当パッケージのパス}
glide init
glide install // vendorフォルダにパッケージがインストールされる

バージョン指定


参考

https://liginc.co.jp/305623

gae go 環境変数

app.yaml

env_variables:
  ENV: 'dev'

model.go

func init() {
    switch os.Getenv("ENV") {
    case "dev":
        err := godotenv.Load("kintone.dev.env")
        if err != nil {
            log.Fatal("Error loading .env file")
        }
    case "prd":
        err := godotenv.Load("kintone.prd.env")
        if err != nil {
            log.Fatal("Error loading .env file")
        }
    default:
        err := godotenv.Load("../app/kintone.dev.env")
        if err != nil {
            log.Fatal("Error loading .env file")
        }
    }
}

func newClient(ctx context.Context, appID string) *kintone.Client {
    log.Print("init Client")
    log.Print(os.Getenv("KINTONE_DOMAIN"))
    var httpclient *http.Client
    if ctx != nil {
        httpclient = urlfetch.Client(ctx)
    }
    client, _ := kintone.NewClient(
        os.Getenv("KINTONE_DOMAIN"),
        os.Getenv("KINTONE_USER"),
        os.Getenv("KINTONE_PASSWORD"),
        appID,
        httpclient,
    )
    return client
}

datastore gce

管理画面

gceのインスタンス設定画面ですべてのAPIを有効に変更

add

import "cloud.google.com/go/datastore"

func main(){
  datastoreClient, err := datastore.NewClient(ctx, ProjectID)
  if err != nil {
    panic(err)
  }
  e := Entry{
    Price: EntryPrice(1400000),
    Size:  2.2,
  }
  key := datastore.NameKey("Entry", "entry1", nil)
  _, err := c.Put(ctx, key, &e)
  if err != nil {
    panic(err)
  }
}

get

import "cloud.google.com/go/datastore"

func main(){
  datastoreClient, err := datastore.NewClient(ctx, ProjectID)
  if err != nil {
    panic(err)
  }
  var e Entry
  key := datastore.NameKey("Entry", "entry1", nil)
  err := c.Get(ctx, key, &e)
  if err != nil {
    panic(err)
  }
}

gcp stackdriver

実装

// Sample stdlogging writes log.Logger logs to the Stackdriver Logging.
package main

import (
        "log"

        // Imports the Stackdriver Logging client package.
        "cloud.google.com/go/logging"
        "golang.org/x/net/context"
)

func main() {
        ctx := context.Background()

        // Sets your Google Cloud Platform project ID.
        projectID := "YOUR_PROJECT_ID"

        // Creates a client.
        client, err := logging.NewClient(ctx, projectID)
        if err != nil {
                log.Fatalf("Failed to create client: %v", err)
        }
        defer client.Close()

        // Sets the name of the log to write to.
        logName := "my-log"

        logger := client.Logger(logName).StandardLogger(logging.Info)

        // Logs "hello world", log entry is visible at
        // Stackdriver Logs.
        logger.Println("hello world")
}

参考

https://cloud.google.com/logging/docs/setup/go?hl=ja