Go言語のStruct

Goの中では、Structはとても重要です。JAVAのクラスのような扱いの感じです。
C言語でもStructがありますが、GoのStructの柔軟でいろいろな場面で利用できます。

#基本定義
Type struct名　struct {
   項目名１　型１
　 ...
   項目名n　型ｎ
}

例：

```go

type user struct {
	userId   int32
	userName string
}

func main() {
	fmt.Println(user{})
	fmt.Println(user{userId: 1000})
	fmt.Println(user{userName: "tanaka atsuko"})
	fmt.Println(user{userId: 2000, userName: "yahama tarou"})
}

```

初期化出力：
>{0 }
{1000 }
{0 tanaka atsuko}
{2000 yahama tarou}


structのデータ設定はjsonぽく設定できます。


#属性取得
変数名.項目名

例：

```go

type user struct {
	userId   int32
	userName string
}

func main() {
	var yamaha user = user{userId: 2000, userName: "yahama tarou"}

	fmt.Println(yamaha.userId)
	fmt.Println(yamaha.userName)
}
```

出力：
>2000
>yahama tarou

#structが値型で、参照型でない
structが値型なので、メソッドで渡す際には、ポインターにする必要があります。
ポインター指定しない例：

```go

type User struct {
	userId   int32
	userName string
}

func main() {
	var user User = User{userId: 2000, userName: "yahama tarou"}

	fmt.Println("修正前：", user)

	changeUserName(user)

	fmt.Println("修正後", user)
}

func changeUserName(user User) {
	user.userName = "tanaka hiroko"

	fmt.Println("メソッド内修正後", user)
}
```

出力：
>修正前： {2000 yahama tarou}
>メソッド内修正後 {2000 tanaka hiroko}
>修正後 {2000 yahama tarou}

変更メソッドを呼んでもstructの値は変更されません。

ポインター指定する例：

```go

type User struct {
	userId   int32
	userName string
}

func main() {
	var user User = User{userId: 2000, userName: "yahama tarou"}

	fmt.Println("修正前：", user)

	changeUserName(&user)

	fmt.Println("修正後", user)
}

func changeUserName(user *User) {
	user.userName = "tanaka hiroko"

	fmt.Println("メソッド内修正後", user)
}
```

出力：
>修正前： {2000 yahama tarou}
>メソッド内修正後 &{2000 tanaka hiroko}
>修正後 {2000 tanaka hiroko}

structの値は変更されました。

#毎回メソッドを呼び出す際に＆を付加したくない場合
初期化の際にアドレスを取得するように定義する。

例：

```go

type User struct {
	userId   int32
	userName string
}

func main() {
	user := &User{userId: 2000, userName: "yahama tarou"}

	fmt.Println("修正前：", user)

	changeUserId(user)
	changeUserName(user)

	fmt.Println("修正後", user)
}

func changeUserName(user *User) {
	user.userName = "tanaka hiroko"

	fmt.Println("メソッド内修正後", user)
}

func changeUserId(user *User) {
	user.userId = 3000

	fmt.Println("メソッド内修正後", user)
}

```

出力：
>修正前： &{2000 yahama tarou}
>メソッド内修正後 &{3000 yahama tarou}
>メソッド内修正後 &{3000 tanaka hiroko}
>修正後 &{3000 tanaka hiroko}


#匿名struct

```go

func main() {
	user := struct {
		userID   int32
		userName string
	}{
		userID:   2000,
		userName: "yamaha",
	}
	fmt.Println(user.userID)
	fmt.Println(user.userName)
}
```

出力：
>2000
>yamaha

アドレスを指定するように定義なら、下記でよいです。
user := struct {　⇒　user := &struct {


#embeded struct（匿名）

```go


type Address struct {
	prefecture, city, street string
}

type User struct {
	userID   int32
	userName string
	Address
}

func main() {

	user := User{
		userID:   1000,
		userName: "yahama",
	}

	user.Address.prefecture = "千葉県"
	user.Address.city = "千葉市"
	user.Address.street = "花見区"

	fmt.Println(user)
}
```

出力：
>{1000 yahama {千葉県 千葉市 花見区}}

embeded structは匿名structの場合は、「.」で値を付与します。

#embeded structの項目取得
方法１：変数名.項目名
方向２：変数名.struct項目名.項目名

例：

```go


type Address struct {
	prefecture, city, street string
}

type User struct {
	userID   int32
	userName string
	Address
}

func main() {

	user := User{
		userID:   1000,
		userName: "yahama",
	}

	user.Address.prefecture = "千葉県"
	user.Address.city = "千葉市"
	user.Address.street = "花見区"

	fmt.Println(user.prefecture)
	fmt.Println(user.Address.prefecture)
}
```

出力：
>千葉県
>千葉県

#struct型の項目

```go

type Address struct {
	prefecture, city, street string
}

type User struct {
	userID   int32
	userName string
	address  Address
}

func main() {

	user := User{
		userID:   1000,
		userName: "yahama",
		address: Address{
			prefecture: "千葉県",
			city:       "千葉市",
			street:     "花見区",
		},
	}

	fmt.Println(user.userName)
	fmt.Println(user.address.prefecture)
	fmt.Println(user)
}

```

出力：
>yahama
>千葉県
>{1000 yahama {千葉県 千葉市 花見区}}

ちなみに、このときはembededでないので、
user.prefectureで取得するとすると、下記のエラーになります。
user.prefecture undefined (type User has no field or method prefecture)

#匿名の項目名

```go

type User struct {
	int32
	string
}

func main() {
	user := User{
		1000,
		"yahama",
	}

	fmt.Println(user)
}
```

出力
>{1000 yahama}


#同じstructのデータのみ　「==」と「!=」で比較できる
```go

type User struct {
	int32
	string
}

func main() {
	user1 := User{
		1000,
		"yahama",
	}
	user2 := User{
		1000,
		"yahama",
	}
	user3 := User{
		2000,
		"yahama2",
	}

	fmt.Println(user1 == user2)
	fmt.Println(user1 == user3)
	fmt.Println(user1 != user3)
}
```

出力：
>true
>false
>true


以上