2020年9月7日月曜日

interface of go, laws of reflection by Rob Pike, import ./ ....

package main

import ( "fmt"  "./intset"  )  

func main() {

  var x , y intset.IntSet 

// ここでintsetを指定しており、以下ではinstset.AddでなくAddとかける

  x.Add(1)

  y.Add(2)

  x.UnionWith(&y)

  fmt.Println(x.String())

  }

----------------------------------------------------------------------------------------

How to use interfaces in Go

Before I started programming Go, I was doing most of my work with Python. 

As a Python programmer, I found that learning to use interfaces in Go 

was extremely difficult. That is, the basics were easy, and I knew how to use 

the interfaces in the standard library, but it took some practice 

before I knew how to design my own interfaces.  

In this post, I’ll discuss Go’s type system in an effort to explain 

how to use interfaces effectively.

Goのプログラミングを始める前は、ほとんどの作業をPythonで行っていました。 

Pythonプログラマーとして、Goでインターフェースの使い方を学ぶのは非常に難しいことに気づきました。

つまり、基本は簡単で、標準ライブラリのインターフェイスの使い方は知っていましたが、

独自のインターフェイスを設計する方法を知るまでには、ある程度の練習が必要でした。

この投稿では、インターフェースを効果的に使用する方法を説明するために、

Goの型システムについて説明します。


Introduction to interfaces

So what is an interface? An interface is two things: it is a set of methods, 

but it is also a type. Let’s focus on the method set aspect of interfaces first.

では、インターフェースとは何ですか?インターフェイスは2つのものです。

それはメソッドのセットですが、タイプでもあります。

まず、インターフェースのメソッドセットの側面に焦点を当てましょう。


Typically, we’re introduced to interfaces with some contrived example.

 Let’s go with the contrived example of writing some application 

where you’re defining Animal datatypes, because that’s a totally 

realistic situation that happens all the time. 

The Animal type will be an interface, and we’ll define an Animal 

as being anything that can speak. This is a core concept in Go’s type system; 

instead of designing our abstractions in terms of what kind of 

data our types can hold, we design our abstractions in terms of 

what actions our types can execute.

通常、いくつかの工夫された例を使用してインターフェースを紹介します。

動物のデータ型を定義するアプリケーションを作成するという不自然な例を見てみましょう。

これは、常に発生する完全に現実的な状況だからです。

動物の種類はインターフェースになり、動物は話すことができるものとして定義します。

これは、Goの型システムのコアコンセプトです。タイプが保持できるデータの種類の

観点から抽象化を設計するのではなく、タイプが実行できるアクションの観点から抽象化を設計します。


We start by defining our Animal interface:


type Animal interface {

    Speak() string

}


pretty simple: we define an Animal as being any type that has a method named Speak.

The Speak method takes no arguments and returns a string. 

Any type that defines this method is said to satisfy the Animal interface.

非常に単純です。動物を、Speakという名前のメソッドを持つ任意のタイプとして定義します。 

Speakメソッドは引数をとらず、文字列を返します。このメソッドを定義するすべてのタイプは、

Animalインターフェイスを満たすと言われます。

 Goにはimplementsキーワードはありません。タイプがインターフェースを満たすかどうかは

自動的に決定されます。このインターフェースを満たすいくつかのタイプを作成しましょう。


There is no implements keyword in Go; whether or not a type satisfies an interface is determined automatically. Let’s create a couple of types that satisfy this interface:


type Dog struct {

}


func (d Dog) Speak() string {

    return "Woof!"

}


type Cat struct {

}


func (c Cat) Speak() string {

    return "Meow!"

}


type Llama struct {

}


func (l Llama) Speak() string {

    return "?????"

}


type JavaProgrammer struct {

}


func (j JavaProgrammer) Speak() string {

    return "Design patterns!"

}

We now have four different types of animals: A dog, a cat, a llama, and a Java programmer. 

In our main() function, we can create a slice of Animals, and put one of each type into that slice, and see what each animal says. Let’s do that now:

現在、犬、猫、ラマ、Javaプログラマーの4種類の動物がいます。 

main()関数では、Animalsのスライスを作成し、各タイプの1つをそのスライスに入れて、

各動物の発言を確認できます。今それをしましょう:


func main() {

    animals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}

    for _, animal := range animals {

        fmt.Println(animal.Speak())

    }

}

You can view and run this example here:http://play.golang.org/p/yGTd4MtgD5


Great, now you know how to use interfaces, and I don’t need to talk about them

 any more, right? Well, no, not really. Let’s look at a few things that aren’t 

very obvious to the budding gopher.

これで、インターフェイスの使用方法がわかりました。これ以上、インターフェイスに

ついて話す必要はありません。いや、そうではない。新進のホリネズミにはあまり

明白ではないいくつかのことを見てみましょう。


The interface{} type


The interface{} type, the empty interface, is the source of much confusion.

 The interface{} type is the interface that has no methods. 

Since there is no implements keyword, all types implement at least zero methods, 

and satisfying an interface is done automatically, 

all types satisfy the empty interface. 

That means that if you write a function that takes an interface{} value 

as a parameter, you can supply that function with any value. So, this function:

空のインターフェイスであるinterface {}タイプは、多くの混乱の原因です。 

interface {}タイプは、メソッドを持たないインターフェースです。

 implementsキーワードがないため、すべてのタイプが少なくともゼロの

メソッドを実装し、インターフェースを満たすことが自動的に行われるため、

すべてのタイプが空のインターフェースを満たします。

つまり、interface {}値をパラメーターとして受け取る関数を作成する場合、

その関数に任意の値を指定できます。したがって、この関数:


func DoSomething(v interface{}) {

   // ...

}

will accept any parameter whatsoever.

Here’s where it gets confusing: inside of the DoSomething function,

 what is v’s type? Beginner gophers are led to believe that “v is of any type”,

 but that is wrong. v is not of any type; it is of interface{} type. 

すべてのパラメータを受け入れます。ここで混乱します。DoSomething関数の内部で、

vのタイプは何ですか?初心者のゴファーは「vはどんなタイプでもある」

と信じるように導かれますが、それは間違っています。 vはどのタイプでもありません。

これはinterface {}タイプです。


Wait, what? When passing a value into the DoSomething function, 

the Go runtime will perform a type conversion (if necessary), 

and convert the value to an interface{} value.

All values have exactly one type at runtime, and v’s one static type is interface{}.

待って、何?値をDoSomething関数に渡すと、Goランタイムは(必要に応じて)型変換を実行し、

その値をinterface {}値に変換します。すべての値は実行時に正確に1つの型を持ち、

vの1つの静的型はinterface {}です。

This should leave you wondering: ok, so if a conversion is taking place, 

what is actually being passed into a function that takes an interface{} value 

(or, what is actually stored in an []Animal slice)? 

An interface value is constructed of two words of data; 

one word is used to point to a method table for the value’s underlying type, 

and the other word is used to point to the actual data being held by that value. 

これで疑問に思うはずです。わかりました。変換が行われている場合、

interface {}値を受け取る関数に実際に何が渡されているのでしょうか

(または、[] Animalスライスに実際に何が格納されているのでしょうか)。

インターフェイス値は、2ワードのデータで構成されます。 

1つの単語は、値の基になる型のメソッドテーブルを指すために使用され、

もう1つの単語は、その値によって保持されている実際のデータを指すために使用されます。


I don’t want to bleat on about this endlessly. If you understand that an interface value 

is two words wide and it contains a pointer to the underlying data, 

that’s typically enough to avoid common pitfalls. 

If you are curious to learn more about the implementation of interfaces,

 I think Russ Cox’s description of interfaces is very, very helpful.

私はこれについて際限なく悲鳴を上げたくありません。インターフェース値が2ワード幅であり、

基になるデータへのポインターが含まれていることを理解している場合は、

通常、一般的な落とし穴を回避するのに十分です。インターフェイスの実装について

詳しく知りたい場合は、RussCoxによるインターフェイスの説明が非常に役立つと思います。


In our previous example, when we constructed a slice of Animal values, 

we did not have to say something onerous like Animal(Dog{})

 to put a value of type Dog into the slice of Animal values, 

because the conversion was handled for us automatically. 

Within the animals slice, each element is of Animal type,

 but our different values have different underlying types.

前の例では、Animal値のスライスを作成したときに、変換が処理されたため、

Dogタイプの値をAnimal値のスライスに入れるためにAnimal(Dog {})のような

面倒なことを言う必要はありませんでした。自動的に。動物スライス内では、

各要素は動物タイプですが、値が異なれば基本的なタイプも異なります。


So… why does this matter? Well, understanding how interfaces are represented 

in memory makes some potentially confusing things very obvious. 

For example, the question “can I convert a []T to an []interface{}” 

is easy to answer once you understand how interfaces are represented in memory.

それで…なぜこれが重要なのでしょうか?さて、インターフェイスがメモリ内で

どのように表されるかを理解すると、混乱を招く可能性のあることが非常に明白になります。

たとえば、「[] Tを[] interface {}に変換できますか」という質問は、

インターフェイスがメモリ内でどのように表されるかを理解すれば簡単に答えることができます。


 Here’s an example of some broken code that is representative of a common

 misunderstanding of the interface{} type:

これは、インターフェース{}タイプの一般的な誤解を表すいくつかの壊れたコードの例です。


package main


import (

    "fmt"

)


func PrintAll(vals []interface{}) {

    for _, val := range vals {

        fmt.Println(val)

    }

}


func main() {

    names := []string{"stanley", "david", "oscar"}

    PrintAll(names)

}


Run it here:http://play.golang.org/p/4DuBoi2hJU


By running this, you can see that we encounter the following error: 

cannot use names (type []string) as type []interface {} in function argument. 

If we want to actually make that work, we would have to convert the []string to 

an []interface{}:

これを実行すると、次のエラーが発生することがわかります。関数の引数で

type []interface{}としてnames(type []string)を使用できません。

実際にそれを機能させたい場合は、[]stringを[]interface{}に変換する必要があります。



package main


import (

    "fmt"

)


func PrintAll(vals []interface{}) {

    for _, val := range vals {

        fmt.Println(val)

    }

}


func main() {

    names := []string{"stanley", "david", "oscar"}

    vals := make([]interface{}, len(names))

    for i, v := range names {

        vals[i] = v

    }

    PrintAll(vals)

}

Run it here:http://play.golang.org/p/Dhg1YS6BJS


That’s pretty ugly, but c'est la vie. Not everything is perfect. 

(in reality, this doesn’t come up very often,

 because []interface{} turns out to be less useful than you would initially expect)

それはかなり醜いですが、c'est lavieです。すべてが完璧というわけではありません。 

(実際には、[] interface {}は当初の予想よりも役に立たないことが判明したため、

これはあまり頻繁に発生しません)


Pointers and interfaces


Another subtlety of interfaces is that an interface definition 

does not prescribe whether an implementor should implement 

the interface using a pointer receiver or a value receiver.

 When you are given an interface value, there’s no guarantee 

whether the underlying type is or isn’t a pointer. 

In our previous example, we defined all of our methods on value 

receivers, and we put the associated values into the Animal slice. 

Let’s change this and make the Cat’s Speak() 

method take a pointer receiver:

インターフェイスのもう1つの微妙な点は、インターフェイス定義では、

実装者がポインタレシーバーと値レシーバーのどちらを使用して

インターフェイスを実装する必要があるかを規定していないことです。

インターフェース値が与えられた場合、基になる型がポインターであるか

どうかは保証されません。前の例では、値レシーバーですべてのメソッドを定義し、

関連する値を動物スライスに配置しました。これを変更して、

CatのSpeak()メソッドにポインタレシーバーを取得させましょう。


func (c *Cat) Speak() string {

    return "Meow!"

}

If you change that one signature, and you try to run 

the same program exactly as-is (http://play.golang.org/p/TvR758rfre), 

you will see the following error:

その1つの署名を変更し、同じプログラムをそのまま実行しようとすると

(http://play.golang.org/p/TvR758rfre)、次のエラーが表示されます。


prog.go:40: cannot use Cat literal (type Cat) as type Animal in array element:

    Cat does not implement Animal (Speak method requires pointer receiver)

This error message is a bit confusing at first, to be honest.

 What it’s saying is not that the interface Animal demands that 

you define your method as a pointer receiver, but that you have 

tried to convert a Cat struct into an Animal interface value, 

but only *Cat satisfies that interface.

 You can fix this bug by passing in a *Cat pointer 

to the Animal slice instead of a Cat value, by using new(Cat) instead of

 Cat{} (you could also say &Cat{}, I simply prefer the look of new(Cat)):

このエラーメッセージは、正直に言うと、最初は少し混乱します。

つまり、インターフェイスAnimalは、メソッドをポインタレシーバーとして定義する

ことを要求しているのではなく、Cat構造体をAnimalインターフェイス値に変換

しようとしましたが、* Catだけがそのインターフェイスを満たしています。

このバグを修正するには、Cat値の代わりにAnimalスライスへの* Catポインターを渡し、

Cat {}の代わりにnew(Cat)を使用します(&Cat {}と言うこともできますが、

私は単にnew(Cat)):


animals := []Animal{Dog{}, new(Cat), Llama{}, JavaProgrammer{}}

now our program works again:http://play.golang.org/p/x5VwyExxBM


Let’s go in the opposite direction: let’s pass in a *Dog pointer instead of a Dog value,

 but this time we won’t change the definition of the Dog type’s Speak method:


animals := []Animal{new(Dog), new(Cat), Llama{}, JavaProgrammer{}}

This also works (http://play.golang.org/p/UZ618qbPkj), but recognize a subtle difference: 

we didn’t need to change the type of the receiver of the Speak method. 

This works because a pointer type can access the methods of its associated value type, 

but not vice versa. That is, a *Dog value can utilize the Speak method defined on Dog, 

but as we saw earlier, a Cat value cannot access the Speak method defined on *Cat.

これも機能しますが(http://play.golang.org/p/UZ618qbPkj)、微妙な違いを認識しています。

Speakメソッドのレシーバーのタイプを変更する必要はありませんでした。

これは、ポインター型が関連する値型のメソッドにアクセスできるために機能しますが、

その逆はできません。つまり、* Dog値はDogで定義されたSpeakメソッドを利用できますが、

前に見たように、Cat値は* Catで定義されたSpeakメソッドにアクセスできません。


That may sound cryptic, but it makes sense when you remember the following: 

everything in Go is passed by value. Every time you call a function, 

the data you’re passing into it is copied. In the case of a method with a

 value receiver, the value is copied when calling the method. 

This is slightly more obvious when you understand that a method of the following signature:

それは不可解に聞こえるかもしれませんが、次のことを覚えていると意味があります。

Goのすべてが値によって渡されます。関数を呼び出すたびに、関数に渡すデータがコピーされます。

値レシーバーを持つメソッドの場合、メソッドを呼び出すときに値がコピーされます。

これは、次の署名のメソッドを理解すると、もう少し明白になります。


func (t T)MyMethod(s string) {

    // ...

}


is a function of type func(T, string); method receivers are passed into the

 function by value just like any other parameter.

タイプfunc(T、string);の関数です。メソッドレシーバーは、他のパラメーターと

同じように、値によって関数に渡されます。


Any changes to the receiver made inside of a method defined on a value type

 (e.g., func (d Dog) Speak() { ... }) will not be seen by the caller because

 the caller is scoping a completely separate Dog value.

 Since everything is passed by value, it should be obvious 

why a *Cat method is not usable by a Cat value; 

any one Cat value may have any number of *Cat pointers 

that point to it. If we try to call a *Cat method by using a Cat value, 

we never had a *Cat pointer to begin with. Conversely, 

if we have a method on the Dog type, and we have a *Dog pointer, 

we know exactly which Dog value to use when calling this method, 

because the *Dog pointer points to exactly one Dog value; 

the Go runtime will dereference the pointer to its associated 

Dog value any time it is necessary. That is, given a *Dog value d and a method

 Speak on the Dog type, we can just say d.Speak(); 

we don’t need to say something like d->Speak() as we might do in other languages.

値型(func(d Dog)Speak(){...}など)で定義されたメソッド内で行われた

レシーバーへの変更は、呼び出し元が完全に別個のDog値をスコープしているため、

呼び出し元には表示されません。すべてが値によって渡されるため、

* CatメソッドがCat値で使用できない理由は明らかです。 

1つのCat値には、それを指す任意の数の* Catポインターを含めることができます。

 Cat値を使用して* Catメソッドを呼び出そうとすると、

最初から* Catポインターがありませんでした。

逆に、Dogタイプのメソッドがあり、* Dogポインターがある場合、

* Dogポインターは正確に1つのDog値を指しているため、このメソッドを呼び出すときに

使用するDog値が正確にわかります。 Goランタイムは、必要なときにいつでも、

関連するDog値へのポインターを逆参照します。つまり、* Dog値dとメソッドSpeakon 

the Dogタイプが与えられた場合、d.Speak();と言うことができます。

他の言語のようにd-> Speak()のようなことを言う必要はありません。


The real world: getting a proper timestamp out of the Twitter API

The Twitter API represents timestamps using a string of the following format:


"Thu May 31 00:00:01 +0000 2012"


of course, timestamps can be represented in any number of ways in a JSON document, 

because timestamps aren’t a part of the JSON spec. For the sake of brevity, 

I won’t put in the entire JSON representation of a tweet, but let’s take a 

look at how the created_at field would be handled by encoding/json:

現実の世界:TwitterAPIから適切なタイムスタンプを取得する

Twitter APIは、次の形式の文字列を使用してタイムスタンプを表します。


「2012年5月31日木曜日00:00:01 + 0000」

もちろん、タイムスタンプはJSON仕様の一部ではないため、JSONドキュメントでは

さまざまな方法でタイムスタンプを表すことができます。

簡潔にするために、ツイートのJSON表現全体を入力することはしませんが、

encoding / jsonによってcreated_atフィールドがどのように処理されるかを見てみましょう。


package main


import (

    "encoding/json"

    "fmt"

    "reflect"

)


// start with a string representation of our JSON data

var input = `

{

    "created_at": "Thu May 31 00:00:01 +0000 2012"

}

`


func main() {

    // our target will be of type map[string]interface{}, which is a

    // pretty generic type that will give us a hashtable whose keys

    // are strings, and whose values are of type interface{}

    var val map[string]interface{}


    if err := json.Unmarshal([]byte(input), &val); err != nil {

        panic(err)

    }


    fmt.Println(val)

    for k, v := range val {

        fmt.Println(k, reflect.TypeOf(v))

    }

}

run it here:http://play.golang.org/p/VJAyqO3hTF


Running this application, we see that we arrive at the following output:


map[created_at:Thu May 31 00:00:01 +0000 2012]

created_at string


We can see that we’ve retrieved the key properly, but having a timestamp 

in a string format like that isn’t very useful. If we want to compare 

timestamps to see which is earlier, or see how much time has passed since 

the given value and the current time, using a plain string won’t be very helpful.

キーが適切に取得されたことがわかりますが、そのような文字列形式のタイムスタンプを

持つことはあまり役に立ちません。タイムスタンプを比較してどちらが早いかを確認したり、

指定された値と現在の時刻から経過した時間を確認したりする場合は、

プレーンな文字列を使用してもあまり役に立ちません。


Let’s naively try to unmarshal this to a time.Time value, which is the standard 

library representation of time, and see what kind of error we get. Make the following change:


これを単純にtime.Time値にアンマーシャリングしてみましょう。これは、時間の標準

ライブラリ表現であり、どのようなエラーが発生するかを確認します。次の変更を行います。


   var val map[string]time.Time


    if err := json.Unmarshal([]byte(input), &val); err != nil {

        panic(err)

    }

running this, we will encounter the following error:


parsing time ""Thu May 31 00:00:01 +0000 2012"" as ""2006-01-02T15:04:05Z07:00"":

    cannot parse "Thu May 31 00:00:01 +0000 2012"" as "2006"


that somewhat confusing error message comes from the way that Go handles the 

conversion of time.Time values to and from strings. 

In a nutshell, what it means is that the string representation 

we gave it does not match the standard time formatting 

(because Twitter’s API was originally written in Ruby, and the default 

format for Ruby is not the same as the default format for Go). 

We’ll need to define our own type in order to unmarshal this value correctly. 

The encoding/json package looks to see if values passed to json.Unmarshal 

satisfy the json.Unmarshaler interface, which looks like this:

そのやや紛らわしいエラーメッセージは、Goがtime.Time値の文字列への変換と

文字列からの変換を処理する方法から来ています。一言で言えば、私たちが与えた文字

列表現が標準時間のフォーマットと一致しないことを意味します

(TwitterのAPIは元々Rubyで書かれており、Rubyのデフォルトフォーマットは

Goのデフォルトフォーマットと同じではないため)。この値を正しくアンマーシャリング

するには、独自のタイプを定義する必要があります。 

encoding / jsonパッケージは、json.Unmarshalに渡された値がjson.Unmarshaler

インターフェイスを満たしているかどうかを確認します。これは次のようになります。


type Unmarshaler interface {

    UnmarshalJSON([]byte) error

}

this is referenced in the documentation here:http://golang.org/pkg/encoding/json/#Unmarshaler


So what we need is a time.Time value with an UnmarshalJSON([]byte) error method:


type Timestamp time.Time


func (t *Timestamp) UnmarshalJSON(b []byte) error {

    // ...

}


By implementing this method we satisfy the json.Unmarshaler interface,

 causing json.Unmarshal to call our custom unmarshalling code when seeing a 

Timestamp value. For this case, we use a pointer method, because we want 

the caller to the see the changes made to the receiver. 

In order to set the value that a pointer points to, we dereference 

the pointer manually using the * operator. Inside of the UnmarshalJSON method,

 t represents a pointer to a Timestamp value. By saying *t, we dereference the pointer 

t and we are able to access the value that t points to. 

このメソッドを実装することで、json.Unmarshalerインターフェースを満たし、

タイムスタンプ値を確認したときにjson.Unmarshalがカスタムの非マーシャリングコード

を呼び出すようにします。この場合、呼び出し側に受信側に加えられた変更を確認して

もらいたいので、ポインターメソッドを使用します。ポインターが指す値を設定するために、

*演算子を使用してポインターを手動で逆参照します。 

UnmarshalJSONメソッド内で、tはタイムスタンプ値へのポインターを表します。

 * tと言うことで、ポインターtを逆参照し、tが指す値にアクセスできます。


Remember: everything is pass-by-value in Go. 

That means that inside of the UnmarshalJSON method, the pointer t is not the same

 pointer as the pointer in its calling context; it is a copy. 

If you were to assign t to another value directly, you would just be

 reassigning a function-local pointer; the change would not be seen by the caller. 

 However, the pointer inside of the method call points to the same data as

 the pointer in its calling scope; by dereferencing the pointer, 

we make our change visible to the caller.

覚えておいてください:Goではすべてが値渡しです。つまり、UnmarshalJSONメソッド内では、

ポインターtは呼び出し元のコンテキストのポインターと同じポインターではありません。

コピーです。 tを別の値に直接割り当てる場合は、関数ローカルポインタを再割り当てするだけです。

変更は発信者には表示されません。ただし、メソッド呼び出し内のポインターは、

呼び出しスコープ内のポインターと同じデータを指します。ポインターを逆参照することにより、

変更を呼び出し元に表示します。


We can make use of the time.Parse method, which has the signature func(layout, value string) 

(Time, error). That is, it takes two strings: the first string is a layout string 

that describes how we are formatting our timestamps, and the second is the value 

we wish to parse. It returns a time.Time value, as well as an error 

(in case we failed to parse the timestamp for some reason). 

You can read more about the semantics of the layout strings in the time package 

documentation, but in this example we won’t need to figure out the layout string 

manually because this layout string already exists in the standard library as 

the value time.RubyDate. So in effect, we can resolve the string 

“Thu May 31 00:00:01 +0000 2012” to a time.Time value by invoking 

the function time.Parse(time.RubyDate, "Thu May 31 00:00:01 +0000 2012"). 

The value we will receive is of type time.Time. In our example, we’re interested 

in values of the type Timestamp. We can convert the time.Time value to a Timestamp 

value by saying Timestamp(v), where v is our time.Time value. Ultimately, our 

UnmarshalJSON function winds up looking like this:

署名func(layout、value string)(Time、error)を持つtime.Parseメソッドを利用できます。

つまり、2つの文字列を取ります。最初の文字列はタイムスタンプのフォーマット方法を説明する

レイアウト文字列であり、2番目の文字列は解析する値です。

これは、time.Time値と、エラー(何らかの理由でタイムスタンプの解析に失敗した場合)

を返します。レイアウト文字列のセマンティクスについて詳しくは、

タイムパッケージのドキュメントをご覧ください。

ただし、この例では、このレイアウト文字列は標準ライブラリに値time.RubyDateと

して既に存在するため、手動で計算する必要はありません。したがって、

実際には、関数time.Parse(time.RubyDate、 "Thu May 31 00:00:01 +を呼び出すことにより、

文字列「Thu May 31 00:00:01 +00002012」をtime.Time値に解決できます。 0000 2012 ")。

受け取る値はtime.Time型です。この例では、Timestampタイプの値に関心があります。 

Timestamp(v)と言うことで、time.Time値をTimestamp値に変換できます。

ここで、vはtime.Time値です。最終的に、UnmarshalJSON関数は次のようになります。


func (t *Timestamp) UnmarshalJSON(b []byte) error {

    v, err := time.Parse(time.RubyDate, string(b[1:len(b)-1]))

    if err != nil {

        return err

    }

    *t = Timestamp(v)

    return nil

}

we take a subslice of the incoming byte slice because the incoming byte slice 

is the raw data of the JSON element and contains the quotation marks surrounding 

the string value; we want to chop those off before passing the string value into time.Parse.

着信バイトスライスはJSON要素の生データであり、文字列値を囲む引用符が含まれているため、

着信バイトスライスのサブスライスを取得します。文字列値をtime.Parseに渡す前に、

それらを切り落とします。


Source for the entire timestamp example can be seen (and executed) 

here:http://play.golang.org/p/QpiFsJi-nZ


Real-world interfaces: getting an object out of an http request

Let’s wrap up by seeing how we might design an interfaces to solve a common 

web development problem: we wish to parse the body of an HTTP request into some object data.

 At first, this is not a very obvious interface to define.

 We might try to say that we’re going to get a resource from an HTTP request like this:

実世界のインターフェース:httpリクエストからオブジェクトを取得する

最後に、一般的なWeb開発の問題を解決するためのインターフェースを設計する方法を見てみましょう。

HTTPリクエストの本文を解析してオブジェクトデータにしたいのです。

最初は、これを定義するのはあまり明白なインターフェースではありません。

次のようなHTTPリクエストからリソースを取得すると言ってみてください。


GetEntity(*http.Request) (interface{}, error)


because an interface{} can have any underlying type, so we can just parse

our request and return whatever we want. This turns out to be a pretty bad strategy,

 the reason being that we wind up sticking too much logic into the GetEntity function,

 the GetEntity function now needs to be modified for every new type, and we’ll 

need to use a type assertion to do anything useful with that returned interface{} value. 

In practice, functions that return interface{} values tend to be quite annoying, 

and as a rule of thumb you can just remember that it’s typically better to take 

in an interface{} value as a parameter than it is to return an interface{} value. 

(Postel’s Law, applied to interfaces)

interface {}は任意の基になる型を持つことができるため、リクエストを解析して必要なものを返す

ことができます。これはかなり悪い戦略であることが判明しました。その理由は、

GetEntity関数にロジックを貼り付けすぎてしまい、GetEntity関数を新しい型ごとに

変更する必要があり、型アサーションを使用して次のことを行う必要があるためです。

返されたinterface {}値で役立つことは何でもします。実際には、interface {}値を返す

関数は非常に煩わしい傾向があり、経験則として、インターフェイス{}を返すよりも

interface {}値をパラメータとして取り込む方が一般的に優れていることを覚えておいてください。

値。 (インターフェースに適用されるポステルの法則)


We might also be tempted to write some type-specific function like this:


GetUser(*http.Request) (User, error)


This also turns out to be pretty inflexible, because now we have different functions 

for every type, but no sane way to generalize them. Instead,

 what we really want to do is something more like this:

また、これはかなり柔軟性がないことがわかりました。これは、

タイプごとに異なる関数がありますが、それらを一般化するための適切な方法がないためです。

代わりに、私たちが本当にやりたいことは、次のようなものです。


type Entity interface {

    UnmarshalHTTP(*http.Request) error

}

func GetEntity(r *http.Request, v Entity) error {

    return v.UnmarshalHTTP(r)

}


Where the GetEntity function takes an interface value that is guaranteed

 to have an UnmarshalHTTP method. To make use of this, we would define 

on our User object some method that allows the User to describe how 

it would get itself out of an HTTP request:


GetEntity関数が、UnmarshalHTTPメソッドを持つことが保証されている

インターフェイス値を取得する場合。これを利用するために、ユーザーオブジェクトに

HTTPリクエストから自分自身を取得する方法をユーザーが記述できるようにするメソッドを定義します。


func (u *User) UnmarshalHTTP(r *http.Request) error {

   // ...

}


in your application code, you would declare a var of User type, and then pass a pointer 

to this function into GetEntity:

アプリケーションコードでは、Userタイプの変数を宣言してから、

この関数へのポインターをGetEntityに渡します。


var u User

if err := GetEntity(req, &u); err != nil {

    // ...

}


That’s very similar to how you would unpack JSON data.  This type of thing works

consistently and safely because the statement var u User will automatically zero

 the User struct.  Go is not like some other languages in that declaration and 

initialization occur separately, and that by declaring a value without initializing

 it you can create a subtle pitfall wherein you might access a section of junk data;

 when declaring the value, the runtime will zero the appropriate memory space to

hold that value.  Even if our UnmarshalHTTP method fails to utilize some fields, 

those fields will contain valid zero data instead of junk.

これは、JSONデータを解凍する方法と非常によく似ています。このタイプのものは、

ステートメントvar u Userが自動的にUser構造体をゼロにするため、一貫して安全に機能します。

 Goは、宣言と初期化が別々に行われるという点で他の言語とは異なり、値を初期化せず

に宣言することで、ジャンクデータのセクションにアクセスする可能性のある微妙な落とし穴

を作成できます。値を宣言すると、ランタイムはその値を保持するための適切なメモリスペースを

ゼロにします。 UnmarshalHTTPメソッドが一部のフィールドを利用できない場合でも、

それらのフィールドには、ジャンクではなく有効なゼロデータが含まれます。


That should seem weird to you if you’re a Python programmer, because it’s basically 

inside-out of what we typically do in Python. The reason that this form becomes 

so handy is that now we can define an arbitrary number of types, each of which is 

responsible for its own unpacking from an http request. It is now up to the entity 

definitions to decide how they may be represented. Then, we can build around the

 Entity type to create things like generic HTTP handlers.

Pythonプログラマーの場合、これは基本的にPythonで通常行うことの裏返しであるため、

奇妙に思えるかもしれません。このフォームが非常に便利になる理由は、任意の数のタイプを

定義できるようになったためです。各タイプは、httpリクエストからの独自のアンパックを担当します。

これらをどのように表現するかを決定するのは、エンティティ定義次第です。

次に、エンティティタイプを中心に構築して、汎用HTTPハンドラーなどを作成できます。


Wrapping up

I hope, after reading this, that you feel more comfortable using interfaces in Go. Remember the following:


create abstractions by considering the functionality that is common between datatypes, instead of the fields that are common between datatypes

an interface{} value is not of any type; it is of interface{} type

interfaces are two words wide; schematically they look like (type, value)

it is better to accept an interface{} value than it is to return an interface{} value

a pointer type may call the methods of its associated value type, but not vice versa

everything is pass by value, even the receiver of a method

an interface value isn’t strictly a pointer or not a pointer, it’s just an interface

if you need to completely overwrite a value inside of a method, use the * operator to manually dereference a pointer

Ok, I think that sums up everything about interfaces that I personally found confusing. Happy coding :)


まとめ

これを読んだ後、Goのインターフェースをより快適に使用できるようになることを願っています。

次の点に注意してください。


データ型間で共通のフィールドではなく、データ型間で共通の機能を考慮して抽象化を作成します

interface {}の値はどのタイプでもありません。インターフェイス{}タイプです

インターフェイスは2ワード幅です。概略的には(タイプ、値)のように見えます

interface {}値を返すよりも、interface {}値を受け入れる方がよい

ポインタ型は、関連する値型のメソッドを呼び出すことができますが、その逆はできません。

メソッドの受信者でさえ、すべてが値によって渡されます

インターフェース値は厳密にはポインターでもポインターでもありません。単なるインターフェースです。

メソッド内の値を完全に上書きする必要がある場合は、*演算子を使用して手動でポインターを逆参照します

わかりました、それは私が個人的に混乱していると思ったインターフェースについてのすべてを要約

していると思います。ハッピーコーディング:)


---------------------------------------------

The Laws of Reflection

Rob Pike

6 September 2011


Introduction

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でリフレクションがどのように機能するかを説明することで、物事を明確にすることを試みます。

各言語のリフレクションモデルは異なります(多くの言語ではまったくサポートされていません)が、

この記事はGoに関するものなので、この記事の残りの部分では、「リフレクション」という単語は

「Goでのリフレクション」を意味するものと解釈する必要があります。

Types and interfaces

Because reflection builds on the type system, let's start with a refresher about types in 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. 

タイプとインターフェース

リフレクションは型システムに基づいて構築されているので、Goの型についての復習から始めましょう。

Goは静的に型付けされます。すべての変数には静的な型があります。つまり、int、float32、* MyType、[] byteなど、

コンパイル時に既知で固定されている型は1つだけです。


If we declare


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.

次に、型はintで、jは型MyIntです。変数iとjには異なる静的型があり、同じ基本型がありますが、変換せずに互いに割り当てることはできません。


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. 

タイプの1つの重要なカテゴリは、メソッドの固定セットを表すインターフェイスタイプです。

インターフェイス変数は、その値がインターフェイスのメソッドを実装している限り、

任意の具体的な(非インターフェイス)値を格納できます。。


A well-known pair of examples is io.Reader and io.Writer, the types Reader and Writer from the io package:

よく知られている例のペアはio.Readerとio.Writerで、ioパッケージのタイプReaderとWriterです


// Reader is the interface that wraps the basic Read method.// Readerは、基本的なReadメソッドをラップするインターフェースです。

タイプライターインターフェース{

    Write(p [] byte)(n int、errエラー)

} 

type Reader interface {

    Read(p []byte) (n int, err error)

}


// Writer is the interface that wraps the basic Write method. // Writerは、基本的なWriteメソッドをラップするインターフェースです 

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は静的にタイプされ、rの静的タイプは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のインターフェースは動的に型付けされていると言う人もいますが、それは誤解を招きます。それらは静的に型付けされます。

インターフェース型の変数は常に同じ静的型を持ち、実行時にインターフェース変数に格納された値が型を変更する場合でも、

その値は常にインターフェースを満たします。


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

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でのインターフェース値の表現に関する詳細なブログ投稿を書いています。

ここですべての話を繰り返す必要はありませんが、簡単な要約が適切です。


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


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. 

rには、(値、タイプ)のペア(tty、* os.File)が概略的に含まれています。タイプ* os.FileはRead以外のメソッドを実装している

ことに注意してください。インターフェイス値はReadメソッドへのアクセスのみを提供しますが、内部の値はその値に関するすべての型情報を保持します。


That's why we can do things like this:


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.

空のインターフェイス値emptyにも、同じペア(tty、* os.File)が含まれます。これは便利です。空のインターフェースは任意の値を保持でき、

その値に関して必要となる可能性のあるすべての情報を含みます。



(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が空のインターフェースを満たすことが静的に知られているため、ここでは型アサーションは必要ありません。

ReaderからWriterに値を移動した例では、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つの重要な詳細は、インターフェイス内のペアは常にフォーム(値、具象タイプ)を持ち、

フォーム(値、インターフェイスタイプ)を持つことができないことです。インターフェイスはインターフェイス値を保持しません。


Now we're ready to reflect.


The first law of reflection

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.)

基本的なレベルでは、リフレクションはインターフェース変数内に格納されているタイプと値のペアを調べるメカニズムにすぎません。

開始するには、パッケージリフレクトで知っておく必要がある2つのタイプがあります。タイプと値です。

これらの2つのタイプは、インターフェース変数の内容へのアクセスを提供し、reflect.TypeOfおよびReflect.ValueOfと呼ばれる

2つの単純な関数は、インターフェース値からreflect.Typeおよびreflect.Valueのピースを取得します。 

(また、reflect.Valueからは、reflect.Typeに簡単にアクセスできますが、今のところ、ValueとTypeの概念を分離しておいてください。)


Let's start with 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:

プログラムは、reflect.TypeOfにインターフェイス値ではなくfloat64変数xを渡しているように見えるため、

インターフェイスがどこにあるのか疑問に思われるかもしれません。しかし、それはそこにあります。 

godocが報告するように、reflect.TypeOfのシグニチャーには空のインターフェースが含まれています。


// TypeOf returns the reflection Type of the value in the interface{}.

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は最初に空のインターフェイスに格納され、次に引数として渡されます。 

Reflect.TypeOfは、空のインターフェースをアンパックして、タイプ情報を復元します。


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メソッドはそうではありません。)


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に、reflect.ValueのTypeを返すTypeメソッドがあることです。

もう1つは、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の反射法則の主題である設定可能性を理解する必要があります


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:

リフレクションライブラリには、価値のあるいくつかのプロパティがあります。まず、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.

2番目のプロパティは、リフレクションオブジェクトのKindが、静的な型ではなく、基になる型を記述することです。


If a reflection object contains a value of a user-defined integer type, as in

次のように、リフレクションオブジェクトにユーザー定義の整数型の値が含まれている場合


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です。

いい換えると、Typeは識別できても、KindはIntとMyIntを区別できません。



The second law of reflection

2. Reflection goes from reflection object to interface value.


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

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:

物理的な反射と同様に、Goでのリフレクションも独自の反転を生成します。

Reflect.Valueを指定すると、Interfaceメソッドを使用してインターフェース値を回復できます。

実際には、メソッドは型と値の情報をインターフェース表現にパックし、結果を返します。


// Interface returns v's value as an 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.


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などへの引数はすべて空のインターフェース値として渡され、

前の例と同じようにfmtパッケージによって内部的にアンパックされます。

したがって、reflect.Valueの内容を正しく印刷するには、Interfaceメソッドの結果をフォーマットされた印刷ルーチンに渡すだけです。



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にタイプアサートする必要はありません。

空のインターフェース値には、具体的な値のタイプ情報が内部にあり、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関数の逆ですが、その結果は常に静的な型のインターフェイスです{}。


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

繰り返し:リフレクションは、インターフェース値からリフレクションオブジェクトに行き、再び戻ります。


The third law of reflection

3. 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.

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

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.

panic:アドレス指定不可能な値を使用するreflect.Value.SetFloat

問題は、値7.1がアドレス指定できないことではありません。それはvが設定可能ではないということです。

設定可能性はリフレクション値のプロパティであり、すべてのリフレクション値が持つわけではありません。


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


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. 

xのコピーをReflect.ValueOfに渡すため、reflect.ValueOfの引数として作成されたインターフェース値は、

x自体ではなくxのコピーです。


Thus, if the statement 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.

もし成功した場合、vはxから作成されたように見えますが、xは更新されません。

代わりに、リフレクション値内に格納されている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.

これは簡単でおなじみで、リフレクションも同じように機能します。リフレクションによってxを変更する場合は、

リフレクションライブラリに変更する値へのポインターを与える必要があります。


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

それをしましょう。まず、いつものようにxを初期化してから、それを指す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:

リフレクションオブジェクトpは設定できませんが、設定したいpではなく、(実質的に)* pです。 

pが指すものを取得するには、ValueのElemメソッドを呼び出します。これは、ポインターを介して間接的に行い、

結果をvというリフレクションValueに保存します。


v := p.Elem()

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


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


settability of v: true


and since it represents x, we are finally able to use v.SetFloat to modify the value of 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.

リフレクションは理解するのが難しい場合がありますが、何が起こっているのかを偽ることができる

リフレクションのタイプと値によってではありますが、言語が行うことを正確に行っています。

リフレクション値は、それらが表すものを変更するために何かのアドレスを必要とすることに注意してください。



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. 

前の例では、v自体はポインターではなく、ポインターから派生しただけです。

この状況が発生する一般的な方法は、リフレクションを使用して構造のフィールドを変更する場合です。


As long as we have the address of the structure, we can modify its fields.

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.

structのアドレスがある限り、そのフィールドを変更できます。

次に、構造体の値tを分析する簡単な例を示します。

後で修正するため、構造体のアドレスを使用してリフレクションオブジェクトを作成します。

次に、typeOfTをその型に設定し、単純なメソッド呼び出しを使用してフィールドを反復処理します

(詳細については、reflectパッケージを参照してください)。構造体タイプからフィールドの名前を抽出していますが、

フィールド自体は通常の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.

ここで渡すことで導入された設定可能性についてもう1つポイントがあります。

Tのフィールド名は大文字(エクスポート)です。なぜなら、構造体の!!エクスポートされたフィールドのみ!!が設定可能だからです。

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

sには設定可能な反射オブジェクトが含まれているため、構造のフィールドを変更できます。


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が作成されるようにプログラムを変更した場合、tのフィールドを設定できないため、

SetIntおよびSetStringの呼び出しは失敗します。


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.

There's plenty more to reflection that we haven't covered — sending and receiving on channels, 

allocating memory, using slices and maps, calling methods and functions — but this post is long enough.

 We'll cover some of those topics in a later article.

これらの法則を理解すると、Goでのリフレクションは非常に使いやすくなりますが、微妙なままです。

強力なツールなので、慎重に使用し、厳密に必要な場合を除いては使用しないでください。

まだ説明していないことはたくさんあります。チャネルでの送受信、メモリの割り当て、スライスとマップの使用、

メソッドと関数の呼び出しなどですが、この投稿は十分に長いです。これらのトピックの一部については、後の記事で取り上げます。

--------------------------------------

Introduction

If you have written any Go code you have probably encountered the 

built-in error type. Go code uses error values to indicate an 

abnormal state. For example, the os.Open function returns a 

non-nil error value when it fails to open a file.

Goコードを記述した場合は、おそらく組み込みのエラータイプに遭遇した

ことでしょう。 Goコードは、エラー値を使用して異常な状態を示します。

たとえば、os.Open関数は、ファイルのオープンに失敗すると、

nil以外のエラー値を返します。


func Open(name string) (file *File, err error)

The following code uses os.Open to open a file. If an error occurs 

it calls log.Fatal to print the error message and stop.

次のコードは、os.Openを使用してファイルを開きます。

エラーが発生した場合は、log.Fatalを呼び出してエラーメッセージを

出力し、停止します。


f, err := os.Open("filename.ext")

if err != nil {

    log.Fatal(err)

}

// do something with the open *File f

You can get a lot done in Go knowing just this about the error type, 

but in this article we'll take a closer look at error and discuss 

some good practices for error handling in Go.

エラーの種類についてこれだけを知っていれば、Goで多くのことを成し遂げる

ことができますが、この記事では、エラーを詳しく見て、

Goでのエラー処理のいくつかのグッドプラクティスについて説明します。


The error type

The error type is an interface type. An error variable represents 

any value that can describe itself as a string. Here is the 

interface's declaration:

エラータイプはインターフェイスタイプです。エラー変数は、それ自体を

文字列として記述できる任意の値を表します。インターフェイスの宣言は

次のとおりです。


type error interface {

    Error() string

}


The error type, as with all built in types, is predeclared in the 

universe block.

エラータイプは、すべての組み込みタイプと同様に、ユニバースブロック

で事前に宣言されています。



The most commonly-used error implementation is the errors package's 

unexported errorString type.

最も一般的に使用されるエラーの実装は、エラーパッケージのエクスポート

されていないerrorStringタイプです。


// errorString is a trivial implementation of error.

type errorString struct {

    s string

}


func (e *errorString) Error() string {

    return e.s

}


You can construct one of these values with the errors.

New function. It takes a string that it converts to an 

errors.errorString and returns as an error value.

これらの値の1つをerrors.New関数で作成できます。

これは、errors.errorStringに変換する文字列を受け取り、

エラー値として返します。


// New returns an error that formats as the given text.

func New(text string) error {

    return &errorString{text}

}


Here's how you might use errors.New:


func Sqrt(f float64) (float64, error) {

    if f < 0 {

        return 0, errors.New("math: square root of negative number")

    }

    // implementation

}


A caller passing a negative argument to Sqrt receives a 

non-nil error value (whose concrete representation is an 

errors.errorString value). The caller can access the error string

 ("math: square root of...") by calling the error's Error method, 

or by just printing it:

Sqrtに負の引数を渡す呼び出し元は、nil以外のエラー値を受け取ります

(具体的な表現はerrors.errorString値です)。呼び出し元は、

エラーのErrorメソッドを呼び出すか、次のように出力することで、

エラー文字列( "math:square root of ...")にアクセスできます。


f, err := Sqrt(-1)

if err != nil {

    fmt.Println(err)

}


The fmt package formats an error value by calling its Error() 

string method.

fmtパッケージは、Error()文字列メソッドを呼び出してエラー値を

フォーマットします。


It is the error implementation's responsibility to summarize 

the context. The error returned by os.Open formats as 

"open /etc/passwd: permission denied," not just "permission denied." 

The error returned by our Sqrt is missing information 

about the invalid argument.

コンテキストを要約するのはエラー実装の責任です。 os.Openに

よって返されるエラーは、「permissiondenied」だけでなく「

open / etc / passwd:permissiondenied」としてフォーマットされます。

 Sqrtによって返されるエラーには、無効な引数に関する情報がありません。


To add that information, a useful function is the fmt package's 

Errorf. It formats a string according to Printf's rules and 

returns it as an error created by errors.New.

その情報を追加するために役立つ関数は、fmtパッケージのErrorfです。

 Printfのルールに従って文字列をフォーマットし、errors.Newに

よって作成されたエラーとして返します。


if f < 0 {

    return 0, fmt.Errorf("math: square root of negative number %g", f)

}


In many cases fmt.Errorf is good enough, but since error is an 

interface, you can use arbitrary data structures as error values, 

to allow callers to inspect the details of the error.

多くの場合、fmt.Errorfで十分ですが、エラーはインターフェイスで

あるため、任意のデータ構造をエラー値として使用して、

呼び出し元がエラーの詳細を検査できるようにすることができます。



For instance, our hypothetical callers might want to recover 

the invalid argument passed to Sqrt. We can enable that

 by defining a new error implementation instead of using 

errors.errorString:

たとえば、架空の呼び出し元は、Sqrtに渡された無効な引数を回復したい

場合があります。 errors.errorStringを使用する代わりに、

新しいエラー実装を定義することで、これを有効にできます。



type NegativeSqrtError float64


func (f NegativeSqrtError) Error() string {

 return fmt.Sprintf("math: square root of negative number %g",float64(f))

}


A sophisticated caller can then use a type assertion to check 

for a NegativeSqrtError and handle it specially, while callers 

that just pass the error to fmt.Println or log.Fatal will 

see no change in behavior.

洗練された呼び出し元は、型アサーションを使用してNegativeSqrtErrorを

チェックし、それを特別に処理できますが、エラーをfmt.Printlnまたは

log.Fatalに渡すだけの呼び出し元は、動作に変化がありません。


As another example, the json package specifies a SyntaxError type 

that the json.Decode function returns when it encounters a syntax 

error parsing a JSON blob.

別の例として、jsonパッケージは、JSONBLOBの解析で構文エラーが発生した

ときにjson.Decode関数が返すSyntaxErrorタイプを指定します。



type SyntaxError struct {

    msg    string // description of error

    Offset int64  // error occurred after reading Offset bytes

}


func (e *SyntaxError) Error() string { return e.msg }


The Offset field isn't even shown in the default formatting of 

the error, but callers can use it to add file and line information 

to their error messages:

オフセットフィールドは、エラーのデフォルトのフォーマットにも表示

されませんが、呼び出し元はそれを使用して、エラーメッセージに

ファイルと行の情報を追加できます。


if err := dec.Decode(&val); err != nil {

    if serr, ok := err.(*json.SyntaxError); ok {

        line, col := findLine(f, serr.Offset)

        return fmt.Errorf("%s:%d:%d: %v", f.Name(), line, col, err)

    }

    return err

}

(This is a slightly simplified version of some actual code 

from the Camlistore project.)


The error interface requires only a Error method; specific error 

implementations might have additional methods. 

For instance, the net package returns errors of type error, 

following the usual convention, but some of the error 

implementations have additional methods defined by the net.

Error interface:

エラーインターフェイスには、Errorメソッドのみが必要です。

特定のエラー実装には、追加のメソッドがある場合があります。

たとえば、netパッケージは通常の規則に従って、タイプerrorの

エラーを返しますが、一部のエラー実装には、net.Error

インターフェイスによって定義された追加のメソッドがあります。


package net


type Error interface {

    error

    Timeout() bool   // Is the error a timeout?

    Temporary() bool // Is the error temporary?

}


Client code can test for a net.Error with a type assertion 

and then distinguish transient network errors from permanent ones.

 For instance, a web crawler might sleep and retry when 

it encounters a temporary error and give up otherwise.

クライアントコードは、タイプアサーションを使用してnet.Errorを

テストし、一時的なネットワークエラーと永続的なネットワークエラー

を区別できます。たとえば、Webクローラーは、一時的なエラーが発生

したときにスリープして再試行し、それ以外の場合はあきらめる可能性

があります。


if nerr, ok := err.(net.Error); ok && nerr.Temporary() {

    time.Sleep(1e9)

    continue

}

if err != nil {

    log.Fatal(err)

}


Simplifying repetitive error handling


In Go, error handling is important. The language's design and 

conventions encourage you to explicitly check for errors where 

they occur (as distinct from the convention in other languages 

of throwing exceptions and sometimes catching them).

 In some cases this makes Go code verbose, but fortunately

there are some techniques you can use to minimize repetitive 

error handling.

Goでは、エラー処理が重要です。言語の設計と規則により、

エラーが発生した場所を明示的にチェックすることが推奨されます

(例外をスローし、場合によってはキャッチする他の言語の規則とは

異なります)。これによりGoコードが冗長になる場合もありますが、

幸い、繰り返しのエラー処理を最小限に抑えるために使用できる

手法がいくつかあります。


Consider an App Engine application with an HTTP handler 

that retrieves a record from the datastore and formats 

it with a template.

データストアからレコードを取得し、テンプレートでフォーマットする

HTTPハンドラーを備えたAppEngineアプリケーションについて考えてみます。


func init() {

    http.HandleFunc("/view", viewRecord)

}


func viewRecord(w http.ResponseWriter, r *http.Request) {

    c := appengine.NewContext(r)

    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)

    record := new(Record)

    if err := datastore.Get(c, key, record); err != nil {

        http.Error(w, err.Error(), 500)

        return

    }

    if err := viewTemplate.Execute(w, record); err != nil {

        http.Error(w, err.Error(), 500)

    }

}


This function handles errors returned by the datastore.

Get function and viewTemplate's Execute method. 

In both cases, it presents a simple error message to the user

 with the HTTP status code 500 ("Internal Server Error"). 

This looks like a manageable amount of code,

 but add some more HTTP handlers and you quickly end up

 with many copies of identical error handling code.

この関数は、datastore.Get関数とviewTemplateのExecuteメソッドに

よって返されるエラーを処理します。どちらの場合も、HTTPステータス

コード500(「内部サーバーエラー」)を含む簡単なエラーメッセージが

ユーザーに表示されます。これは管理可能な量のコードのように見えますが、

HTTPハンドラーをさらに追加すると、同じエラー処理コードのコピーが

すぐに多くなります。


To reduce the repetition we can define our own HTTP appHandler 

type that includes an error return value:

繰り返しを減らすために、エラーの戻り値を含む独自のHTTPappHandler

タイプを定義できます。


type appHandler func(http.ResponseWriter, *http.Request) error

Then we can change our viewRecord function to return errors:


func viewRecord(w http.ResponseWriter, r *http.Request) error {

    c := appengine.NewContext(r)

    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)

    record := new(Record)

    if err := datastore.Get(c, key, record); err != nil {

        return err

    }

    return viewTemplate.Execute(w, record)

}


This is simpler than the original version, but the http package 

doesn't understand functions that return error. 

To fix this we can implement the http.Handler interface's 

ServeHTTP method on appHandler:

これは元のバージョンよりも単純ですが、httpパッケージはエラー

を返す関数を理解していません。これを修正するために、appHandlerに

http.HandlerインターフェースのServeHTTPメソッドを実装できます。


func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

    if err := fn(w, r); err != nil {

        http.Error(w, err.Error(), 500)

    }

}


The ServeHTTP method calls the appHandler function and displays

 the returned error (if any) to the user. Notice that the method's

 receiver, fn, is a function. (Go can do that!) The method 

invokes the function by calling the receiver in the expression 

fn(w, r).

ServeHTTPメソッドはappHandler関数を呼び出し、返されたエラー

(存在する場合)をユーザーに表示します。メソッドのレシーバーfn

が関数であることに注意してください。 (Goはそれを行うことができます!)

メソッドは、式fn(w、r)でレシーバーを呼び出すことによって

関数を呼び出します。


Now when registering viewRecord with the http package we use 

the Handle function (instead of HandleFunc) as appHandler 

is an http.Handler (not an http.HandlerFunc).

ここで、viewRecordをhttpパッケージに登録するとき、appHandlerは

http.Handler(http.HandlerFuncではない)であるため、

(HandleFuncの代わりに)Handle関数を使用します。



func init() {

    http.Handle("/view", appHandler(viewRecord))

}


With this basic error handling infrastructure in place,

 we can make it more user friendly. Rather than just displaying 

the error string, it would be better to give the user a 

simple error message with an appropriate HTTP status code, 

while logging the full error to the App Engine developer 

console for debugging purposes.

この基本的なエラー処理インフラストラクチャを導入することで、

よりユーザーフレンドリーにすることができます。エラー文字列を表示

するだけでなく、デバッグの目的でエラー全体をApp Engine開発者

コンソールに記録しながら、適切なHTTPステータスコードを含む

簡単なエラーメッセージをユーザーに提供することをお勧めします。


To do this we create an appError struct containing an error 

and some other fields:


type appError struct {

    Error   error

    Message string

    Code    int

}

Next we modify the appHandler type to return *appError values:


type appHandler func(http.ResponseWriter, *http.Request) *appError


(It's usually a mistake to pass back the concrete type of an error 

rather than error, for reasons discussed in the Go FAQ, 

but it's the right thing to do here because ServeHTTP is 

the only place that sees the value and uses its contents.)

(Go FAQで説明されている理由により、通常、エラーではなく具体的??な

タイプのエラーを返すのは間違いですが、ServeHTTPが値を確認して

その内容を使用する唯一の場所であるため、ここで行うのは正しいことです。)


And make appHandler's ServeHTTP method display the appError's 

Message to the user with the correct HTTP status Code and log the 

full Error to the developer console:

そして、appHandlerのServeHTTPメソッドに、正しいHTTPステータスコードを

含むappErrorのメッセージをユーザーに表示させ、エラー全体を開発者

コンソールに記録します。


func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

    if e := fn(w, r); e != nil { // e is *appError, not os.Error.

        c := appengine.NewContext(r)

        c.Errorf("%v", e.Error)

        http.Error(w, e.Message, e.Code)

    }

}


Finally, we update viewRecord to the new function signature and have

 it return more context when it encounters an error:

最後に、viewRecordを新しい関数シグネチャに更新し、エラーが発生した

ときに、より多くのコンテキストを返すようにします。


func viewRecord(w http.ResponseWriter, r *http.Request) *appError {

    c := appengine.NewContext(r)

    key := datastore.NewKey(c, "Record", r.FormValue("id"), 0, nil)

    record := new(Record)

    if err := datastore.Get(c, key, record); err != nil {

        return &appError{err, "Record not found", 404}

    }

    if err := viewTemplate.Execute(w, record); err != nil {

        return &appError{err, "Can't display record", 500}

    }

    return nil

}


This version of viewRecord is the same length as the original, 

but now each of those lines has specific meaning and we are 

providing a friendlier user experience.

このバージョンのviewRecordは元のバージョンと同じ長さですが、

これらの各行には特定の意味があり、より使いやすいユーザーエ

クスペリエンスを提供しています。


It doesn't end there; we can further improve the error handling 

in our application. Some ideas:

それだけではありません。アプリケーションのエラー処理をさらに

改善できます。いくつかのアイデア:


give the error handler a pretty HTML template,


make debugging easier by writing the stack trace to the HTTP 

response when the user is an administrator,

エラーハンドラにきれいなHTMLテンプレートを与えます。


ユーザーが管理者の場合、HTTP応答にスタックトレースを書き込むことで

デバッグを容易にします。


write a constructor function for appError that stores the stack 

trace for easier debugging,

デバッグを容易にするためにスタックトレースを格納するappErrorのコ

ンストラクター関数を記述します。


recover from panics inside the appHandler, logging the error to 

the console as "Critical," while telling the user "a serious 

error has occurred." This is a nice touch to avoid exposing the user 

to inscrutable error messages caused by programming errors. 

See the Defer, Panic, and Recover article for more details.

appHandler内のパニックから回復し、エラーを「重大」としてコンソール

に記録し、ユーザーに「重大なエラーが発生しました」と伝えます。

これは、プログラミングエラーによって引き起こされる不可解な

エラーメッセージにユーザーをさらさないようにするための良い方法です。

詳細については、延期、パニック、および回復の記事を参照してください。


Conclusion

Proper error handling is an essential requirement of good software.

 By employing the techniques described in this post you should be 

able to write more reliable and succinct Go code.


適切なエラー処理は、優れたソフトウェアの重要な要件です。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

https://stackoverflow.com/questions/18306151/in-go-which-value-s-kind-is-reflect-interface

var v interface{} 

var t = reflect.ValueOf(&v).Type().Elem()

fmt.Println(t.Kind() == reflect.Interface)

----------------------------------------------------------------------

package main import ( "fmt" "reflect" ) func main() { var v interface{} = 1 t := reflect.TypeOf(&v).Elem() fmt.Printf("Type: %s\n", t) fmt.Printf("Kind: %v\n", t.Kind()) fmt.Printf("IsInterface: %v\n", t.Kind() == reflect.Interface) i := reflect.ValueOf(v).Type() fmt.Println(i.String()) }

0 件のコメント:

コメントを投稿