interface 実装パターン

package main

import "log"

type Worker interface {
    Hello() string
}

type User struct {
    Name string
}

func (u User) Hello() string {
    return u.Name
}

func Hello(w Worker) string {
    return w.Hello()
}

func main() {
    u := User{Name: "yohei"}    
    w := Worker(u)

    // 以下のやり方でも良い
    // var w Worker
    // w = u

    log.Print(Hello(w))
}

go wrap

package main

import "log"

// Isao ...
func Isao(input string) string {
    switch input {
    case "hello":
        return "hello!"
    case "hi":
        return "hi!"
    }
    return "何をいってるかわからねえよ!このやろう!!!"
}

func IsaoWrapper(input string) string {
    output := Isao(input)
    if output == "何をいってるかわからねえよ!このやろう!!!" {
        output = "何をいってるのかわかりません。"
    }
    return output
}

func main() {
    log.Print(IsaoWrapper("hello!"))
}

dispatch.yaml

defalut

src/default/app.yaml

application: lucky-antler-166302
version: 1
runtime: go
api_version: go1.8

handlers:
- url: /.*
  script: _go_app
  secure: always

src/default/handler.go

package app

import (
    "fmt"
    "net/http"
)

func init() {
    http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, default!")
}

app1

src/app1/app1.yaml

application: lucky-antler-166302
module: app1
version: 1
runtime: go
api_version: go1.8

handlers:
- url: /.*
  script: _go_app
  secure: always

src/app1/handler.go

package app1

import (
    "fmt"
    "net/http"
)

func init() {
    http.HandleFunc("/app1", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, app1")
}

app2

src/app2/app2.yaml

application: lucky-antler-166302
module: app2
version: 1
runtime: go
api_version: go1.8

handlers:
- url: /.*
  script: _go_app
  secure: always

src/app2/handler.go

package app2

import (
    "fmt"
    "net/http"
)

func init() {
    http.HandleFunc("/app2", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, app2!")
}

dispatch.yaml

src/dispatch.yaml

dispatch:
  # Default service serves the typical web resources and all static resources.
  - url: "*/favicon.ico"
    service: default

  # Default service serves simple hostname request.
  # - url: "lucky-antler-166302.appspot.com/"
  #   service: default

  # Send all mobile traffic to the mobile frontend.
  - url: "*/app1/*"
    service: app1

  # Send all work to the one static backend.
  - url: "*/app2/*"
    service: app2

デプロイ

  1. goapp deploy で各アプリをデプロイ
  2. 以下のコマンドでdispatch.yamlをデプロイ
    gcloud app deploy dispatch.yaml –project lucky-antler-166302

確認

  • https://lucky-antler-166302.appspot.com/
    Hello, default!

  • https://lucky-antler-166302.appspot.com/app1/
    Hello, app1

  • https://lucky-antler-166302.appspot.com/app2/
    Hello, app2

注意事項

/app1/ にアクセスした場合に、app1 moduleの /app1 にルーティングされる

each 1000件づつ実行

方法1

User.find_each do |u|
  p u // 1000件づつ、メモリにキャッシュ。1件づつブロック内で処理。
end

方法2

User.find_in_batches do |us|
  p us.count // 1000件が出力される
end

association先がnilのレコードを取得

モデル構成

class User < ApplicationRecord
  has_many :comments
  has_one :nickname
end

レコード取得

// user.comments = nil のユーザー
User.includes(:comments).references(:comments).where(comments: {id: nil})

// user.nickname = nil のユーザー
User.includes(:nickname).references(:nicknames).where(nicknames: {id: nil})

gin test

package app

import (
    "html/template"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
)

func init() {
    r := gin.Default()
    r.GET("/", newHandler)
    r.POST("/create", createHandler)
    http.Handle("/", r)
}

func newHandler(c *gin.Context) {
    t, err := template.ParseFiles("form.tmpl")
    if err != nil {
        log.Print("error", err)
    }
    t.ExecuteTemplate(c.Writer, "form", nil)
}

func createHandler(c *gin.Context) {
    key := "name"
    if str, ok := c.GetPostForm(key); ok { // GetPostFormがあれば存在しないKeyの場合はエラーハンドリングできる
        c.String(200, "%s created!", str)
    } else {
        c.String(200, "%sフィールドがありません", key)
    }
}

func testHandler(str string) func(*gin.Context) {
    return func(c *gin.Context) {
        c.String(200, str)
    }
}

Github

https://github.com/YoheiMiyamoto/gin-test

handler クロージャからの生成

package app

import (
    "html/template"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
)

func init() {
    r := gin.Default()
    r.GET("/", newHandler("hi!"))
    http.Handle("/", r)
}

// handlerを引数から生成する
func newHandler(str string) func(*gin.Context) {
    return func(c *gin.Context) {
        c.String(200, str)
    }
}

構造体の配列

type Users []*User

func (us Users) IDs() []string {
    ids := make([]string, len(us))
    for i, u := range us {
        ids[i] = u.ID
    }
    return ids
}

func main() {
    us := Users{&User{ID: "1"}, &User{ID: "2"}}
    log.Print(us.IDs()) // ["1","2"]にが戻る
}