Javaなど他言語に存在するコンストラクタは、Goには存在しません。
それでも、オブジェクト指向ライクを実現するための慣習があります。
コンストラクタは、初期化処理ですが、goの場合、typeに関する初期化処理は、
typeで定義したstructの中身の頭文字が、大文字である場合、次のように書くことができます。
type Vertex struct { X, Y int } func main() { _ := Vertex{5, 8} }
しかし、typeで定義したstructの中身の頭文字が、小文字の場合、
外部packageからは参照することができません。
(structの型名の頭文字も同様です。)
これはtypeに限らず、変数やメソッドなどにも当てはまることで、
頭文字が小文字の場合、packageの中でしか使うことができない、いわばprivateの扱いになります。
そこで、外部には隠蔽されるtypeへのアクセス方法として、コンストラクタ風の慣習が用いられます。
package A type Vertex struct { x, y int } // package main import "./A" func NewVertex(x, y int) *Vertex { // コンストラクタ風の、ポインタを返す関数を定義 return &Vertex{x, y} // アドレスを返す } func main() { v := NewVertex(2, 3) // Vertexにアクセスできる fmt.Println(*v) // {2 3} vはポインタ型なので、*を付けて実体に直す }
New<type定義した型名>で、その型のポインタを返す関数を定義するのが慣習となっています。
ポインタで返すことで、一度変数に代入しなくてもメソッドを繋げることができます(メソッドチェーン)。
また、大きな構造体となると、値ではなく、ポインタの方がメモリの節約になります。
メソッドチェーンの例は次の通りです。
package A type Vertex struct { x, y int } // package main import "./A" func NewVertex(x, y int) *Vertex { return &Vertex{x, y} } func (v *Vertex) Scale(rate int) Vertex { return Vertex{v.x * rate, v.y * rate} } func main() { v := NewVertex(2, 3).Scale(5) // メソッドチェーン。NewVertex()が値を返す場合、エラーになる fmt.Println(v) // {10 15} }
intをtype定義する場合の例です。
package A type num int // package main import "./A" func NewNum(x num) *num { return &x // アドレスを返す } func (n *num) scale(x num) { *n = *n * x // nはポインタ型なので、*をつけて実体に直す } func main() { n := NewNum(2) n.scale(*n) // nはポインタ型なので、*をつけて実体に直す fmt.Println(*n) // 4 nはポインタ型なので、*をつけて実体に直す }
mapをtype定義する場合の例です。
package A type forMap map[string]string // package main import "./A" func NewForMap() *forMap { m := make(forMap, 2) m["国名"] = "不明" m["地域"] = "不明" return &m } func (fm *forMap) Asign(x, y string) { if fm == nil { // ポインタレシーバのメソッドは、 nil ポインタ変数からでも呼び出しが可能なため、panicを引き起こさないよう回避する return } (*fm)["国名"] = x // ポインタ型fmの実体にアクセスする (*fm)["地域"] = y // ポインタ型fmの実体にアクセスする } func main() { m := NewForMap() fmt.Println(*m) // map[国名:不明 地域:不明] m.Asign("アメリカ", "北米") fmt.Println(*m) // map[国名:アメリカ 地域:北米] }
Goのシンプルさについて from pospome
www.slideshare.net
※コンストラクタについて
【Java】 コンストラクタって何? this( )の意味 | 一番かんたんなJava入門