259
152

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Go】基本文法③(ポインタ・構造体)

Last updated at Posted at 2018-08-08

概要

A Tour of Goの順番に沿ってGoの基本で個人的に学習したことをまとめています。

No 記事
1 【Go】基本文法①(基礎)
2 【Go】基本文法②(フロー制御文)
3 〜〜【Go】基本文法③(ポインタ・構造体)「今ココ」〜〜
4 【Go】基本文法④(配列・スライス)
5 【Go】基本文法⑤(Maps・ Range)
6 【Go】基本文法⑥(インターフェース)
7 【Go】基本文法⑦(並行処理)
8 【Go】基本文法総まとめ

今回はポインタと構造体に焦点を当てて学習しました。

ポインタ

ポインタとは?

ポインタはメモリのアドレス情報のことです。
詳しい説明は以下のリンクがとても参考になりました。

【参考】

package main

import "fmt"

func main() {
    var var1 int = 10
    var var2 *int = &var1
    fmt.Println(var1) //=> 10
    fmt.Println(var2) //=> 0x10414020   
    fmt.Println(*var2) //=> 10
}

変数のアドレス取得方法

Goでは& を用いることで変数のアドレスの取得が可能です。
例えば &var1 で変数 var1 のアドレスを取得することが可能です。

func main() {
    var var1 int = 10
    var var2 *int = &var1
    fmt.Println(var1) //=> 10
    fmt.Println(var2) //=> 0x10414020   
}

上記では変数 var1 のアドレスを ポインタ型変数var2 に入れてその値(0x10414020)を表示しています。
次にポインタ型変数とは何か理解します。

ポインタ型とは?

メモリー上のアドレスを記憶する変数の型のこと です。
サンプルコード上の *int がポインタ型を示します。

var var2 *int = &var1

ポインタ型変数とは?

ポインタ型で宣言された変数のこと です。
つまり、メモリ上のアドレスを値として入れられる変数のこと です。
ポインタ型にしたい変数に * をつけて宣言します。

var var1 int      //int型
var var2 *int    //int型へのポイント型

サンプルコード上の var2 がポインタ型変数を示します。
初期値が指定されていない場合、Go 言語のポインタは nil (nil ポインタ) に初期化されます。

【参考】ポインタ型変数とは

ポインタ型変数の中身へのアクセス方法

ポインタ型変数名の前に * をつけることで変数の中身へのアクセスが可能です。
例えば *var2 とすることで var2 の値の参照が可能です。

func main() {
    var var1 int = 10
    var var2 *int = &var1
    fmt.Println(*var2) //=> 10
}

Structs(構造体)

構造体とは?

Goにはオブジェクト指向言語におけるclassというものは存在しません。
似た役割として関連する情報をひとまとめにする struct(構造体) が使用されます。

構造体の定義方法

構造体は下記のように typestruct を使用して定義します。

package main 

import "fmt"

type Person struct {
   firstName string 
   age int
}

構造体の初期化方法

構造体の初期化方法は複数存在します。

  • ①変数定義後にフィールドを設定する方法
  • {} で順番にフィールドの値を渡す方法
  • ③フィールド名を で指定する方法

上から順に初期化の方法を確認します。

①変数定義後にフィールドを設定する方法

type Person struct {
   firstName string 
   age int
}

func main(){
  var mike Person
  mike.firstName = "Mike"
  mike.age = 20
  fmt.Println(mike.firstName, mike.age) //=> Mike 20
}

{} で順番にフィールドの値を渡す方法

type Person struct {
   firstName string 
   age int
}

func main(){
  bob := Person{"Bob", 30}
  fmt.Println(bob.firstName, bob.age) //=>Bob 30
}

③フィールド名を で指定する方法

type Person struct {
   firstName string 
   age int
}

func main(){
  sam := Person{age: 15, firstName: "Sam"}
  fmt.Println(sam.firstName, sam.age) //=>Sam 15
}

また以下のように初期化関数を作成することで初期化をすることも一般的に行われます。

type Person struct {
   firstName string 
   age int
}

func newPerson(firstName string, age int) *Person{
     person := new(Person)
	 person.firstName = firstName
	 person.age = age
	 return person
}

func main(){
  var jen *Person = newPerson("Jennifer", 40)
  fmt.Println(jen.firstName, jen.age) //=>Jennifer 40
} 

構造体とポインタ

struct のフィールドは、struct のポインタを通してアクセスすることもできます。

package main

import "fmt"

type Person struct {
  firstName string
  age int
}

func main() {
	tim := Person{"Tim", 25}
	person1 := &tim
	(*person1).age = 25
	person1.age = 53 //shortcutでp.Xと書くことも出来る
	fmt.Println(person1) //=> {Tim 53}
}

構造体でのメソッドの定義

Goにはクラスと言う概念は存在しませんが、構造体内にメソッド method を定義できます。
普通の関数と違うのはレシーバ引数の部分だけです。

メソッドは以下の様に定義することができます。

func (<レシーバ引数>) <関数名>([引数]) [戻り値の型] {
    [関数の本体]
}

実際に Person という構造体に対して intro というメソッドを定義してみます。

type Person struct {
   firstName string 
   age int
}

func (p Person) intro(greetings string) string{
    return greetings + " I am " + p.firstName
}

func main(){
  bob := Person{"Bob", 30}
  fmt.Println(bob.intro("Hello")) //=> Hello I am Bob
}

上記の例では intro メソッドは p という名前の Person 型のレシーバを持つことを意味しています。

構造体の埋め込み

上記で何度も記した通り、Goはオブジェクト指向言語の様なクラスを持ちません。
ですのでクラスの継承も存在しません。
そこで継承に似た機能として構造体の埋め込みがあります。

package main 

import "fmt"

type Person struct {
   firstName string 
}

func (a Person) name() string{ //Personのメソッド
    return a.firstName
}

type User struct {
     Person
}

func (a User) name() string { //Userのメソッド
    return a.firstName
}

func main(){
  bob := Person{"Bob"}
  mike := User{}
  mike.firstName = "Mike"
  
  fmt.Println(bob.name()) //=> Bob
  fmt.Println(mike.name()) //=> Mike
}

参考

My Jorney of Go③
C言語のポインタきらい
Goで学ぶポインタとアドレス
メソッドの定義方法
ポインタ型変数とは
Goのinterface/structの埋め込み
お気楽 Go 言語プログラミング入門

259
152
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
259
152

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?