😴

【Go】"ぬるぽ"についてまとめました

2021/12/14に公開約1,800字4件のコメント

本記事は Go Advent Calendar 2021 の15日目の記事です。

https://qiita.com/advent-calendar/2021/go

はじめに

nilで下記エラー(ぬるぽ)で詰まり、調べた内容を記事に残そうと思います。

panic: runtime error: invalid memory address or nil pointer dereference

ぬるぽとは

ぬるぽとは、Javaで発生するエラーメッセージ「NullPointerException」の略称です。
nil値の参照型変数を参照しようとした時に発生するエラーメッセージです。
ちなみに、Javaではnilではなくnullと言います。
Javaを扱っている人は必ずと言っていいほど目にするエラーです。(本記事のサンプルコードはGoで記述しています)

発生原因

  • nilに何かしらのデータを渡す。
  • nilであるスライス、マップにデータを代入する。
  • nilポインタのデリファレンス(参照)

上記のような場合に、panicが発生します。

そもそもnilとは

nilは何もないという意味で、固く言うと参照型変数の値が定義されていない状態です。
参照型変数の値は参照するメモリ上のアドレス、その変数の参照先の値を示します。

ポインタとアドレスについては、下記記事にまとめてみたので、閲覧頂けると喜びます。

https://zenn.dev/genki86web/articles/a0ae1d57ad1806

この参照するメモリ上のアドレスとその参照先の値が定義されていない場合、参照型変数の値はnilになります。ですのでnilに何かしらのデータを渡すことができません。

もしnilに何かしらのデータを渡そうとすると、panicが発生します。
サンプルコードで確認してみます。

package main

func main() {

	// 宣言だけで値(データ)は何も入っていないので nilです
	// ですが、宣言はしているのでアドレスは持っています
	var n *int

	// nilに何かしらのデータを渡すと、panicが発生します
	*n = 0
}

出力結果

panic: runtime error: invalid memory address or nil pointer dereference

対処方法

nilだったらエラーを返すように、エラーハンドリングをしましょう。

package main

import (
	"errors"
	"fmt"
)

func countusers(users []string) (int, error) {

	// usersの中身がnilの場合は、intに0を、errorにエラーメッセージを返します
	if users == nil {
		return 0, errors.New("users is nil")
	}

	// usersの中身がnilでは無い場合は、intにusersの中身の数を、errorにnilを返します
	return len(users), nil
}

func main() {

	// countusersにnilを渡し、結果をcountとerrに入れます
	count, err := countusers(nil)

	// errがnilでは無い場合は、エラーメッセージを出力します
	if err != nil {
		fmt.Println(err)
		return
	}

	// errがnilの場合は、usersの中身の数を出力します
	fmt.Println(count)
}

出力結果

users is nil

nilなので、エラーメッセージが出力されました。

まとめ

いかがでしたでしょうか。
ぬるぽについて困っている方のお役に少しでも立てば嬉しく思います。
何か誤っている内容がありましたら、ご教授いただけると幸いです。
閲覧いただき、ありがとうございました。

参考にした記事

Discussion

「nilであるポインタの型からメソッドを呼び出す。」はGo特有の挙動ですが呼び出せます。(JavaやC++などでは無理)

ご指摘ありがとうございます!修正致します。

あと、発生原因に加えると良いのは「nilポインタのデリファレンス(参照)」です。

以下のコードのpointerがnilの場合にpanicになります。

val := *pointer

結果

panic: runtime error: invalid memory address or nil pointer dereference

ご指摘ありがとうございます!
発生原因に追記しておきます。

ログインするとコメントできます