ぺい

渋谷系アドテクエンジニアの落書き

GolangのgoaでAPIをデザインしよう(ベース作成編)

f:id:tikasan0804:20170505212036p:plain

goaはいいぞ!

Golangのgoaの勉強に役立つ情報まとめ - ぺい
goaの情報をもっと見たい方は、上のリンクから確認してください

ベースの作成が微妙にだるい

結構goaを使う機会が増えてきて、微妙にだるいなーと思ったことがありました。 goaで何度かAPI作ったことがある人なら分かると思いますが
「使うコード大体決まってるのに、毎回作るの面倒・・・」

ということで、自分がよく使う構成をベースのテンプレートを作成しました。個人的には、これをCLIでやりたい気持ちもありましたが、goaのv2が出てからやろうかなという気持ちです。

作ったもの

github.com

上記2パターン作成しました。それぞれにREADMEを置いてます。 良い書き方や間違っている部分あれば、PRください。

builderscon 2017 Tokyo 控えめに言って最高だった

builderscon.io

行ってきました!大満足でした!

buildersconとは?

公式サイトに以下のようにあります。

buildersconは「知らなかった、を聞く」をテーマとした技術を愛する全てのギーク達のお祭りです。 buildersconではトークに関して技術的な制約はありません、特定のプログラミング言語や技術スタックによるくくりも設けません。 必要なのは技術者達に刺激を与えワクワクさせてくれるアイデアのみです。

あなたが実装したクレイジーなハックを見せて下さい。あなたの好きな言語のディープな知識をシェアしてください。あなたの直面した様々な問題と、それをどう解決したかを教えてください。未来技術のような未知の領域について教えてください。

buildersconに参加して、あなたの情熱をシェアしてください!皆様のご参加をお待ちしております!

f:id:tikasan0804:20170805200427p:plain

ノベルティのTシャツはこんな感じでした。いい感じですね。

なぜこのカンファレンスは面白いのか

このカンファレンスは、特定のテーマはあるものの、言語やフレームワークや設計思想など発表内容に、ほとんど縛りがありません。なので、多種多様な発表が凝縮されていて、常に発見があります。何かの技術をテーマとしたカンファレンスが面白いのは当然ですが、こういった全く違う趣向のものも面白いなと率直に感じました。

どんなセッションがある?

builderscon.io トップレベルで変態なセッションでした。内容はタイトルからは分からないくらい高度で、最後には会場全体が「すげえ・・・」ってなってました。

builderscon.io メルカリのバナー作成をUI含めて自動生成するというすごそうなツールのお話でした。作るのにかかる工数をどこまでに抑えるか、今後どのような展開が予想されるかなど、様々な意思決定や実際に組んだコードの意図なども含めて話があり、メルカリのエンジニアすげえ・・・って感じでした。

builderscon.io 正直僕には難しすぎて、鼻水が出ました。ただただすごいです。

builderscon.io 大規模サービスになると何が辛いんだっけみたいな話から、具体的な解決パターンなどが詳しく解説されていて、かなり参考になる話でした。これは一度見直さなければ・・・という感じのセッションです。

builderscon.io Slack社のSlackのコア部分がPHPで構成されていて、それは一体どのようにしてトラフィックに耐えているのか、またどのようにして、パフォーマンス向上を実現したのかについてのセッションでした。
主にHHVMとPHP7についての話でした。(Slackは最終的にHHVMを採用しました)このセッションは最後の質疑応答が非常に面白かったです。中でも以下の回答が秀逸でした。

セッション動画

www.youtube.com 今後恐らくここに順次アップされていくと思われます。他にも見たいセッションがたくさんあったので、アップされるのが楽しみです。

まとめ

次回は参加するだけではなく、何かLTでも良いので発表出来たらなと考えていたりします・・・。
主催の@lestrratさん、運営の方々、スポンサーのみなさん。ありがとうございました!本当に良かったです。

builderscon 2017 Tokyo: Building high performance push notification server in Go

builderscon.io

github.com

GoのOSSのGaurunを使ってアプリユーザーにプッシュ通知を送るための話。
※聞きながら書いたので、雑になってます

プッシュ通知の仕組み

Push通知のためのサービスを通して、ユーザーに通知が行く。
APNs GCM/FCMなどを使った話をします。

APNs

種類

  • APNs Binary Provider API(レガシー)
  • APNs Provider API これだと、JSONペイロードcurlで投げるだけでプッシュ通知を試せたりするくらい気軽になる。

GCM/FCM

  • HTTPS
  • サーバーキー

GoogleはFCM使えと言っている。
基本はJSONペイロードcurlで投げるだけでpush通知を投げれる。

ネットワークを介す処理だから遅い

APNsとGCM/FCMとの通信には、ある程度時間がかかる。これはサーバーがアメリカにあったりするからです。特にAPNsは結構遅い。

構成例

サーバー -> nginx -> Gaurun -> HTTP2 -> APNs/GCMなど -> アプリ

通知するタイミングは、お気に入りつけたや購入したコメントしたなど。
出来れば短時間で対象ユーザーに送りたい。

短時間で大量にさばくには、ネットワークレイテンシが高い問題を解消する必要があった。(これが難しい)

旧メルカリの構成

通知が遅くなる問題を見たら、処理と通知が同期的に行われていたから、ネットワークレイテンシと比例して遅くなる。またバッチ処理もあまり効率が良くなかったので、全ユーザー通知も時間がかかっていた。

通知を非同期にした

APIサーバーが通知Queueに送って、それらを順次処理していく形にした。これで劇的なパフォーマンスの改良が可能になった。QueueはQ4Mを使った。

PHPがそもそも遅いので限界があった

PHPは並行処理が苦手なので、そこまで速くならなかった。

Goと相性が良かった

ネットワークレイテンシを下げる必要がある。スループットを改善する。このような需要とマッチしていた。

Gaurun

プッシュ通知サーバーに使うGoOSS
JSON baseのAPI(HTTP)

提供しているAPI

  • プッシュ通知
  • モニタリング(errorの数やgoroutineの数)
  • コンフィグ

Goを採用した理由

  • 高い並行性
  • 高いパフォーマンス
  • 標準パッケージが使いやすい

構成

  • HTTPサーバー
  • APNs GCM/FCMのプロキシ
  • queueと並行処理が出来る

gorutineはwerkerはpusherを持っている。
werkerはpusherの数しか知らない。pusherはpushするだけ。

コネクションハンドリング

http.Clientを使っている(net/http) 設定は、http.Transportを使っている。昔は結構自力で書いてたけど、いまは標準パッケージにお任せしている。

Timeoutについて

サーバーのタイムアウトなのか?クライアントのタイムアウトなのか?接続する時のタイムアウトなのか?とにかく色んなタイムアウトがある。

net/httpパッケージ

  • net.Dial
  • http.Transport
  • http.Client
  • http.Server

上記それぞれにTimeoutが用意されている

Gaurunのパフォーマンスを上げる

TOMLで設定をチューニングする必要があります。なぜなら、初期設定のままだと、結構保守的な設定になっています。

  • core.workers ワーカーの数
  • core.queues channelのサイズ

などなど、色々な設定が出来る。

pusherの数

core.workers x core.pusher_max を調整して、メモリを無駄なく使うと良い。

Keep-Aliveの数

keep-aliveはあまりにも大きすぎる数値を指定すると、場合によってはAPNsなどに拒否されることがあったりするかも?

Bulk enqueue

JSONペイロードのnotification[]の中に複数指定して、リクエストすればおk。デフォルトでは、100件までとしている。

Device tokenのスクリーニング

無効化されたtokenを定期的に削除したい。無駄に送信するとパフォーマンスが落ちるので大事です。Gaurunでは成功、失敗が error_logで取れるので、これを使えばスクリーニングが出来ます。

メルカリでの実際の運用
JSON.log -> S3 -> Batch -> MySQL

Golangのreflectの公式ドキュメント翻訳

reflectパッケージ

f:id:tikasan0804:20170719172956p:plain

※翻訳については、ざっくりこんな感じくらいのノリです。

reflect - The Go Programming Language

Package reflect implements run-time reflection, allowing a program to manipulate objects with arbitrary types. The typical use is to take a value with static type interface{} and extract its dynamic type information by calling TypeOf, which returns a Type.

Package reflectionは実行時reflectionを実装し、プログラムが任意の型のオブジェクトを操作できるようにします。 一般的な使用方法は、静的型interface{}で値をとり、Typeを返すことで動的型情報を抽出することです。

package main

import (
    "fmt"
    "reflect"
)

func main() {
    fmt.Println("----typeof-----")
    typeof(1, "string", true)
    fmt.Println("----typeof2-----")
    typeof2(1)
}

// vが何の値かを出力する
func typeof(value ...interface{}) {
    for _, v := range value {
        fmt.Println(reflect.TypeOf(v))
    }
}

// vがint型と同じか比較する
func typeof2(v interface{}) {
    fmt.Println(reflect.TypeOf(v).Kind() == reflect.Int)
}
go run intro1/main.go
----typeof-----
int
string
bool
----typeof2-----
true

A call to ValueOf returns a Value representing the run-time data. Zero takes a Type and returns a Value representing a zero value for that type.

ValueOfを呼び出すと、実行時データを表すValueが返されます。 ZeroはTypeを取り、その型のゼロ値を表すValueを返します。

package main

import (
    "fmt"
    "reflect"
)

func main() {
    fmt.Println("----valueof-----")
    valueof(1, "str", false)
    fmt.Println("----valueof2-----")
    valueof2(100)
    fmt.Println("----valueof3-----")
    valueof3()
}

// vからValueOfでポインタにアクセスして、Elemでポインタにある値を返す
func valueof(value ...interface{}) {
    for _, v := range value {
        fmt.Println(reflect.ValueOf(&v).Elem())
    }
}

// valueに格納されている値がint型と適合したら、その値をansに格納する
func valueof2(value interface{}) {
    var ans int
    v := reflect.ValueOf(&value).Elem()
    if intValue, ok := v.Interface().(int); ok {
        ans += intValue
        fmt.Println(ans)
    }
}

// int型のゼロ値を取得し表示する
func valueof3() {
    var value int
    fmt.Println(reflect.ValueOf(&value).Elem())
}
go run intro2/main.go
----valueof-----
1
str
false
----valueof2-----
100
----valueof3-----
0

See “The Laws of Reflection” for an introduction to reflection in Go: https://golang.org/doc/articles/laws_of_reflection.html

Goでのreflectionの概要については、「The Laws of Reflection」を参照してください。https://golang.org/doc/articles/laws_of_reflection.html

リフレクションの法則

The Laws of Reflection

Reflection in computing is the ability of a program to examine its own structure, particularly through types; it’s a form of metaprogramming. It’s also a great source of confusion.

コンピューティングにおけるリフレクションとは、プログラムが自分の構造、特に型を調べる能力です。 それはメタプログラミングの一種です。 それはまた混乱の大きな原因です。

In this article we attempt to clarify things by explaining how reflection works in Go. Each language’s reflection model is different (and many languages don’t support it at all), but this article is about Go, so for the rest of this article the word “reflection” should be taken to mean “reflection in Go”.

この記事では、Goでreflectionがどのように機能するかを説明して、物事を明確にしようとしています。 各言語のreflection modelは異なっていますが(そして多くの言語ではそれをサポートしていません)。これはGoについての記事なので、「reflection」という言葉は「Goのreflection」を意味すると解釈されるべきです

前書き

Introduction

Because reflection builds on the type system, let’s start with a refresher about types in Go.

reflectionはシステム上に構築されるため、Goのタイプについての再考から始めましょう。

Go is statically typed. Every variable has a static type, that is, exactly one type known and fixed at compile time: int, float32, *MyType, byte, and so on. If we declare

Goは静的に型付けされています。 すべての変数は静的型を持ちます。つまり、int、float32、* MyType、 byteなど、コンパイル時に既知で固定された1つの型だけです。
もし、変数宣言をしたら以下のようになります。

type MyInt int

var i int
var j MyInt

then i has type int and j has type MyInt. The variables i and j have distinct static types and, although they have the same underlying type, they cannot be assigned to one another without a conversion.

MyIntはint型を持ち、jはMyInt型を持っています。 変数iとjには別個の静的型があり、それらは同じ基底型を持ちますが、変換なしでは互いに割り当てることはできません。

i = j // 同じ基底クラスのintをもっていても代入出来ない。

One important category of type is interface types, which represent fixed sets of methods. An interface variable can store any concrete (non-interface) value as long as that value implements the interface’s methods. A well-known pair of examples is io.Reader and io.Writer, the types Reader and Writer from the io package:

typeの重要なカテゴリの1つは、固定されたメソッドセットを表すinterface typesです。 interface変数は、その値がinterfaceのメソッドを実装している限り、任意の具体的な(非interface)値を格納できます。
よく知られた例のペアは、io.Readerとio.Writerです。これは、ioパッケージのReaderとWriterタイプです。interfaceについては、Javaなどにあるものと同じような挙動をします。

// Readerは、基本的なReadメソッドをラップするinterfaceです。
type Reader interface {
    Read(p []byte) (n int, err error)
}

// Writerは、基本的なWriteメソッドをラップするinterfaceです。
type Writer interface {
    Write(p []byte) (n int, err error)
}

Any type that implements a Read (or Write) method with this signature is said to implement io.Reader (or io.Writer). For the purposes of this discussion, that means that a variable of type io.Reader can hold any value whose type has a Read method:

このシグネチャでRead(またはWrite)メソッドを実装するすべての型は、io.Reader(またはio.Writer)を実装すると言われています。 ここでは、io.Reader型の変数に、その型がReadメソッドを持つ値を保持できることを示します。

var r io.Reader
r = os.Stdin
r = bufio.NewReader(r)
r = new(bytes.Buffer)
// and so on

It’s important to be clear that whatever concrete value r may hold, r’s type is always io.Reader: Go is statically typed and the static type of r is io.Reader.

どのような具体的な値rが保持されていても、rの型は常にio.Readerです:Goは静的に型指定され、静的型はio.Readerです。

An extremely important example of an interface type is the empty interface:

インターフェイスタイプの非常に重要な例は、空のインターフェイスです。

interface{}

It represents the empty set of methods and is satisfied by any value at all, since any value has zero or more methods.

これは、空のメソッドセットを表し、任意の値が0以上のメソッドを持つため、すべての値がすべて満たされます。

Some people say that Go’s interfaces are dynamically typed, but that is misleading. They are statically typed: a variable of interface type always has the same static type, and even though at run time the value stored in the interface variable may change type, that value will always satisfy the interface.

一部の人々は、Goのinterfaceは動的に型付けされていると言いますが、それは誤解を招くものです。 それらは静的に型付けされています:interface型の変数は常に同じ静的型を持ち、実行時にinterface変数に格納された値が型を変更しても、その値は常にinterfaceを満たします。

We need to be precise about all this because reflection and interfaces are closely related.

reflectionとinterfacesは密接に関連しているため、すべてのことについて正確にする必要があります。

インタフェースの表現

The representation of an interface

Russ Cox has written a detailed blog post about the representation of interface values in Go. It’s not necessary to repeat the full story here, but a simplified summary is in order.

Russ Coxは、Goにinterfaceの値を表現するための詳細なブログ記事を書いています。 ここでは話を繰り返す必要はないですが、簡略な要約が必要です。

A variable of interface type stores a pair: the concrete value assigned to the variable, and that value’s type descriptor. To be more precise, the value is the underlying concrete data item that implements the interface and the type describes the full type of that item. For instance, after

interface typeの変数は、変数に割り当てられた具体的な値と、その値のタイプ記述子のペアを格納します。 より正確に言えば、値はinterfaceを実装する基礎となる具体的なデータ項目であり、タイプはその項目のフルタイプを表します。

例えば

var r io.Reader
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
    return nil, err
}
r = tty

r contains, schematically, the (value, type) pair, (tty, os.File). Notice that the type os.File implements methods other than Read; even though the interface value provides access only to the Read method, the value inside carries all the type information about that value. That’s why we can do things like this:

rには (value, type) の対(tty, os.File)が概略的に含まれています。 os.File型はRead以外のメソッドを実装していることに注意してください。 interface値がReadメソッドへのアクセスのみを提供しても、内部の値はその値に関するすべての型情報を保持します。 だから私たちはこのようなことをすることができます。

var w io.Writer
w = r.(io.Writer)

The expression in this assignment is a type assertion; what it asserts is that the item inside r also implements io.Writer, and so we can assign it to w. After the assignment, w will contain the pair (tty, *os.File). That’s the same pair as was held in r. The static type of the interface determines what methods may be invoked with an interface variable, even though the concrete value inside may have a larger set of methods.

この代入の式は型アサーションです。 それが主張するのは、rの中のアイテムもio.Writerを実装しているので、wに割り当てることができるということです。 代入の後、wにはペア(tty, *os.File)が含まれます。 それはrと同じペアです。 インタフェースの静的型は、内部の具体的な値がより大きな一連のメソッドを持つ場合でも、インタフェース変数で呼び出されるメソッドを決定します。

Continuing, we can do this:

続けて、これを行うことが出来ます。

var empty interface{}
empty = w

and our empty interface value empty will again contain that same pair, (tty, *os.File). That’s handy: an empty interface can hold any value and contains all the information we could ever need about that value.

空のinterfaceの空の値には、同じペア (tty, *os.File)が再び含まれます。 それは便利です:空のinterfaceは、任意の値を保持することができ、我々がその値について必要とする可能性のあるすべての情報を含みます。

(We don’t need a type assertion here because it’s known statically that w satisfies the empty interface. In the example where we moved a value from a Reader to a Writer, we needed to be explicit and use a type assertion because Writer’s methods are not a subset of Reader’s.)

ここでは、wが空のinterfaceを満たしていることが静的にわかっているため、タイプアサーションは必要ありません。ReaderからWriterに値を移動した例では、明示的に型アサーションを使用する必要がありました。 Readerのサブセットではありません)。

One important detail is that the pair inside an interface always has the form (value, concrete type) and cannot have the form (value, interface type). Interfaces do not hold interface values.

1つの重要な詳細は、interface内のペアは常にフォーム(値、具体的なタイプ)を持ち、フォーム(値、interface型)を持つことができないということです。interfaceはinterface値を保持しません。

Now we’re ready to reflect.

今我々は反映する準備が整いました。

reflectionの第1の法則

The first law of reflection

1.Reflectionは、interface値からreflection objectに向かう

  1. Reflection goes from interface value to reflection object.

At the basic level, reflection is just a mechanism to examine the type and value pair stored inside an interface variable. To get started, there are two types we need to know about in package reflect: Type and Value. Those two types give access to the contents of an interface variable, and two simple functions, called reflect.TypeOf and reflect.ValueOf, retrieve reflect.Type and reflect.Value pieces out of an interface value. (Also, from the reflect.Value it’s easy to get to the reflect.Type, but let’s keep the Value and Type concepts separate for now.)

基本レベルでは、reflectionはinterface変数の内部に格納されている型と値のペアを調べるメカニズムに過ぎません。 始めるには、パッケージreflectに反映させるためにTypeValueの2種類が必要です。 これらの2つの型は、interface変数の内容にアクセスできます。また、reflect.TypeOfおよびreflect.ValueOfという2つの単純な関数は、reflect.Typeとreflectを取得します。 (また、reflect.Valueからreflect.Typeに到達するのは簡単ですが、ValueとTypeのコンセプトを今のところ分けておきましょう。)

Let’s start with TypeOf:

TypeOfから始めましょう。

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x float64 = 3.4
    fmt.Println("type:", reflect.TypeOf(x))
}

This program prints

このプログラムをプリントすると

type: float64

You might be wondering where the interface is here, since the program looks like it’s passing the float64 variable x, not an interface value, to reflect.TypeOf. But it’s there; as godoc reports, the signature of reflect.TypeOf includes an empty interface:

interfaceの値ではなくfloat64変数xを渡しているように見えるので、interfaceがどこにあるのか疑問に思うかもしれません。 しかしそれはreflect.TypeOfにあります。 godocレポートとして、reflect.TypeOfのシグネチャには空のinterfaceが含まれています。

// TypeOfは、インタフェース{}内の値のreflection Typeを返します。
func TypeOf(i interface{}) Type

When we call reflect.TypeOf(x), x is first stored in an empty interface, which is then passed as the argument; reflect.TypeOf unpacks that empty interface to recover the type information.

reflect.TypeOf(x)を呼び出すと、xはまず空のinterfaceに格納され、引数として渡されます。 型情報を復元するために空のinterfaceを展開します。

The reflect.ValueOf function, of course, recovers the value (from here on we’ll elide the boilerplate and focus just on the executable code):

もちろんreflect.ValueOf関数は値を復元します(ここからは、ボイラープレートを削除し、実行可能コードだけに焦点を当てます)。

var x float64 = 3.4
fmt.Println("value:", reflect.ValueOf(x).String())

prints

value: <float64 Value>

(We call the String method explicitly because by default the fmt package digs into a reflect.Value to show the concrete value inside. The String method does not.)

(デフォルトでは、fmtパッケージはreflect.Valueを掘り下げて具体的な値を内部に表示するため、Stringメソッドは明示的に呼び出します。Stringメソッドはそうではありません)。 ちなみに、これをStringなしで実行すると

var x float64 = 3.4
fmt.Println("value:", reflect.ValueOf(x))
value: 3.4

Both reflect.Type and reflect.Value have lots of methods to let us examine and manipulate them. One important example is that Value has a Type method that returns the Type of a reflect.Value. Another is that both Type and Value have a Kind method that returns a constant indicating what sort of item is stored: Uint, Float64, Slice, and so on. Also methods on Value with names like Int and Float let us grab values (as int64 and float64) stored inside:

どちらも反映されます。 reflect.Typeとreflect.Valueには、それらを調べて操作するための方法がたくさんあります。 1つの重要な例として、ValueはTypeはreflect.ValueのTypeを返すメソッド があります。 もう一つは、TypeとValueの両方に、どの種類のアイテムが格納されているかを示す定数(Uint、Float64、Sliceなど)を返すKindメソッドがあることです。 また、IntやFloatのような名前を持つValueのメソッドでは、内部に格納されている値(int64とfloat64など)を取得できます。

var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
fmt.Println("value:", v.Float())

prints

type: float64
kind is float64: true
value: 3.4

There are also methods like SetInt and SetFloat but to use them we need to understand settability, the subject of the third law of reflection, discussed below.

SetIntやSetFloatのようなメソッドもありますが、それらを使用するには、後述する第3回reflectionの主題である設定可能性を理解する必要があります。

The reflection library has a couple of properties worth singling out. First, to keep the API simple, the “getter” and “setter” methods of Value operate on the largest type that can hold the value: int64 for all the signed integers, for instance. That is, the Int method of Value returns an int64 and the SetInt value takes an int64; it may be necessary to convert to the actual type involved:

reflectionライブラリには、注目に値するいくつかのプロパティがあります。 まず、APIを単純なものにするために、Valueのgetterメソッドとsetterメソッドは、値を保持できる最大の型、たとえば、すべての符号付き整数に対してint64で動作します。 つまり、ValueのIntメソッドはint64を返し、SetInt値はint64を返します。 関係する実際のタイプに変換する必要があるかもしれません:

var x uint8 = 'x'
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())                            // uint8.
fmt.Println("kind is uint8: ", v.Kind() == reflect.Uint8) // true.
x = uint8(v.Uint())                                       // v.Uint returns a uint64.

The second property is that the Kind of a reflection object describes the underlying type, not the static type. If a reflection object contains a value of a user-defined integer type, as in

2番目のプロパティは、reflection objectの種類が静的型ではなく基底型を記述していることです。 reflection objectにユーザ定義の整数型の値が含まれている場合

type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)

the Kind of v is still reflect.Int, even though the static type of x is MyInt, not int. In other words, the Kind cannot discriminate an int from a MyInt even though the Type can.

静的な型のxはintではなくMyIntであるにもかかわらず、vの種類はまだ reflect.Intです。 言い換えれば、種類はできますが、KindはMyIntからintを区別できません。

reflectionの第2の法則

The second law of reflection

Reflectionはreflection objectからinterfaceの値に向かう

  1. Reflection goes from reflection object to interface value.

Like physical reflection, reflection in Go generates its own inverse.

物理的な反射のように、Goでのreflectionはそれ自身の逆を生成します。

Given a reflect.Value we can recover an interface value using the Interface method; in effect the method packs the type and value information back into an interface representation and returns the result:

与えられたreflect.Valueは、Interfaceメソッドを使用してInterface値を復元できます。 実際にはこのメソッドは型と値の情報をInterface表現にパックして返します。

// Interfaceはvの値をinterface{}として返します。
func (v Value) Interface() interface{}

As a consequence we can say

結果として、我々は言うことができる

y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)

to print the float64 value represented by the reflection object v.

reflection object vによって表されるfloat64値を出力する。

We can do even better, though. The arguments to fmt.Println, fmt.Printf and so on are all passed as empty interface values, which are then unpacked by the fmt package internally just as we have been doing in the previous examples. Therefore all it takes to print the contents of a reflect.Value correctly is to pass the result of the Interface method to the formatted print routine:

しかし、私たちはもっと良くすることができます。 fmt.Println、fmt.Printfなどの引数は、すべて空のinterface値として渡され、前の例で行ったように内部的にfmtパッケージによってアンパックされます。 したがって、reflect.Valueの内容を出力するには、Interfaceメソッドの結果を書式付きprintルーチンに渡すだけです。

fmt.Println(v.Interface())

(Why not fmt.Println(v)? Because v is a reflect.Value; we want the concrete value it holds.) Since our value is a float64, we can even use a floating-point format if we want:

(なぜfmt.Println(v)なのか?vはreflect.Valueなので、具体的な値が必要です。)値がfloat64なので、必要ならば浮動小数点フォーマットを使用することもできます:

fmt.Printf("value is %7.1e\n", v.Interface())

and get in this case

この場合

3.4e+00

Again, there’s no need to type-assert the result of v.Interface() to float64; the empty interface value has the concrete value’s type information inside and Printf will recover it.

ここでも、v.Interface()の結果をfloat64にタイプアサートする必要はありません。 空のinterfaceの値は具体的な値の型情報を内部に持ち、Printfはそれを復元します。

In short, the Interface method is the inverse of the ValueOf function, except that its result is always of static type interface{}.

要するに、InterfaceメソッドはValueOf関数の逆ですが、その結果は常に静的型interface{}である点が異なります。

Reiterating: Reflection goes from interface values to reflection objects and back again.

繰り返します:Reflectionはinterface値からreflection objectsに戻り、再び戻る。

reflectionの第3の法則

The third law of reflection

3.reflection objectを変更するには、その値を設定可能にする必要があります。

  1. To modify a reflection object, the value must be settable.

The third law is the most subtle and confusing, but it’s easy enough to understand if we start from first principles.

第3の法則は最も微妙で混乱しますが、しかし、最初の原則から始めたら理解することは簡単です。

Here is some code that does not work, but is worth studying.

ここで動作しないコードがありますが、勉強する価値があります。

var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // Error: will panic.

If you run this code, it will panic with the cryptic message

このコードを実行すると、謎のメッセージでパニックに陥ります

panic: reflect.Value.SetFloat using unaddressable value
reflect.Value.Setfloatをアドレス指定が不可能な値を使用した

The problem is not that the value 7.1 is not addressable; it’s that v is not settable. Settability is a property of a reflection Value, and not all reflection Values have it.

問題は、値7.1がアドレスが指定可能ではないということではありません。 vは設定できません。 設定可能性は、reflection Valueの特性であり、すべてのreflection Valuesがそれを有するわけではない。

The CanSet method of Value reports the settability of a Value; in our case,

ValueのCanSetメソッドは、Valueの設定可能性を報告します。 私達の場合。

var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("settability of v:", v.CanSet())

prints

settability of v: false

It is an error to call a Set method on an non-settable Value. But what is settability?

設定できない値に対してSetメソッドを呼び出すのはエラーです。 では、設定可能性とは何ですか?

Settability is a bit like addressability, but stricter. It’s the property that a reflection object can modify the actual storage that was used to create the reflection object. Settability is determined by whether the reflection object holds the original item. When we say

設定可能性は、アドレス可能性のようなものですが、より厳しいものです。 reflection objectは作成に使用された実際のストレージを変更することができるプロパティです。 設定可能性は、reflection objectが元のアイテムを保持するかどうかによって決まります。 私たちが言うとき

var x float64 = 3.4
v := reflect.ValueOf(x)

we pass a copy of x to reflect.ValueOf, so the interface value created as the argument to reflect.ValueOf is a copy of x, not x itself. Thus, if the statement

xのコピーを渡します reflect.ValueOf、したがって、reflect.ValueOfへの引数として作成されたinterfaceの値は、x自身ではなくxのコピーです。 したがって

v.SetFloat(7.1)

were allowed to succeed, it would not update x, even though v looks like it was created from x. Instead, it would update the copy of x stored inside the reflection value and x itself would be unaffected. That would be confusing and useless, so it is illegal, and settability is the property used to avoid this issue.

たとえそれがxから作成されたように見えるとしても、xは更新されないでしょう。 代わりに、それはreflection valueの内部に格納されたxのコピーを更新し、x自体は影響を受けません。 このような操作は、混乱を生むだけで役に立ちません。設定可能性はこの問題を回避するために使用されるプロパティです。

If this seems bizarre, it’s not. It’s actually a familiar situation in unusual garb. Think of passing x to a function:

これが奇妙に思われるかもしれませんが、そうではありません。 実際には普通ではない服装ではおなじみの状況です。では、 xを関数に渡すことを考えてみましょう:

f(x)

We would not expect f to be able to modify x because we passed a copy of x’s value, not x itself. If we want f to modify x directly we must pass our function the address of x (that is, a pointer to x):

私たちは、x自身の値ではなく、xの値のコピーを渡したので、fでxを変更できるとは思わないでしょう。fでxを直接変更したい場合は、関数xのアドレス(xのポインタ)を渡す必要があります。

f(&x)

This is straightforward and familiar, and reflection works the same way. If we want to modify x by reflection, we must give the reflection library a pointer to the value we want to modify.

こういったことは、簡単でよく知られていることで、reflectionも同じように機能します。 reflectionでxを変更する場合は、reflectionライブラリに変更したい値へのポインタを与える必要があります。

Let’s do that. First we initialize x as usual and then create a reflection value that points to it, called p.

やってみましょう。 最初にxを通常どおりに初期化し、それを指すreflection 値のpを作成します。

var x float64 = 3.4
p := reflect.ValueOf(&x) // Note: take the address of x.
fmt.Println("type of p:", p.Type())
fmt.Println("settability of p:", p.CanSet())

The output so far is

これまでの出力は

type of p: *float64
settability of p: false

The reflection object p isn’t settable, but it’s not p we want to set, it’s (in effect) *p. To get to what p points to, we call the Elem method of Value, which indirects through the pointer, and save the result in a reflection Value called v:

reflection objectのpは設定できませんが、設定したいpではありません。実際には*pです。 pが何を指しているかを知るために、ポインタを介して間接的に行われるValueのElemメソッドを呼び出して、その結果をvと呼ばれるreflection Valueに保存する。

v := p.Elem()
fmt.Println("settability of v:", v.CanSet())

Now v is a settable reflection object, as the output demonstrates,

出力が示す通り、vは設定可能なreflection objectです。

settability of v: true

and since it represents x, we are finally able to use v.SetFloat to modify the value of x:

vはxを表すので、最終的にv.SetFloatを使ってxの値を変更することができます:

v.SetFloat(7.1)
fmt.Println(v.Interface())
fmt.Println(x)

The output, as expected, is

出力は、期待どおりです。

7.1
7.1

Reflection can be hard to understand but it’s doing exactly what the language does, albeit through reflection Types and Values that can disguise what’s going on. Just keep in mind that reflection Values need the address of something in order to modify what they represent.

Reflectionは理解するのが難しいかもしれませんが、何が起こっているのかを隠すことができるreflectionのTypesとValuesにもかかわらず、言葉の意味を正確にしています。 reflectionには、表現するものを変更するために、何かのアドレスが必要です。

構造体

Structs

In our previous example v wasn’t a pointer itself, it was just derived from one. A common way for this situation to arise is when using reflection to modify the fields of a structure. As long as we have the address of the structure, we can modify its fields.

前の例では、vはポインタそのものではなく、単にポインタから導出されたものです。 この状況が発生する一般的な方法は、reflectionを使用して構造のフィールドを変更する場合です。 構造体のアドレスがあれば、そのフィールドを変更することができます。

Here’s a simple example that analyzes a struct value, t. We create the reflection object with the address of the struct because we’ll want to modify it later. Then we set typeOfT to its type and iterate over the fields using straightforward method calls (see package reflect for details). Note that we extract the names of the fields from the struct type, but the fields themselves are regular reflect.Value objects.

構造体の値tを解析する簡単な例を次に示します。 構造体のアドレスを使ってリフレクションオブジェクトを作成します。後で変更する必要があるからです。 次に、typeOfTをその型に設定し、簡単なメソッド呼び出しを使用してフィールドを反復処理します(詳細はパッケージを参照)。 struct型からフィールドの名前を抽出しますが、フィールド自体は通常のreflect.Valueオブジェクトです。

type T struct {
    A int
    B string
}
t := T{23, "skidoo"}
s := reflect.ValueOf(&t).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField(); i++ {
    f := s.Field(i)
    fmt.Printf("%d: %s %s = %v\n", i,
        typeOfT.Field(i).Name, f.Type(), f.Interface())
}

The output of this program is

このプログラムの出力は

0: A int = 23
1: B string = skidoo

There’s one more point about settability introduced in passing here: the field names of T are upper case (exported) because only exported fields of a struct are settable.

ここではsettabilityについてもう一度説明します。Tのフィールド名は、構造体のエクスポートされたフィールドのみが設定可能であるため、Tのフィールド名は大文字(エクスポートされます)です。

Because s contains a settable reflection object, we can modify the fields of the structure.

sには設定可能なreflection objectが含まれているため、構造のフィールドを変更できます。

s.Field(0).SetInt(77)
s.Field(1).SetString("Sunset Strip")
fmt.Println("t is now", t)

And here’s the result:

そして結果は次のとおりです。

t is now {77 Sunset Strip}

If we modified the program so that s was created from t, not &t, the calls to SetInt and SetString would fail as the fields of t would not be settable.

&tではなくtからsを作成するようにプログラムを修正した場合、SetIntとSetStringの呼び出しは失敗し、tのフィールドは設定できません。

結論

Conclusion

Here again are the laws of reflection:

反射の法則もここにあります。

  • Reflection goes from interface value to reflection object.
  • Reflection goes from reflection object to interface value.
  • To modify a reflection object, the value must be settable.
  • Once you understand these laws reflection in Go becomes much easier to use, although it remains subtle. It’s a –
  • powerful tool that should be used with care and avoided unless strictly necessary.
  • Reflectionは、interface値から反射オブジェクトに向かう。
  • Reflectionは、reflection objectからinterface値に向かいます。
  • reflection objectを変更するには、その値を設定可能にする必要があります。
  • これらの法律を理解すれば、Goでの反映はずっと使いやすくなりますが、微妙なままです。 どうしても必要な場合を除いて使用し、出来れば避けるべき強力なツールです。

感想

勉強のために翻訳しましたが、思ったより分量多くて辛かった。

Cloud Datastoreをざっくり理解する

スケーラビリティの高い NoSQL データベース

f:id:tikasan0804:20170715202352p:plain

いま友人と開発しているプロダクトで、本格的にDatastoreを使った開発をすることになったので、概念を理解するためのメモ記事です。

cloud.google.com

RDBから理解するDatastore概念

概念 Datastore RDB
オブジェクトのカテゴリ Kind Table
1つのオブジェクト Entity Row
1つのブジェクとの各データ Property Field
オブジェクトに対するユニークなID Key Primary Key

これらを分かりやすい説明をしてくれていたものがあったので、引用させて頂きます。

Kindと呼ばれるテーブルみたいなものに
Entityと呼ばれるオブジェクトを格納できます。
Entityには一意のKeyが割り当てられています。
EntityのフィールドはPropertyといいます。

つまり、Kind -> Entity -> Propertyという親子関係のようです。

GAE/GO Cloud Datastoreを使ってみる | teppeeeのブログ

次に実行されるメソッドの種類について

動作 Datastore RDB
取得 Get, GetAll SELECT
追加 Put INSERT
更新 Put UPDATE
削除 Delete DELETE

基本的なCRUDは当然出来ます。ただ、Readに関しては読み取るだけなら問題はないですが、複雑な検索はRDBに比べると非力なので、Search APIを使って検索したりすることが一般的なようです。

Datastoreのデータ整理

cloudplatform-jp.googleblog.com

上記の記事が非常に分かりやすかったので、引用しながら理解していこうと思います。

Google Cloud Datastore のような非リレーショナル データベースにおけるデータのモデリングや保存には、固有の難しさがあります。結合や正規化など、リレーショナル データベースの有益な機能の多くは、非リレーショナル データについては、スケーラビリティに欠けるという理由で適用されません。リレーショナル データベースを「オブジェクトと関係」としてとらえるという一般的なアプローチも、非リレーショナル データベースに当てはめるのは困難です。

DatastoreはRDBの代わりにはならない。同じ考えでやることは困難のようです。

具体例:マルチユーザーブログ

RDBでのモデリング

User

Id username name
1 tonystark Tony Stark
2 dianaprince Diana Prince

Post

Id user_id content
1 1 Hello, world!
2 2 Another post

特定ユーザーの検索クエリ
user_idが1のユーザーの投稿で検索する
SELECT * FROM Post WHERE user_id = 1

Datastoreのモデリング

Key Data
(Post, 1) {“user”: Key(User, tonystark), “content”: “Hello, World!”}
(Post, 2) {“user”: Key(User, dianaprince), “content”: “Another post”}
(User, tonystark) {“name”: “Tony Stark”}
(User, dianaprince) {“name”: “Diana Prince”}

Entityが特定のKindを持っている構造になります。今回の例だと、(Post, 1) PostがKindに当たります。RDBでいうところの、Rowがそれぞれ特定のTableを持っているという構造になります。

では、Post Kindでusernameをフィルタリングすると以下のようなクエリになります。
tonystarkでフィルダリングする例
datastore.Query(kind='Post', filters=[('user', '=', Key('User', tonystark))])

上記のようなグローバルクエリをDatastoreで実行すると、結果整合性を持つことになります。

結果整合性とは

NoSQLでよく登場する性質で、「データの何らかの変更は最終的には全体に適用される」というものです。変更の定義は、追加や削除、更新を総称しているものとします。これはどういうことかと言うと、様々なユーザーがリソースに対して操作を行ったりします。場合によっては、作業が衝突して問題が起きそうですが、これは最後に行った更新を適用するようにしていて、結果的には問題ないとするものです。
つまり、様々なCRUDの操作があったとして、

時間 操作
12:10 ☆更新
12:12 ◯更新
12:09 △更新

上記のような操作のログデータが集約された時に、最終的に適用されるのは、最終更新時間である「◯更新」が正しいとします。なので、基本的にひたすらInsertをしていくということになります。(帳簿的な感じ?)
RDBにおいては厳密な一貫性を重視しているということから、性質上全く違うということがここから分かります。

ちなみに、Datastoreでは、データ整理方法に応じて強整合性と結果整合性のどちらかを選択出来ます。

強い整合性

強い整合性は、先程の結果整合性と処理の流れそのものは同じですが、データに対してアクセス出来るタイミングが全く異なります。分散させたストアにそれぞれ適用が完了してから、ロックを解除します。これらのバランスや性質については公式ドキュメントが非常に分かりやすくまとめてくれているので、参照してみてください。

cloud.google.com

KindやKeyの性質を理解する

先程紹介した記事には以下のように書かれています。

カインドをテーブルと、キー名をプライマリ キーと考えたくなるかもしれません。しかし、キーは祖先を持つことができ、そのためにキーパスが存在します。非リレーショナル データをテーブルやキーの観点からとらえるのではなく、ファイル システムとして考えてみましょう。

ファイルシステムとして考える???

対象

Key Data
(Post, 1) {“user”: Key(User, tonystark), “content”: “Hello, World!”}
(Post, 2) {“user”: Key(User, dianaprince), “content”: “Another post”}
(User, tonystark) {“name”: “Tony Stark”}
(User, dianaprince) {“name”: “Diana Prince”}

ファイルシステムに置き換える

/1.post
/2.post
/tonystark.user
/dianaprince.user

ユーザー別にグループ化する

/tonystark.user
  /1.post
/dianaprince.user
  /2.post

最初の投稿パスは、/tonystark.user/1.postとなります。つまり、以下のように整理されています。

Key(ファイルパス) Data(ファイル)
(User, tonystark) {“name”: “Tony Stark”}
(User, tonystark, Post, 1) {“content”: “Hello, World!”}
(User, dianaprince) {“name”: “Diana Prince”}
(User, dianaprince, Post, 2) {“content”: “Another post”}

投稿をユーザー別に整理すると、エンティティ グループが作成されます。その中にはユーザーのプロフィールとすべての投稿が含まれます。Cloud Datastore では、1つのエンティティ グループに対するクエリは強い整合性を持ちます。このため、ユーザーは投稿を作成すると、すぐに見ることができます。祖先をキーに指定してクエリを行うことも可能です。

datastore.Query(kind='Post', ancestor=Key('User', username))

このようなパターンの場合、強い整合性を持つとあります。つまり、その分のトレードオフが発生することになります。Datastoreでは、各エンティティグループには、約1秒間に1回しか更新できません。その代わり、全ての読み取りが強い整合性を持ちます。ここでの更新はCRUD全般を指します。 ※1秒間に1回というのは、各エンティティグループにのみ適用されるルールで、別エンティティグループなら同時操作を可能としています。

この設計の場合、全てのユーザがアップロードした投稿を返すクエリは結果整合性を持つようになります。

datastore.Query(kind='Post')

つまり、以下のようになります。

クエリ 性質
全ての投稿を取得 結果整合性
自分の投稿を取得 強い整合性

自分の投稿だけを見る分にはすぐ確認できますが、投稿が全体に公開されるフィードなどにはすぐ更新されませんということだと思います。ここまでの説明で分かる通り、結果整合性と強い整合性は全く違う性質を持っているので、使い所をしっかり判断することが大事だと考えられます。

具体例:Wiki

ファイル パスのメタファーを使って、シンプルな Wikiモデリングすることもできます。Wiki では、ページを保存するたびに新しいリビジョンが作成されます。ユーザーは任意のリビジョンからページをリストアできます。 このデータをファイル システムとして表現すると、次のようになります。
この構造は、各ページのすべてのリビジョンを別々のエンティティ グループに保存します。

/home.page
  / current.revision
  / 05-29-2015-10-30-27.revision
  / 05-20-2015-06-33-11.revision

/another.page
  / current.revision
  / 04-10-2015-11-23-10.revision

データの操作の流れは以下の通りです。

現在のページデータ(current.revision)を新しいリビジョンにコピーし、current.revisionを新しいコンテンツで上書きします。Datastoreにあるトランザクションを利用するとこういった複数回の処理を、整合性を保つことが出来ます。つまり、成功すれば適用し、失敗すればロールバックしてくれるということです(すごい)

このトランザクション処理は、25のエンティティグループにまたがって実行することが出来ます。ですが、このトランザクションは範囲が多ければ多いほど、失敗の確率が上がるので注意が必要そうです。

これら関連するリビジョンをリストで取得することが、祖先キーを指定することで可能となっています。

datastore.Query(kind='revision', ancestor=Key('page', home))

リビジョンの更新はほとんど同じで、新しく投稿されたコンテンツを使うのではなく、current.revisionを更新することで実現出来ます。

まとめ

記事には以下のようにまとめられていました。

  • ページは 1 秒間に 1 回まで更新できる。
  • ページ上のクエリとそのリビジョンは強い整合性を持つ。
  • 保存操作では、強い整合性を持つクエリが使用されるため、ページの保存やリビジョンのリストアは、トランザクションとして実行できる。
  • ページ数が膨大でも、ページの読み書きは高速。

これは理解するためには、まずは使ってみて、経験を積むことが大事な気がしますね。なんか作ったらまとめてみようと思います。

goaのデザインコードを分割する

f:id:tikasan0804:20170505212036p:plain

Golangのgoaの勉強に役立つ情報まとめ - ぺい
goaの情報をもっと見たい方は、上のリンクから確認してください

肥大化しがちなDSLコードを分割する

goaの開発フローは、以下のような感じです。

  1. DSLを作成する
  2. コントローラー作成
  3. 追加仕様または修正でDSLをごにょる

上記のようなことをしていたら、結構DSLが肥大化します。そこで、DSLを少し工夫することで分割することが可能です。これをすると以下のような構成に出来るので、困ってる人は実践してみてください。

├── Makefile
├── README.md
├── app
├── client
├── controllers
│   ├── hello.go
│   └── sample.go
├── design
│   ├── api_definition.go
│   ├── media
│   │   ├── hello.go
│   │   └── sample.go
│   └── resources
│       ├── hello.go
│       └── sample.go
└── main.go

ソース

github.com

まだ、PR出している最中ですが、上記のコードがその具体例になります。

goaのGoglandスニペットを活用しよう

f:id:tikasan0804:20170505212036p:plain

Golangのgoaの勉強に役立つ情報まとめ - ぺい
goaの情報をもっと見たい方は、上のリンクから確認してください

DSLを楽ちんにするスニペットを活用する

goaのDSL書くの面倒ですよね!? Gogland用のgoaのDSLを書くためのスニペット作成しました。

github.com

この発想はkawakenさんの以下の記事の影響されて作ったものです。(goa studyにて)

kawaken.hateblo.jp

イデア求む

Goglandでスニペットをコードベースで管理したいんですけど、何かいい方法ないですかね。