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入門