カテゴリ: Go言語 更新日: 2026/02/13

Go言語の構造体にメソッドを定義する方法をやさしく解説

Go言語の構造体にメソッドを定義する方法をやさしく解説
Go言語の構造体にメソッドを定義する方法をやさしく解説

先生と生徒の会話形式で理解しよう

生徒

「Go言語で、あるデータに動きをつける方法ってありますか?例えば、人の情報に“挨拶する”みたいな動作を持たせたいんです。」

先生

「とても良い視点ですね。Go言語では“構造体”というデータのまとまりに、“メソッド”という形で動作(関数)を定義することができますよ。」

生徒

「なるほど!でも、その“メソッド”ってどうやって書くんですか?」

先生

「それでは、構造体とメソッドの基本的な使い方を一緒に学んでいきましょう!」

1. 構造体とは?

1. 構造体とは?
1. 構造体とは?

Go言語の構造体(struct)とは、複数の情報をひとまとめにして扱える自分専用のデータ型です。「名前」「年齢」「職業」など、関連するデータを1セットにできるので、バラバラの変数で管理するより圧倒的に分かりやすく整理できます。

イメージとしては、ノートに項目ごとに情報を書き込むようなものです。例えば、人の情報をひとまとめにしたい場合、次のように定義します。


type Person struct {
    Name string
    Age  int
}

Personという構造体には、名前を入れるName、年齢を入れるAgeの2つの項目(フィールド)が含まれています。これを使えば、1人分の情報をひとつの変数で表現でき、複数人のデータ管理もスムーズになります。

例えば次のように値を入れれば、1人の情報をまとめて扱えます。


p1 := Person{Name: "太郎", Age: 20}

このように構造体を使うと、プログラムの見通しが良くなり、ミスも減らせます。特に初心者でも理解しやすく、現場でも頻繁に使われるとても重要な仕組みです。

2. メソッドとは?関数との違いを知ろう

2. メソッドとは?関数との違いを知ろう
2. メソッドとは?関数との違いを知ろう

メソッドは、特定の構造体(データのまとまり)に結びつけて定義する「そのデータ専用の関数」です。関数との一番の違いは、レシーバ(receiver)と呼ばれる「どの構造体に属する動きなのか」を明示できる点にあります。関数は単独で呼び出しますが、メソッドは「変数.メソッド名」という形で、そのデータと一緒に呼び出します。

たとえば「人があいさつする」という動きは、Personという構造体にくっついているほうが読みやすく、コードの意味も伝わりやすくなります。下の短いサンプルで、関数とメソッドの書き方・呼び出し方の違いを見てみましょう。


package main

import "fmt"

type Person struct {
    Name string
}

// 関数:データ(構造体)を引数で受け取って処理する
func GreetFunc(p Person) {
    fmt.Println("こんにちは、私は", p.Name, "です。")
}

// メソッド:構造体に結びついた関数(レシーバで所属を明示)
func (p Person) Greet() {
    fmt.Println("こんにちは、私は", p.Name, "です。")
}

func main() {
    user := Person{Name: "太郎"}

    // 関数の呼び出し(データを渡す)
    GreetFunc(user)

    // メソッドの呼び出し(データに対する動きとして呼ぶ)
    user.Greet()
}

どちらも同じメッセージを表示しますが、呼び出し方が異なります。関数版は「処理したい対象を引数として渡す」のに対し、メソッド版は「対象となるデータに対して動きを呼び出す」書き方になります。これにより、「この動きはこのデータの責務」という関係がはっきりし、読み手が意図を追いやすくなります。実際の開発では、データに密接した処理はメソッドにまとめると、コードの見通しや再利用性が高まり、チーム開発でも理解しやすい構成になります。

3. メソッドの定義方法

3. メソッドの定義方法
3. メソッドの定義方法

メソッドは、funcのあとに置くレシーバ(receiver)で「どの構造体に属する処理か」を宣言してから、メソッド名・引数・戻り値を続けて書きます。レシーバは丸かっこで包み、左に変数名、右に型名を書きます(例:(p Person))。この形にすることで「Personに結びついた処理」であることがひと目でわかり、コードの読みやすさと保守性がぐっと上がります。

まずは最小の例です。Personというデータに「あいさつする」という動きを生やします。レシーバは値レシーバを使い、読み取り専用の振る舞いを定義しています。


type Person struct {
    Name string
    Age  int
}

// Personに紐づくメソッド(レシーバ:p Person)
func (p Person) Greet() {
    fmt.Println("こんにちは、私の名前は", p.Name, "です。")
}

ここでのポイントは、(p Person)という宣言が「この関数はPersonのメソッドである」ことを示している点です。呼び出すときは、変数.Greet()のように「データに対して動作を呼ぶ」書き方になります(呼び出し例は後続セクションで登場します)。

次に、引数や戻り値を持つメソッドの書き方です。メッセージの形式を選べるよう、引数で指定して文字列を返す例を示します。定義の位置は通常の関数と同じで、パッケージ内であればどこに置いてもかまいません。


func (p Person) FormatGreet(prefix string) string {
    msg := prefix + "、私は" + p.Name + "です。"
    return msg
}

このように、レシーバを使うことで「どのデータに属するふるまいか」を明確にできます。メソッド名は目的が伝わる動詞や名詞を選ぶと読みやすく、構造体の責務も自然に整理されます。まずは小さな動きからメソッド化して、データと処理をセットで考える習慣を身につけていきましょう。

4. メソッドを使ってみよう!

4. メソッドを使ってみよう!
4. メソッドを使ってみよう!

構造体を作成してメソッドを呼び出すには、以下のように書きます。


package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// Person型にGreetというメソッドを定義
func (p Person) Greet() {
    fmt.Println("こんにちは、私の名前は", p.Name, "です。")
}

func main() {
    p1 := Person{Name: "太郎", Age: 20}
    p1.Greet() // メソッド呼び出し
}

実行結果:


こんにちは、私の名前は 太郎 です。

5. 値レシーバとポインタレシーバの違い

5. 値レシーバとポインタレシーバの違い
5. 値レシーバとポインタレシーバの違い

メソッドを定義する際、レシーバを値渡しにするか、ポインタ渡しにするかを選べます。

値レシーバは、構造体のコピーが渡されるので、元のデータは変更されません。一方、ポインタレシーバでは、元のデータを直接変更できます。


func (p *Person) Birthday() {
    p.Age += 1
}

このように*Personと書くことで、ポインタ(元のデータ)に対して操作できます。

6. ポインタレシーバの実例

6. ポインタレシーバの実例
6. ポインタレシーバの実例

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func (p *Person) Birthday() {
    p.Age += 1
}

func main() {
    p1 := Person{Name: "花子", Age: 25}
    p1.Birthday()
    fmt.Println(p1.Name, "は", p1.Age, "歳になりました。")
}

実行結果:


花子 は 26 歳になりました。

ポイント:ポインタレシーバを使うと、構造体の内容を書き換えることができます。年齢のように「増やしたい」「変更したい」データにはポインタレシーバが便利です。

7. レシーバ名は自由に決めていいの?

7. レシーバ名は自由に決めていいの?
7. レシーバ名は自由に決めていいの?

レシーバの変数名は自由に決められますが、一般的には構造体名の頭文字の小文字を使うことが多いです。例えば、Personならpという名前にするのが慣例です。

ただし、意味がわかりやすければ他の名前でも問題ありません。

8. メソッドを使うとコードが読みやすくなる理由

8. メソッドを使うとコードが読みやすくなる理由
8. メソッドを使うとコードが読みやすくなる理由

構造体にメソッドを定義することで、「この動作はこのデータに関係している」とはっきり分かるようになります。

例えば、Greetという動作がPersonにあることで、「この人があいさつするんだな」と一目でわかります。プログラムが大きくなっても、整理されたコードになります。

まとめ

まとめ
まとめ

Go言語で構造体にメソッドを定義するという考え方は、一見むずかしいように感じますが、実際のプログラムで手を動かしてみると「データ」と「動作」がセットになることで理解が深まります。とくに、名前や年齢のような情報を持った構造体に挨拶の動作を追加する例は、はじめて学ぶ人にもイメージしやすく、実践的です。構造体はフィールドをまとめる箱のような役割を持ち、メソッドはその箱から取り出したデータに振る舞いを与えるという仕組みです。この「データ」と「動き」がつながっていることこそが、大規模なプログラムで役立つポイントになります。

さらに、値レシーバとポインタレシーバの違いは、Go言語ならではの特徴といえます。値レシーバでは元の値が変わらないため、安全に読み取りができ、ポインタレシーバでは直接書き換えができるため「年齢を増やす」「ポイントを加算する」など、更新を伴う処理で大活躍します。実際に動かして比べてみると、コードの見た目はほとんど同じなのに、挙動が大きく変わる点はとても興味深いところです。

また、レシーバ名の付け方も自由に決められますが、慣習として構造体名の頭文字を小文字にすることで読みやすさが保たれます。チームで開発する場合は、このような小さな決まりが積み重なることで読みやすいプログラムへとつながります。メソッドが増えても、型ごとに動きがまとまっていれば、あとからコードを読む人にも親切です。構造体とメソッドが組み合わさることで、Go言語のプログラムは「意味のあるかたまり」になり、自然に整理されたコードへ近づいていきます。

以下は、学んだ内容をまとめた最終サンプルです。構造体とメソッドを組み合わせ、挨拶と誕生日の処理をまとめて書くと、どのデータにどんな操作ができるのかが読み手に伝わりやすくなります。

サンプルプログラムまとめ


package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// あいさつするメソッド(値レシーバ)
func (p Person) Greet() {
    fmt.Println("こんにちは、私の名前は", p.Name, "です。")
}

// 年齢をひとつ増やすメソッド(ポインタレシーバ)
func (p *Person) Birthday() {
    p.Age += 1
}

func main() {
    p := Person{Name: "太郎", Age: 20}

    // あいさつ
    p.Greet()

    // 年齢を増やす
    p.Birthday()
    fmt.Println(p.Name, "は", p.Age, "歳になりました。")
}

このサンプルのように、「自分というデータが自分であいさつをする」「年齢をひとつ増やす」といった動作が、構造体の中に自然におさまります。もし値レシーバとポインタレシーバの違いがあいまいなままであれば、実際に値が変わるかどうかを画面に出力して確かめてみると理解が深まります。人の情報を表す構造体は、住所やメールアドレス、会員ランクなどを追加していけば、より豊かな例に発展させることができます。こうしてメソッドを活用していけば、Go言語のプログラムは「人間が読んで理解しやすいもの」へと育っていくのです。

先生と生徒の振り返り会話

生徒

「構造体とメソッドを組み合わせることで、データと動きをひとまとめにできるというのが、やっとわかってきました。人にあいさつさせる例が、とてもイメージしやすかったです。」

先生

「良い気づきですね。データのそばに、そのデータ専用の処理を置くことで、コードが自然な文章のように読めるようになります。大きな開発になるほど、この考え方が役に立ちますよ。」

生徒

「値レシーバとポインタレシーバの違いも、理解できました。年齢を増やす処理はポインタじゃないと書き換わらないというのも納得です。」

先生

「その通りです。データを変えるならポインタ、読み取るだけなら値を渡す。ただそれだけですが、使い分けるとプログラムがより安全でわかりやすくなります。」

生徒

「今回の内容をもとに、招待状を送るメソッドや、会員のランクを変更するメソッドなど、いろいろ試してみたくなりました。」

先生

「とても良いですね。まずは小さな例から、自分なりの構造体とメソッドを作っていくと自然と理解が深まりますよ。」

Go言語を基礎からスッキリ学びたい人や、 文法だけでなく「実用的な使い方」まで押さえたい人には、 定番の入門書がこちらです。

基礎からわかるGo言語をAmazonで見る

※ Amazon広告リンク

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

Go言語の構造体とメソッドの違いがいまいち分かりません。初心者にも分かるように説明してください。

Go言語の構造体はデータをまとめた箱で、名前や年齢などの情報をひとまとめにできる仕組みです。メソッドは、その構造体に対して動作や機能を追加するための仕組みです。たとえばPersonという構造体に対して挨拶する、年齢を増やすといった動きを付けられるので、データと処理がセットになり、分かりやすいプログラムが書けます。
関連セミナーのご案内

【超入門】ゼロから始めるGo言語プログラミング:最速で「動くアプリ」を作るマンツーマン指導

「プログラミングの仕組み」が根本からわかる。Go言語でバックエンド開発の第一歩を。

本講座を受講することで、単なる文法の暗記ではなく、「プログラムがコンピュータの中でどう動いているか」という本質的な理解につながります。シンプルながら強力なGo言語(Golang)を通じて、現代のバックエンドエンジニアに求められる基礎体力を最短距離で身につけます。

具体的な開発内容と環境

【つくるもの】
ターミナル(黒い画面)上で動作する「対話型計算プログラム」や、データを整理して表示する「ミニ・ツール」をゼロから作成します。自分の書いたコードが形になる感動を体験してください。

【開発環境】
プロの現場でシェアNo.1のVisual Studio Code (VS Code)を使用します。インストールから日本語化、Go言語用の拡張機能設定まで、現場基準の環境を一緒に構築します。

この60分で得られる3つの理解

1. 環境構築の完全な理解

「なぜ動くのか」という設定の仕組みを理解し、今後の独学で詰まらない土台を作ります。

2. Go言語の基本構造(変数・型)

データの種類やメモリの概念など、他言語にも通じるプログラミングの本質を学びます。

3. 読みやすいコードの書き方

ただ動くだけでなく、誰が見ても分かりやすい「綺麗なコード」を書くための考え方を伝授します。

※本講座は、将来的にバックエンドエンジニアクラウドインフラに興味がある未経験者のためのエントリー講座です。マンツーマン形式により、あなたの理解度に合わせて進行します。

セミナー画像

初めてのGo言語を一緒に学びましょう!

関連記事:
カテゴリの一覧へ
新着記事
New1
Go言語
Go言語のwhile的なforループの使い方!条件式ループの基本を解説
New2
Swift
Swiftのswitch文の使い方|初心者でもわかるパターンマッチング徹底解説
New3
Kotlin
Kotlinの認証と認可を完全解説!初心者でもわかる安全なログイン管理とセキュリティ対策
New4
Go言語
Go言語の関数でエラーハンドリングする基本的な方法
人気記事
No.1
Java&Spring記事人気No1
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.2
Java&Spring記事人気No2
Swift
Swift開発環境の構築方法を徹底解説!Xcode・Windows・Linux対応
No.3
Java&Spring記事人気No3
Go言語
Go言語でリダイレクト処理を行う方法(http.Redirect)を初心者向けに解説
No.4
Java&Spring記事人気No4
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方
No.5
Java&Spring記事人気No5
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!
No.6
Java&Spring記事人気No6
Go言語
Go言語のgo.modファイル完全ガイド!初心者でもわかる仕組みと書き方
No.7
Java&Spring記事人気No7
Kotlin
Kotlinの文字列の部分取得!substring・take・dropの基本
No.8
Java&Spring記事人気No8
Go言語
Go言語でミドルウェアを作成する方法と活用例!初心者でもわかるWebアプリ開発