Goのレシーバを理解する
想定する読者
Javaはわかる、Goのレシーバをどう使うのか、な人
「任意の型に特化した関数」がポイント
以下の記事では、任意の型に特化した関数を定義するための仕組みと説明されている
これが全て。
つまりクラス
Goにはclassはないが、
user.Get、user.Post
address.Get、address.Postのように「まとまり感」を作りたい場合がある
以下のコードで説明する。
語弊を恐れずに、Javaとして読んでみて欲しい。
// レシーバのための型 → つまりこれがクラスってこと
type usr struct {
memberArg string // メンバ変数
}
// クラスで実装するメソッドの、interfaceを定義
type Usr interface {
Get()
Post(req string)
}
// コンストラクタ
func NewUsr() Usr { // 戻り値がクラス(レシーバ用の型)でなく、interfaceであることが重要
var member := "初期値"
return &usr{member}
}
// 実装
func (usr *usr) Get() {
// do something
}
func (usr *usr) Post(req string) {
// do something
}
レシーバ用の型 (ようはクラス) は、
・メソッド
・コンストラクタ
で参照されており、
usrという型ではUsrというinterfaceを使えて
実装は、レシーバを用いたメソッドで定義する。
1️⃣inteface-クラス間は、コンストラクタを書くことで初めてつながる。
// コンストラクタ
func NewUsr() Usr { // 戻り値がクラス(レシーバ用の型)でなく、interfaceであることが重要
var member := "初期値"
return &usr{member}
}
2️⃣メソッド-クラス間はレシーバでつながっている
func (usr *usr) Post(req string) {
Javaと比較
public interface UserInterface {
void get();
void post(String req);
}
public class User implements UserInterface {
private String memberArg; // メンバ変数
public void get() {
// do something
}
public void post(String req) {
// do something
}
}
Goでは
1️⃣inteface-クラス間は、コンストラクタを書くことで初めてつながる。
2️⃣メソッド-クラス間はレシーバでつながっている
Javaでは
1️⃣inteface-クラス間は、implementsで繋げている。
2️⃣メソッド-クラス間はクラスのカッコの中に書くことで繋げている。
Goではクラスという檻を嫌って、レシーバというものになった?ように思うし
パッケージ内で共有、というざっくりとした仕切りさえあれば、使う上では自由度が嬉しい。
考察
そもそもオブジェクト指向なのか?という議論もあるくらいで
Javaと比べることがおかしいようにも思えるが、以下の記事で
とある。
確かに長年Javaを触っていても、interface見たところでJavaDocがしっかりでもしていなければ
結局実装を見るために面倒な検索をしなくてはいけない、といった経験が多数あります。
個人的に、わかりやすさがより重視されているなと思った反面、
レシーバというものをイマイチ使う気にならず、いっそパッケージをクラスがわりにしちゃえば?と思ったり。
(流石にフォルダ増えすぎるので非現実的ですが、、)
どう活かせばいい?
やはりまとまり感を出すために使えばいいだろう。
以下を1ファイルとして、Javaクラスファイルのように扱って行けばよさそう
package service
import (
// some
)
// =========================
// define struct
// =========================
// for reciever
type usr struct {
// member
}
type Usr interface {
// interface
}
func NewUsr() Usr {
return &usr{}
}
// =========================
// Imprementation
// =========================
func (usr *usr) Get() {
// do something
}
func (usr *usr) Post(req string) {
// do something
}
GinなんかではPOST等を登録する際に以下のようにまとまり感を出すことができる
package main
import (
// 割愛
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// user系サービスの登録
rg := r.Group("/user")
usr := service.NewUsr()
rg.GET("/get", usr.Get)
rg.POST("/post", usr.Post)
// address系サービスの登録
rg := r.Group("/address")
address := service.NewAddress()
rg.POST("/get", address.Get)
rg.POST("/post", address.Post)
r.Run(":8080")
}
といった具合で活用できる
ALHについて知る
↓ ↓ ↓ 採用サイトはこちら ↓ ↓ ↓
↓ ↓ ↓ コーポレートサイトはこちら ↓ ↓ ↓
↓ ↓ ↓ もっとALHについて知りたい? ↓ ↓ ↓