Goの中では、Structはとても重要です。JAVAのクラスのような扱いの感じです。
C言語でもStructがありますが、GoのStructの柔軟でいろいろな場面で利用できます。
基本定義
Type struct名 struct {
項目名1 型1
...
項目名n 型n
}
例:
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ぽく設定できます。
属性取得
変数名.項目名
例:
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が値型なので、メソッドで渡す際には、ポインターにする必要があります。
ポインター指定しない例:
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の値は変更されません。
ポインター指定する例:
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の値は変更されました。
毎回メソッドを呼び出す際に&を付加したくない場合
初期化の際にアドレスを取得するように定義する。
例:
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
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(匿名)
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の項目取得
方法1:変数名.項目名
方向2:変数名.struct項目名.項目名
例:
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型の項目
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)
匿名の項目名
type User struct {
int32
string
}
func main() {
user := User{
1000,
"yahama",
}
fmt.Println(user)
}
出力
{1000 yahama}
同じstructのデータのみ 「==」と「!=」で比較できる
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
以上