
はじめに
プログラミング言語の中でも、Go言語(Golang)は比較的新しい言語でありながら注目度を高めています。その背景には高い保守性と柔軟なコード設計を支える独特の言語仕様があると考えられます。
本記事では、PHPと比較しながらGo言語の設計思想を解説していきます。メソッドの定義方法、継承と合成の違い、そしてポリモーフィズムの実現方法を具体的なコード例とともに取り上げ、オブジェクト指向経験者でも理解しやすい形でGoの特徴を掘り下げます。
Go言語の最大の特徴とは?
多くのオブジェクト指向言語では、クラスを定義し、それを継承して機能を拡張します。
一方、Goにはクラスや継承の概念がありません。その代わりに「構造体(struct)」と「インターフェース」を組み合わせてプログラムを設計します。
この設計により、以下のような利点があります。
- 依存関係が少ないため保守しやすい
- 機能の合成が容易で、柔軟なコード設計が可能
- テストがしやすい
構造体とは?
Goの構造体の説明に入る前に、まず以下のGoで書かれたコードに注目してください。
sample.goheight := 170 // 太郎の身長
age := 30 // 太郎の年齢
fmt.Println(age) // 「30」と出力される
Go言語では、他の言語と同じようにデータを扱うときは変数を使うことが可能です。ここでは太郎さんの身長と年齢の情報を用意し、年齢を標準出力しています。
ただ、以上のような例では太郎さんの身長と年齢が個別の変数で定義されているため、データをまとめて管理することが難しくなります。
このような問題に対して、Goでは「構造体」を使うことでバラバラのデータを1つにまとめることができます。
sample.gotype Person struct {
Height int
Age int
}
taro := Person{
Height: 170,
Age: 30,
}
fmt.Println(taro.Age) // 「30」と出力される
このように、Goの構造体は「複数の値を1つにまとめる」仕組みです。PHPのクラスに似た役割を果たします。
ここまでを踏まえて、Goの構造体とPHPのクラスの共通点をまとめると以下のようになります。
構造体とクラスの共通点
- データをまとめる
複数の値(フィールド)を1つのまとまりとして扱える - メソッドを定義できる
フィールドに対する操作を定義できる - インスタンスを生成できる
個別の「オブジェクト」を生成できる
また、Goの構造体とPHPのクラスの違いをまとめると以下のようになります。
構造体とクラスの相違点
PHPのクラス | Goの構造体 | |
---|---|---|
メソッドの定義方法 | クラスの中で定義する | クラスの外で定義する |
コードの再利用方法 | 継承 | 埋め込み(合成) |
ポリモーフィズムの実現方法 | インターフェースを明示的に実装 | インターフェースを暗黙的に実装(メソッドが一致すればOK) |
次章からは、この「メソッドの定義方法」、「コードの再利用方法」、「ポリモーフィズムの実現方法」それぞれについてより詳しく解説していきます。
PHPとGoのメソッド定義方法の違い
PHPではクラス内にメソッドを定義します。一方、Goでは構造体の外でメソッドを定義して紐づけます。
この違いはコードの依存関係や再利用性に大きな影響を与えます。Goの方法は疎結合を実現しやすく、保守性が高まります。
以下にPHPのクラスとGoの構造体それぞれのメソッド定義方法を紹介します。
PHPの例(クラス)
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function greet() {
return "Hello, " . $this->name;
}
}
Goの例(構造体)
type User struct {
Name string
}
func (u User) Greet() string {
return "Hello, " + u.Name
}
func main() {
user := User{Name: "Taro"}
fmt.Println(user.Greet())
// "Hello, Taro"
}
両者とも「名前を持つユーザーを表現」し、greet メソッドで挨拶を返すという共通点があります。ただし、Goでは メソッドを構造体の外に定義して紐づけるのが特徴です。
コードの再利用方法の違い ― 継承と合成
PHPの場合
PHPでは継承によって親クラスの機能を子クラスに引き継ぎます。しかし、継承は親クラスの変更が子クラスに波及しやすいため、保守が難しくなることがあります。
PHPの例(クラス)
class Animal {
public function eat() {
echo "食べる\n";
}
}
class Dog extends Animal {
public function speak() {
echo "ワンワン!";
}
}
Goの場合
Goでは構造体に別の構造体を埋め込む「合成(埋め込み)」を使って構造体同士を組み合わせます。必要な機能だけを柔軟に取り込めるため、より保守しやすい設計が可能です。
Goの例(構造体)
type Animal struct{}
func (a Animal) Eat() {
fmt.Println("食べる")
}
type Dog struct {
Animal
}
func (d Dog) Speak() {
fmt.Println("ワンワン!")
}
継承は便利な反面、親クラスの変更が子クラスに波及しやすく保守性が下がることがあります。Goの「合成」は必要な機能だけを組み合わせるため、変更の影響範囲を限定でき、保守しやすいのが利点です。
ポリモーフィズムの実現方法の違い ― 明示的 vs. 暗黙的な実装
PHPの場合
PHPではインターフェースを明示的に実装しなければなりません。
PHPの例(クラス)
interface Animal {
public function speak(): string;
}
class Dog implements Animal {
public function speak(): string {
return "ワンワン";
}
}
Goの場合
Goでは暗黙的にポリモーフィズムを実装できます。
構造体のメソッドがインターフェースのメソッドと一致していれば、構造体は自動的にインターフェースを実装したことになるため、コードをシンプルに保ちながら柔軟性を確保できます。
Goの例(構造体)
type Animal interface {
Speak() string
}
type Dog struct{}
func (d Dog) Speak() string {
return "ワンワン"
}
この仕組みにより、開発者は「インターフェースを実装している」ことを明示しなくても自然にポリモーフィズムを実現できます。結果として疎結合なコードが書きやすく、テストや再利用の柔軟性が向上します。
Go言語の最大の特徴
改めてGoの構造体とPHPのクラスの違いをまとめます。
構造体とクラスの相違点
PHPのクラス | Goの構造体 | |
---|---|---|
メソッドの定義方法 | クラスの中で定義する | クラスの外で定義する |
コードの再利用方法 | 継承 | 埋め込み(合成) |
ポリモーフィズムの実現方法 | インターフェースを明示的に実装 | インターフェースを暗黙的に実装(メソッドが一致すればOK) |
Go言語の設計思想のメリット
PHPでは継承とインターフェースを使って共通処理を定義しますが、Goでは構造体とインターフェースを組み合わせて共通処理を実現します。この設計により、構造体間の結合度が低く(疎結合)、柔軟で依存性の少ないコードを書くことができます。これにより、テストが容易になり、長期的な保守コストを抑えやすくなります。
最後に
GoはPHPなどのオブジェクト指向言語と比べて特殊な仕組みを持ちますが、その分シンプルで保守しやすいコードが書ける言語です。これから需要が伸びる可能性の高い言語のひとつでもあるので、学んでみる価値は十分にあるでしょう。