【Go】Go言語特有の書き方

2025年4月7日Go

kamiです。
TwitterYoutubeもやってます。

今回はGo言語特有の書き方の紹介です。
Goと他の言語で書き方が違うことがあるので、他の言語もこれからGoを学ぶ方も覚えておきましょう。

変数宣言

Goでは、短縮記法の「 := 」がよく使われます。

name := "Kami"
age := 20

:= と _ の使い方

import {
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-lambda-go/lambdacontext"
}

func handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
  lc, ok := lambdacontext.FromContext(ctx);
  // 以下省略
}
  • lc は *LambdaContext を受け取る変数。
  • _ は 「使わないけど捨てられない戻り値」 のためのプレースホルダ。

ここでは bool(成功判定)を無視しています。

  lc, ok := lambdacontext.FromContext(ctx);

_(ブランク識別子)とは?

  • 「_」は使わない値を使用する

Goでは戻り値をすべて受け取らないとコンパイルエラーになるため、「使わない値」には _ を使います。

ブランク識別子を使った例

この関数はint 型(42)と、error 型(エラー)を返します。

func hogeFunc() (int, error) {
    return 42, errors.New("エラー")
}
  • 最初の int(この場合は 42) → 使わないから _ に捨てる
  • 2つ目の error → err に格納する
_, err := hogeFunc()  // 結果は無視、エラーだけ使う

簡単に_(ブランク識別子)を使った例で紹介すると分かりやすいですよね

スポンサードサーチ

エラーハンドリング

Goでは例外(try-catch)ではなく、「エラーは値として返す」のが一般

file, err := os.Open("file.txt")
if err != nil {
    log.Fatal(err)
}

defer 文(処理の後回し)

Goでは、関数の終了時に何かを遅延実行したいときに defer を使います。

func readFile() {
    f, _ := os.Open("file.txt")
    defer f.Close() // ← 関数が終わる直前に実行される
    // ファイルを読む処理...
}

スポンサードサーチ

並行処理(concurrency)

  • go をつけるだけで別スレッド的に動く「ゴルーチン」が走ります。
  • 超軽量スレッド。超低コスト。Goの代表的な機能!
go fetchData() // ← fetchData() を別ゴルーチンで並行実行

select 文(複数チャネルを同時に待つ)

他の言語であるswitch文と同じ使い方ですが、goではselect文になります。

select {
case msg := <-ch1:
    fmt.Println("ch1から受信:", msg)
case msg := <-ch2:
    fmt.Println("ch2から受信:", msg)
default:
    fmt.Println("どこからもデータなし")
}

スポンサードサーチ

型スイッチ(type switch)

「どの型かによって処理を分ける」ことが簡単にできます。

interface{} + 型スイッチ、Goっぽい書き方ですね

func printType(x interface{}) {
    switch v := x.(type) {
    case string:
        fmt.Println("文字列:", v)
    case int:
        fmt.Println("整数:", v)
    default:
        fmt.Println("未知の型")
    }
}

初期化(init)

  • main() より前に 自動的に呼ばれる特別な関数
  • 複数定義してもOK(複数ファイルでも)
func init() {
    fmt.Println("初期化中…")
}

無名関数(即実行関数)

JavaScriptのIIFEみたいな「書いた瞬間に実行する関数」。Goでも使われます!

func() {
    fmt.Println("即時実行!")
}()

それぞれの意味を確認

*Person にすることで、構造体の中身を書き換えられる(mutable)ようになります。

icon

「レシーバ付きメソッド」っていうのは
→ func (x T) MethodName() の形をした、「構造体などの型にくっついた関数」のこと

func (p Person) Greet() {
    fmt.Printf("こんにちは、%sです!\n", p.Name)
}

type Person struct {
    Name string
}

func (p *Person) Greet() {
    fmt.Println("こんにちは、", p.Name)
}

func main() {
    p := Person{Name: "太郎"}
    p.Greet()
}

レシーバメソッドの補足

  • Person という型(構造体)から、p という変数を作っています。
  • このステップで「太郎」という人物を用意してるイメージ。
p := Person{Name: "太郎"} // ← ① 構造体の変数(インスタンス)を作る
  • ①で作った p に対して、Greet() メソッドを実行しています。
  • 「pよ、あいさつしなさい!」という命令。
p.Greet() // ← ② その人にメソッド(挨拶)をさせる

値レシーバ((p Person))との違い

func (p Person) Greet()  // 値レシーバ(コピーを受け取る)
func (p *Person) Greet() // ポインタレシーバ(参照を受け取る)
レシーバ中身を書き換えられる?コピー発生?主な用途
❌ できない✅ する読み取り専用で軽い構造体向け
ポインタ✅ 書き換え可能❌ 発生しない大きな構造体・更新したい時

GoGo

Posted by kami