ポインタや構造体を勉強する。
ポインタと言えばC言語が代表的ですが、Go言語でも使えます!
C言語から書きやすいとよく聞くGo言語ですが、Printf/Scanfに限らずC言語と共通する点が多く、私自身もC言語を長く触っている身としては入りやすいですね…
ポインタを使ってみる
試しにポインタを使ってみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package main import "fmt" func main() { // ポインタを宣言 var pointer *int // 数字の変数を宣言 num := 100 // ポインター変数に格納 pointer = &num // 出力 fmt.Printf("&num:\t\t%v\n", &num) // num変数のアドレスを表示 fmt.Printf("pointer:\t%v\n", pointer) // 格納されているアドレスを表示 fmt.Printf("num:\t\t%v\n", num) // num変数の値を表示 fmt.Printf("*pointer:\t%v\n", *pointer) // アドレスに格納されている値を表示 return } |
一度実行してみてもらうと分かると思うのですが、
&
オペレータはその変数(オペランド)へのポインタを引き出す*
オペレータはポインタの指す先の変数を指す
といった感じで、基本的にはC言語のポインタと変わりません。
因みに、オペレータ・オペランドという言葉をよく聞くのですが、日本語で表すと
- オペレータ:演算子のこと。
- オペランド:被演算子のこと。要は演算子の対象となる変数や値のこと。
といった感じです。個人的にはカタカナより日本語の方が理解しやすいので、演算子・被演算子と書いて欲しいですね()
因みに、初期値には nil、要は空ということです。
初期値の状態でポインタの値を引き出そうとするとエラーになるので注意してください。
構造体
構造体とは?
一言で表すと「1つもしくは複数の値をまとめて格納できる型」です!
上の言葉で連想すると配列も似た特性を持っている気がしますが、配列と違い、それぞれの値に異なる型を指定することが可能です。このとき、それぞれの変数をフィールド(またはメンバ)と呼びます。
構造体の使い方
まずは定義の方法です。
1 2 3 4 |
type 構造体名 struct { フィールド1 int フィールド2 string } |
実際に定義するとこのようになります。
1 2 3 4 |
type Size struct{ height int width int } |
実際に変数に格納したりアクセスするにはこのように記述します。
1 2 3 4 5 6 |
func main(){ // 変数に格納 変数 := 構造体名{値1, 値2} // 構造体のメンバにアクセスする fmt.Println(変数.フィールド1) } |
さっきの宣言時の例と合わせるとこのようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package main import "fmt" // 構造体を定義 type Size struct{ height int width int } func main() { // 宣言 contents := Size{100, 200} // 高さを変更 contents.height = 300 // 出力 fmt.Printf("height: %v\n", contents.height) fmt.Printf("width : %v\n", contents.width) } |
構造体をポインタでアクセス
以下のように構造体もポインタを使用してアクセスできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package main import "fmt" // 構造体を定義 type Size struct{ height int width int } func main() { // 宣言 contents := Size{100, 200} // 高さを変更 ptr := &contents // ポインタを通して代入 ptr.height = 150 // 通常の出力 fmt.Printf("contents : %v\n", contents) // ポインタを通してアクセスして出力 fmt.Printf("ptr : %v\n", *ptr) } |
この辺りは冒頭で紹介したポインタの扱い方と同じです。
構造体も通常の変数のようにポインタでのアクセスが可能です。
初期値の割り当て
構造体の変数を宣言する際、必ずすべての値を初期化する必要はありません。
例えば、特定の値のみを指定して代入(Name:構文)したり、何も代入しなければ通常の変数と同じゼロ値が代入されます。
また、宣言時に & を付けることで、初めからポインタ変数へポインタを渡すことも可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package main import "fmt" // 構造体を定義 type Size struct{ height int width int } func main() { // 通常の宣言 content1 := Size{100, 200} // フィールドの一部のみ列挙 content2 := Size{width: 200} // 指定なし(初期値:ゼロ値) content3 := Size{} // 新しく割り当てられた構造体へのポインタを ptr := &Size{15, 15} // 出力 fmt.Printf("content1 : %v\n", content1) // content1 : {100 200} fmt.Printf("content2 : %v\n", content2) // content2 : {0 200} fmt.Printf("content3 : %v\n", content3) // content3 : {0 0} fmt.Printf("ptr : %v\n", *ptr) // ptr : {15 15} } |
〆
今回はポインタと構造体を勉強しました。
両方ともC言語と基本的な考え方は似ていて、CやC++を触ったことがあると使いやすい風に感じました。その中でも違いもあるので、言語毎の違いを混同しないようにしないといけませんね…
参考にした記事
オペレータ 【 operator 】 – IT用語辞典e-Words
今回のブログ曲
今回投稿中に聴いていた曲はこちら