[ja] apply patch
This commit is contained in:
425
ja/ebook/02.4.md
425
ja/ebook/02.4.md
@@ -1,211 +1,214 @@
|
|||||||
# 2.4 struct型
|
# 2.4 struct型
|
||||||
## struct
|
## struct
|
||||||
Go言語では、Cや他の言語と同じように、他の型の属性やフィールドのコンテナとして新しい型を宣言することができます。例えば、一個人のエンティティを表している`person`型を作成することができます。このエンティティは属性を持っています:性別と年齢です。このような型は`struct`と呼ばれます。以下にコードを示します:
|
Go言語では、Cや他の言語と同じように、他の型の属性やフィールドのコンテナとして新しい型を宣言することができます。例えば、一個人のエンティティを表している`person`型を作成することができます。このエンティティは属性を持っています:性別と年齢です。このような型は`struct`と呼ばれます。以下にコードを示します:
|
||||||
|
|
||||||
type person struct {
|
type person struct {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
お分かりいただけましたでしょうか?structの宣言はこのように簡単です。上の型は2つのフィールドを持っています。
|
お分かりいただけましたでしょうか?structの宣言はこのように簡単です。上の型は2つのフィールドを持っています。
|
||||||
- string型のフィールドnameはユーザの名前を保存するプロパティです。
|
- string型のフィールドnameはユーザの名前を保存するプロパティです。
|
||||||
- int型のフィールドageはユーザの年齢を保存するプロパティです。
|
- int型のフィールドageはユーザの年齢を保存するプロパティです。
|
||||||
|
|
||||||
どのようにstructは使用されるのでしょうか?下のコードをご覧ください。
|
どのようにstructは使用されるのでしょうか?下のコードをご覧ください。
|
||||||
|
|
||||||
type person struct {
|
type person struct {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
|
|
||||||
var P person // Pは現在person型の変数です。
|
var P person // Pは現在person型の変数です。
|
||||||
|
|
||||||
P.name = "Astaxie" // "Astaxie"を変数Pのnameプロパティに代入します。
|
P.name = "Astaxie" // "Astaxie"を変数Pのnameプロパティに代入します。
|
||||||
P.age = 25 // "25"を変数Pのageプロパティに代入します。
|
P.age = 25 // "25"を変数Pのageプロパティに代入します。
|
||||||
fmt.Printf("The person's name is %s", P.name) // Pのnameプロパティにアクセスします。
|
fmt.Printf("The person's name is %s", P.name) // Pのnameプロパティにアクセスします。
|
||||||
上のようなPの宣言以外に他にも二種類の宣言方法があります。
|
上のようなPの宣言以外に他にもいくつかの宣言方法があります。
|
||||||
|
|
||||||
- 1.順序にしたがって初期化する。
|
- 1.順序にしたがって初期化する。
|
||||||
|
|
||||||
P := person{"Tom", 25}
|
P := person{"Tom", 25}
|
||||||
|
|
||||||
- 2.`field:value`の方法によって初期化します。この場合は順序は任意でかまいません。
|
- 2.`field:value`の方法によって初期化します。この場合は順序は任意でかまいません。
|
||||||
|
|
||||||
P := person{age:24, name:"Tom"}
|
P := person{age:24, name:"Tom"}
|
||||||
|
|
||||||
以下ではひと通りのstructの使用例をご説明します。
|
- 3.もちろん`new`関数を通してポインタを作ることもできます。このPの型は*personです。
|
||||||
|
|
||||||
package main
|
P := new(person)
|
||||||
import "fmt"
|
|
||||||
|
以下ではひと通りのstructの使用例をご説明します。
|
||||||
// 新しい型を宣言します。
|
|
||||||
type person struct {
|
package main
|
||||||
name string
|
import "fmt"
|
||||||
age int
|
|
||||||
}
|
// 新しい型を宣言します。
|
||||||
|
type person struct {
|
||||||
// 二人の年齢を比較します。年齢が大きい方の人を返し、また年齢差も返します。
|
name string
|
||||||
// structも値渡しです。
|
age int
|
||||||
func Older(p1, p2 person) (person, int) {
|
}
|
||||||
if p1.age>p2.age { // p1とp2の二人の年齢を比較します。
|
|
||||||
return p1, p1.age-p2.age
|
// 二人の年齢を比較します。年齢が大きい方の人を返し、また年齢差も返します。
|
||||||
}
|
// structも値渡しです。
|
||||||
return p2, p2.age-p1.age
|
func Older(p1, p2 person) (person, int) {
|
||||||
}
|
if p1.age>p2.age { // p1とp2の二人の年齢を比較します。
|
||||||
|
return p1, p1.age-p2.age
|
||||||
func main() {
|
}
|
||||||
var tom person
|
return p2, p2.age-p1.age
|
||||||
|
}
|
||||||
// 初期値を代入します。
|
|
||||||
tom.name, tom.age = "Tom", 18
|
func main() {
|
||||||
|
var tom person
|
||||||
// 2つのフィールドを明確に初期化します。
|
|
||||||
bob := person{age:25, name:"Bob"}
|
// 初期値を代入します。
|
||||||
|
tom.name, tom.age = "Tom", 18
|
||||||
// structの定義の順番に従って初期化します。
|
|
||||||
paul := person{"Paul", 43}
|
// 2つのフィールドを明確に初期化します。
|
||||||
|
bob := person{age:25, name:"Bob"}
|
||||||
tb_Older, tb_diff := Older(tom, bob)
|
|
||||||
tp_Older, tp_diff := Older(tom, paul)
|
// structの定義の順番に従って初期化します。
|
||||||
bp_Older, bp_diff := Older(bob, paul)
|
paul := person{"Paul", 43}
|
||||||
|
|
||||||
fmt.Printf("Of %s and %s, %s is older by %d years\n",
|
tb_Older, tb_diff := Older(tom, bob)
|
||||||
tom.name, bob.name, tb_Older.name, tb_diff)
|
tp_Older, tp_diff := Older(tom, paul)
|
||||||
|
bp_Older, bp_diff := Older(bob, paul)
|
||||||
fmt.Printf("Of %s and %s, %s is older by %d years\n",
|
|
||||||
tom.name, paul.name, tp_Older.name, tp_diff)
|
fmt.Printf("Of %s and %s, %s is older by %d years\n",
|
||||||
|
tom.name, bob.name, tb_Older.name, tb_diff)
|
||||||
fmt.Printf("Of %s and %s, %s is older by %d years\n",
|
|
||||||
bob.name, paul.name, bp_Older.name, bp_diff)
|
fmt.Printf("Of %s and %s, %s is older by %d years\n",
|
||||||
}
|
tom.name, paul.name, tp_Older.name, tp_diff)
|
||||||
|
|
||||||
### structの匿名フィールド
|
fmt.Printf("Of %s and %s, %s is older by %d years\n",
|
||||||
上でstructをどのように定義するかご紹介しました。定義する際はフィールド名とその型が一つ一つ対応しています。実はGoは型だけの定義もサポートしています。これはフィールド名を書かない方法ではなく、匿名フィールドです。組み込みフィールドとも呼ばれます。
|
bob.name, paul.name, bp_Older.name, bp_diff)
|
||||||
|
}
|
||||||
匿名フィールドがstructである場合、このstructがもつすべてのフィールドは隠されたまま現在定義しているこのstructに導入されます。
|
|
||||||
|
### structの匿名フィールド
|
||||||
ひとつ例をお見せしましょう。上の説明がより具体的になります。
|
上でstructをどのように定義するかご紹介しました。定義する際はフィールド名とその型が一つ一つ対応しています。実はGoは型だけの定義もサポートしています。これはフィールド名を書かない方法ではなく、匿名フィールドです。組み込みフィールドとも呼ばれます。
|
||||||
|
|
||||||
package main
|
匿名フィールドがstructである場合、このstructがもつすべてのフィールドは隠されたまま現在定義しているこのstructに導入されます。
|
||||||
import "fmt"
|
|
||||||
|
ひとつ例をお見せしましょう。上の説明がより具体的になります。
|
||||||
type Human struct {
|
|
||||||
name string
|
package main
|
||||||
age int
|
import "fmt"
|
||||||
weight int
|
|
||||||
}
|
type Human struct {
|
||||||
|
name string
|
||||||
type Student struct {
|
age int
|
||||||
Human // 匿名フィールド、デフォルトでStudentはHumanのすべてのフィールドを含むことになります。
|
weight int
|
||||||
speciality string
|
}
|
||||||
}
|
|
||||||
|
type Student struct {
|
||||||
func main() {
|
Human // 匿名フィールド、デフォルトでStudentはHumanのすべてのフィールドを含むことになります。
|
||||||
// 学生を一人初期化します。
|
speciality string
|
||||||
mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
|
}
|
||||||
|
|
||||||
// 対応するフィールドにアクセスします。
|
func main() {
|
||||||
fmt.Println("His name is ", mark.name)
|
// 学生を一人初期化します。
|
||||||
fmt.Println("His age is ", mark.age)
|
mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
|
||||||
fmt.Println("His weight is ", mark.weight)
|
|
||||||
fmt.Println("His speciality is ", mark.speciality)
|
// 対応するフィールドにアクセスします。
|
||||||
// 対応するメモ情報を修正します。
|
fmt.Println("His name is ", mark.name)
|
||||||
mark.speciality = "AI"
|
fmt.Println("His age is ", mark.age)
|
||||||
fmt.Println("Mark changed his speciality")
|
fmt.Println("His weight is ", mark.weight)
|
||||||
fmt.Println("His speciality is ", mark.speciality)
|
fmt.Println("His speciality is ", mark.speciality)
|
||||||
// 彼の年齢情報を修正します。
|
// 対応するメモ情報を修正します。
|
||||||
fmt.Println("Mark become old")
|
mark.speciality = "AI"
|
||||||
mark.age = 46
|
fmt.Println("Mark changed his speciality")
|
||||||
fmt.Println("His age is", mark.age)
|
fmt.Println("His speciality is ", mark.speciality)
|
||||||
// 体重情報も修正します。
|
// 彼の年齢情報を修正します。
|
||||||
fmt.Println("Mark is not an athlet anymore")
|
fmt.Println("Mark become old")
|
||||||
mark.weight += 60
|
mark.age = 46
|
||||||
fmt.Println("His weight is", mark.weight)
|
fmt.Println("His age is", mark.age)
|
||||||
}
|
// 体重情報も修正します。
|
||||||
|
fmt.Println("Mark is not an athlet anymore")
|
||||||
図解:
|
mark.weight += 60
|
||||||
|
fmt.Println("His weight is", mark.weight)
|
||||||

|
}
|
||||||
|
|
||||||
図2.7 StudentとHumanの継承方法
|
図解:
|
||||||
|
|
||||||
我们看到Student访问属性age和name的时候,就像访问自己所有用的字段一样,对,匿名字段就是这样,能够实现字段的继承。是不是很酷啊?还有比这个更酷的呢,那就是student还能访问Human这个字段作为字段名。请看下面的代码,是不是更酷了。
|

|
||||||
Studentがageとnameの属性にアクセスする際、あたかも自分のフィールドであるかのようにアクセスしたのをご覧いただけるかと思います。そうです。匿名フィールドというのはこういうものです。フィールドの継承を実現できるのです。これってクールじゃないですか?もっとクールにする方法もありますよ。studentはHumanのフィールド名でアクセスできます。下のコードを御覧ください。ほら、とってもクールでしょ?
|
|
||||||
|
図2.7 StudentとHumanの継承方法
|
||||||
mark.Human = Human{"Marcus", 55, 220}
|
|
||||||
mark.Human.age -= 1
|
我们看到Student访问属性age和name的时候,就像访问自己所有用的字段一样,对,匿名字段就是这样,能够实现字段的继承。是不是很酷啊?还有比这个更酷的呢,那就是student还能访问Human这个字段作为字段名。请看下面的代码,是不是更酷了。
|
||||||
|
Studentがageとnameの属性にアクセスする際、あたかも自分のフィールドであるかのようにアクセスしたのをご覧いただけるかと思います。そうです。匿名フィールドというのはこういうものです。フィールドの継承を実現できるのです。これってクールじゃないですか?もっとクールにする方法もありますよ。studentはHumanのフィールド名でアクセスできます。下のコードを御覧ください。ほら、とってもクールでしょ?
|
||||||
匿名によるアクセスとフィールドの修正はとても便利です。でも単なるstructのフィールドですから、すべてのビルトイン型と自分で定義した型をすべて匿名フィールドとみなすことができます。下の例をご覧ください。
|
|
||||||
|
mark.Human = Human{"Marcus", 55, 220}
|
||||||
package main
|
mark.Human.age -= 1
|
||||||
import "fmt"
|
|
||||||
|
匿名によるアクセスとフィールドの修正はとても便利です。でも単なるstructのフィールドですから、すべてのビルトイン型と自分で定義した型をすべて匿名フィールドとみなすことができます。下の例をご覧ください。
|
||||||
type Skills []string
|
|
||||||
|
package main
|
||||||
type Human struct {
|
import "fmt"
|
||||||
name string
|
|
||||||
age int
|
type Skills []string
|
||||||
weight int
|
|
||||||
}
|
type Human struct {
|
||||||
|
name string
|
||||||
type Student struct {
|
age int
|
||||||
Human // 匿名フィールド、struct
|
weight int
|
||||||
Skills // 匿名フィールド、自分で定義した型。string slice
|
}
|
||||||
int // ビルトイン型を匿名フィールドとします。
|
|
||||||
speciality string
|
type Student struct {
|
||||||
}
|
Human // 匿名フィールド、struct
|
||||||
|
Skills // 匿名フィールド、自分で定義した型。string slice
|
||||||
func main() {
|
int // ビルトイン型を匿名フィールドとします。
|
||||||
// 学生Jannを初期化します。
|
speciality string
|
||||||
jane := Student{Human:Human{"Jane", 35, 100}, speciality:"Biology"}
|
}
|
||||||
// ここで対応するフィールドにアクセスしてみます。
|
|
||||||
fmt.Println("Her name is ", jane.name)
|
func main() {
|
||||||
fmt.Println("Her age is ", jane.age)
|
// 学生Jannを初期化します。
|
||||||
fmt.Println("Her weight is ", jane.weight)
|
jane := Student{Human:Human{"Jane", 35, 100}, speciality:"Biology"}
|
||||||
fmt.Println("Her speciality is ", jane.speciality)
|
// ここで対応するフィールドにアクセスしてみます。
|
||||||
// 彼のskill技能フィールドを修正します。
|
fmt.Println("Her name is ", jane.name)
|
||||||
jane.Skills = []string{"anatomy"}
|
fmt.Println("Her age is ", jane.age)
|
||||||
fmt.Println("Her skills are ", jane.Skills)
|
fmt.Println("Her weight is ", jane.weight)
|
||||||
fmt.Println("She acquired two new ones ")
|
fmt.Println("Her speciality is ", jane.speciality)
|
||||||
jane.Skills = append(jane.Skills, "physics", "golang")
|
// 彼のskill技能フィールドを修正します。
|
||||||
fmt.Println("Her skills now are ", jane.Skills)
|
jane.Skills = []string{"anatomy"}
|
||||||
// 匿名ビルトイン型のフィールドを修正します。
|
fmt.Println("Her skills are ", jane.Skills)
|
||||||
jane.int = 3
|
fmt.Println("She acquired two new ones ")
|
||||||
fmt.Println("Her preferred number is", jane.int)
|
jane.Skills = append(jane.Skills, "physics", "golang")
|
||||||
}
|
fmt.Println("Her skills now are ", jane.Skills)
|
||||||
|
// 匿名ビルトイン型のフィールドを修正します。
|
||||||
上の例のとおり、structはstructを匿名フィールドとするだけでなく、自分で定義した型やビルトイン型も匿名フィールドとすることができます。また、対応するフィールド上で関数操作を行うこともできます(例えば例の中のappendです)。
|
jane.int = 3
|
||||||
|
fmt.Println("Her preferred number is", jane.int)
|
||||||
ここで一つ疑問がでてきます:もしhumanにphoneというフィールドがあったとすると、studentもphoneと呼ばれるフィールドができます。これはどうすべきでしょうか?
|
}
|
||||||
|
|
||||||
Goでは簡単にこの問題を解決することができます。外側が優先的にアクセスされますので、`student.phone`とアクセスした場合studentの中のフィールドにアクセスし、humanのフィールドにはアクセスしません。
|
上の例のとおり、structはstructを匿名フィールドとするだけでなく、自分で定義した型やビルトイン型も匿名フィールドとすることができます。また、対応するフィールド上で関数操作を行うこともできます(例えば例の中のappendです)。
|
||||||
|
|
||||||
このように匿名フィールドを通じてフィールドを継承することができます。当然もしあなたが対応する匿名型のフィールドにアクセスしたくなったら、匿名フィールドの名前からアクセスすることができます。下の例をご覧ください。
|
ここで一つ疑問がでてきます:もしhumanにphoneというフィールドがあったとすると、studentもphoneと呼ばれるフィールドができます。これはどうすべきでしょうか?
|
||||||
|
|
||||||
package main
|
Goでは簡単にこの問題を解決することができます。外側が優先的にアクセスされますので、`student.phone`とアクセスした場合studentの中のフィールドにアクセスし、humanのフィールドにはアクセスしません。
|
||||||
import "fmt"
|
|
||||||
|
このように匿名フィールドを通じてフィールドを継承することができます。当然もしあなたが対応する匿名型のフィールドにアクセスしたくなったら、匿名フィールドの名前からアクセスすることができます。下の例をご覧ください。
|
||||||
type Human struct {
|
|
||||||
name string
|
package main
|
||||||
age int
|
import "fmt"
|
||||||
phone string // Human型がもつフィールド
|
|
||||||
}
|
type Human struct {
|
||||||
|
name string
|
||||||
type Employee struct {
|
age int
|
||||||
Human // 匿名フィールドHuman
|
phone string // Human型がもつフィールド
|
||||||
speciality string
|
}
|
||||||
phone string // 社員のphoneフィールド
|
|
||||||
}
|
type Employee struct {
|
||||||
|
Human // 匿名フィールドHuman
|
||||||
func main() {
|
speciality string
|
||||||
Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
|
phone string // 社員のphoneフィールド
|
||||||
fmt.Println("Bob's work phone is:", Bob.phone)
|
}
|
||||||
// もし我々がHumanのphoneフィールドにアクセスする場合は
|
|
||||||
fmt.Println("Bob's personal phone is:", Bob.Human.phone)
|
func main() {
|
||||||
}
|
Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
|
||||||
|
fmt.Println("Bob's work phone is:", Bob.phone)
|
||||||
|
// もし我々がHumanのphoneフィールドにアクセスする場合は
|
||||||
## links
|
fmt.Println("Bob's personal phone is:", Bob.Human.phone)
|
||||||
* [目次](<preface.md>)
|
}
|
||||||
* 前へ: [フローと関数](<02.3.md>)
|
|
||||||
* 次へ: [オブジェクト指向](<02.5.md>)
|
|
||||||
|
## links
|
||||||
|
* [目次](<preface.md>)
|
||||||
|
* 前へ: [フローと関数](<02.3.md>)
|
||||||
|
* 次へ: [オブジェクト指向](<02.5.md>)
|
||||||
|
|||||||
Reference in New Issue
Block a user