地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

Goで学ぶポインタ

Go言語でWebアプリケーションを作る時に、 必ず使うと思われる概念が「構造体」「ポインタ」です。 元々、オブジェクト指向の言語(Ruby)を勉強していたこともあり Go言語を勉強し始めて、一番最初に苦戦した箇所です。。。 今回は非常にざっくりですが、 「構造体」「ポインタ」についてまとめました。

構造体とは

Go言語のデータ構造をざっくり分類すると、 「基本型」「配列型」「関数型」「参照型」「ポインタ型」 といったものに分けられます。 「構造体」は、こうした多様なデータ構造を1つの「型」として取り扱うことができるものです。 => 「複数の型の値を1つにまとめられるもの」 ということです。 Go言語で何かを作ろうとしたとき、 この構造体と関数を色々と使って、開発することが多くなるのではないかと思います。 実際に、どういったものか見ていきます。

■構造体を定義する 以下のように、予約語である「type」「struct {}」を用いて定義します。

package main

import (
  "fmt"
)

type Sample struct {
  X int
  Y int
}

func main() {
  var s Sample
  fmt.Print(s.X)
  fmt.Print(s.Y)
}


/* 出力結果
0
0
*/ 

「type」は既存の方にエイリアスを付けられるものであり、 構造体の定義は、「struct {}」で定義したフィールドにtypeを使って名前をつけたといったイメージです。

ポインタ

「*int」といったように、参照・操作したい型にの前に「*」を付けることで定義できます。 ポインタの役割は、値型等に対して、間接的に参照・操作できるようにすることです。 Rubyをやってきた身としてはなかなかとっつきにくいものでしたが、 実際に手を動かしてやっていくと、自然と慣れてくるものでした! 演算子&を使うことで、任意の型からポインタ型を生成できます。

構造体とポインタ

構造体は、値型であるため 関数の引数で、構造体を渡した場合に、その構造体のコピーが生成されてしまい、 関数は、元の構造体に何ら影響を与えません。 そこで、ポインタを渡すように変更することで、対応します! →このパターンはめちゃめちゃ使ってます。技術書とかをみてもこればっかりです。 以下、コードです。

package main

import (
  "fmt"
)

type Sample struct {
  X int
  Y int
}

func exchangeSample(s *Sample) {
  x, y := s.Y, s.X
  s.X = x
  s.Y = y
}

func main() {
  s := Sample{X: 1, Y: 2}
  exchangeSample(&s)
  fmt.Print(s.X)
  fmt.Print(s.Y)
}

/*出力結果
2
1 =>逆になってる!!! 
*/

メソッド

最後に、こちらもGo言語での開発において頻出となる「メソッド」です。 コードを見たほうが理解が進むと思うので、早速コードから。

package main

import "fmt"

type Sample struct {
  X, Y int
}

//こちらがメソッド
func (s *Sample) renderValue() {
  fmt.Print(s.X)
  fmt.Print(s.Y)
}

func main() {
  s := Sample{X: 1, Y: 2}
  s.renderValue()
}

/*出力結果
1
2
*/

なにやら関数に似ていますが、 関数と違うところは、「レシーバーの型」「変数名」があることです。 今回でいうところの「*Sample」と「s」です。 なにやらRubyインスタンスメソッドのようにも思えます。

まとめ

構造体とポインタについてざっくりではありますが、まとめてみました。 「構造体」「ポインタ」そして「メソッド」は、Go言語に使ったWeb開発では 避けては通れないものなので、しっかり抑えておく必要がありそうです...

参考資料

Webの記事 お気楽 Go 言語プログラミング入門 Golang 構造体と仲良くなろう

書籍 スターティングGo言語 Go言語によるWebアプリケーション開発