Go言語のNULL値の扱い方を完全解説!sql.NullStringなどの型を初心者向けにやさしく説明
生徒
「Go言語でデータベースを使っていたら、NULLっていう値でエラーが出ました。NULLって何ですか?」
先生
「NULLは『値が入っていない』という意味を持つ特別な状態です。Go言語では、そのままでは扱えないので専用の型を使います。」
生徒
「専用の型って難しそうです……」
先生
「大丈夫です。身近な例えを使いながら、sql.NullStringなどの型を順番に見ていきましょう。」
1. NULL値とは何か?
Go言語でデータベース操作を始めると、必ず出会うのがNULL値です。NULLとは「空文字」や「ゼロ」とは違い、「そもそも値が存在しない」状態を表します。
たとえば、名簿に「電話番号」の欄があるとします。まだ電話番号を登録していない人の場合、その欄は空白になります。この「未記入」の状態が、データベースではNULLとして扱われます。
Go言語のstring型やint型は、必ず何らかの値を持つ仕組みになっています。そのため、NULLを直接入れようとするとエラーが発生します。
2. Go言語でNULLが問題になる理由
Go言語は安全性を重視したプログラミング言語です。そのため「値がある前提」で変数を扱います。一方、データベースは「値がない状態」も自然に扱います。
この考え方の違いが原因で、Go言語とデータベースをつなぐときにNULLの問題が起こります。特に初心者の方は、なぜエラーが出るのか分からず戸惑いやすいポイントです。
3. sql.NullStringとは?
Go言語には、database/sqlパッケージの中にNULLを安全に扱うための型が用意されています。その代表例がsql.NullStringです。
sql.NullStringは「文字列の値」と「有効かどうか」をセットで管理する構造になっています。値が存在するときは有効、NULLのときは無効、という状態をはっきり区別できます。
これは「箱の中にメモが入っているかどうか」を確認するイメージに近いです。箱が空ならNULL、メモが入っていれば文字列、という考え方です。
4. sql.NullStringの基本的な使い方
type User struct {
Name sql.NullString
}
このように構造体でsql.NullStringを使うことで、データベースのNULLを安全に受け取れます。
if user.Name.Valid {
fmt.Println(user.Name.String)
} else {
fmt.Println("名前は未登録です")
}
Validがtrueなら値あり、falseならNULLです。この確認を行うことで、予期しないエラーを防げます。
5. sql.NullInt64やsql.NullBoolもある
文字列だけでなく、数値や真偽値にもNULL対応の型があります。たとえばsql.NullInt64やsql.NullBoolです。
考え方はすべて同じで、「値」と「有効かどうか」をセットで管理します。一度理解できれば、他の型も迷わず使えるようになります。
6. NULL対応型を使うメリット
sql.NullStringなどの型を使う最大のメリットは、安全性です。NULLを見落としたまま処理を進めると、実行時エラーにつながります。
Go言語では「コンパイル時に気づける設計」を大切にしています。NULL対応型は、その思想に合った仕組みだと言えます。
7. 初心者がつまずきやすいポイント
初心者の方がよく混乱するのは、「空文字」と「NULL」の違いです。空文字は「値はあるが中身がない」、NULLは「値そのものが存在しない」状態です。
この違いを意識するだけで、Go言語のデータベース操作はぐっと分かりやすくなります。
まとめ
Go言語でデータベース操作を行うとき、初心者がつまずきやすいポイントの一つがNULL値の扱いです。データベースでは、文字列や数値が入っている状態だけでなく、値そのものが存在しない状態も保存できます。この値が存在しない状態をNULLと呼びます。一方で、Go言語の基本的なstring型やint型では、通常は何らかの値を持つことを前提としているため、データベースから取得したNULLをそのまま受け取ろうとすると問題が起こる場合があります。
NULLを理解するときに最も重要なのは、空文字やゼロとの違いです。空文字は文字列としての値が存在していて、その中身が空である状態です。数値のゼロも値としてゼロが保存されています。それに対してNULLは、値自体が存在していない状態です。例えば利用者情報の電話番号が空文字で登録されている場合と、電話番号がまだ一度も登録されておらずNULLになっている場合は、データベース上では異なる状態として扱われます。
Go言語でデータベースのNULLを扱うときは、空文字やゼロと同じものとして考えず、値が存在する状態と値が存在しない状態を明確に分けて考えることが大切です。
Go言語とデータベースでは値の考え方が少し異なる
Go言語では型を明確にしてプログラムを書くため、変数にどの種類のデータが入るのかを意識することが重要です。文字列には文字列、整数には整数というように、扱うデータの種類をはっきりさせます。それに対してデータベースでは、文字列を保存する列であってもNULLを許可している場合があります。
この違いによって、データベースから取得した値をGo言語の変数へ読み込むときに、NULLをどう受け取るかという問題が発生します。例えば利用者の名前をstring型として受け取ろうとしているのに、データベース側の名前がNULLだった場合、そのままでは適切に扱えないことがあります。そのため、NULLになる可能性がある列には、NULLを考慮した型を利用することが大切です。
sql.NullStringを使うと文字列とNULLを区別できる
Go言語のdatabase/sqlパッケージには、データベースのNULLを安全に扱うための型が用意されています。文字列で代表的なのがsql.NullStringです。sql.NullStringを使うと、実際の文字列と、その文字列が有効な値なのかどうかを一緒に管理できます。
sql.NullStringでは、Stringに文字列の内容が入り、Validによって値が存在するかどうかを判断できます。Validが有効であれば文字列を利用でき、無効であればデータベース上ではNULLだったと判断できます。これによって、文字列が空なのか、そもそも値が存在していないのかを区別できます。
package main
import (
"database/sql"
"fmt"
)
type User struct {
Name sql.NullString
}
func main() {
user := User{
Name: sql.NullString{
String: "田中",
Valid: true,
},
}
if user.Name.Valid {
fmt.Println(user.Name.String)
} else {
fmt.Println("名前は未登録です")
}
}
田中
この例では、名前として田中という文字列が入っており、有効な値として扱われています。そのため、Validを確認したあとにStringの内容を表示できます。データベースから取得した値を扱う場合でも基本的な考え方は同じで、まず値が有効かを確認してから実際の文字列を利用します。
NULLだった場合の処理もあらかじめ考えておく
sql.NullStringを使う目的は、単にエラーを避けることだけではありません。NULLだったときに、プログラムとしてどのような表示や処理をするのかを明確にできることも大きなメリットです。
例えば利用者の名前が未登録でNULLだった場合、そのまま何も表示しないのか、未登録という文字を表示するのかは、アプリケーションの仕様によって変わります。Validを確認することで、値が存在する場合と存在しない場合に処理を分けることができます。
package main
import (
"database/sql"
"fmt"
)
func main() {
name := sql.NullString{
Valid: false,
}
if name.Valid {
fmt.Println("名前:", name.String)
} else {
fmt.Println("名前は未登録です")
}
}
名前は未登録です
NULLになる可能性を最初から考えた処理にしておけば、データベースに未入力の情報があっても安全に対応できます。Go言語でデータベースを扱うときには、正常な値だけを想定するのではなく、NULLだった場合の動作も設計しておくことが重要です。
sql.NullInt64やsql.NullBoolも基本的な考え方は同じ
データベースでNULLになる可能性があるのは文字列だけではありません。数値や真偽値にもNULLが保存される場合があります。そのような場合には、sql.NullInt64やsql.NullBoolなどのNULL対応型を利用できます。
sql.NullStringを理解できれば、ほかのNULL対応型も考え方はほとんど同じです。値を保存する部分と、その値が有効かどうかを示す部分を組み合わせて管理します。数値がゼロなのかNULLなのか、真偽値が偽なのかNULLなのかを区別できる点が重要です。
- sql.NullStringは、文字列とNULLを区別したい場合に利用します。
- sql.NullInt64は、整数値とNULLを区別したい場合に利用します。
- sql.NullBoolは、真偽値とNULLを区別したい場合に利用します。
例えば数値のゼロには意味がある場合があります。商品の在庫数がゼロなら、在庫が一つもないという明確な状態です。しかしNULLであれば、在庫数そのものがまだ登録されていないという別の意味を持つ可能性があります。この二つを同じものとして扱ってしまうと、データの意味を正しく判断できなくなります。
真偽値でも同じです。偽という値が保存されている状態と、まだ値が決められておらずNULLになっている状態は異なります。Go言語でデータベース設計やデータ取得処理を行うときは、値がある場合だけでなく、値が存在しない場合にどのような意味を持たせるのかを考えることが大切です。
空文字とNULLを区別するとデータベース操作が分かりやすくなる
初心者のうちは、空文字とNULLを同じようなものだと思ってしまうことがあります。しかし、この違いを理解することはGo言語のデータベース操作を学ぶうえで非常に重要です。
空文字の場合は文字列という値が存在しています。ただし、その文字列の長さがなく、中身が空になっています。一方のNULLには文字列そのものが存在していません。そのため、未入力を空文字として保存するのかNULLとして保存するのかによって、データベースから取得した後の判定方法も変わります。
NULLを理解するときに覚えておきたいポイント
空文字は値が存在している状態です。
ゼロも数値として値が存在している状態です。
NULLは値そのものが存在していない状態です。
sql.NullStringでは値と有効状態を一緒に管理できます。
データを利用する前に有効な値か確認することで安全に処理できます。
NULL対応型を使うことで処理の意図も分かりやすくなる
sql.NullStringなどのNULL対応型を構造体のフィールドに使うと、その項目にはNULLが入る可能性があることをプログラム上でも確認しやすくなります。単純なstring型だけを見た場合は、値が必ず存在するのか、データベース側ではNULLになる可能性があるのか判断しにくいことがあります。
一方でsql.NullStringになっていれば、この項目はNULLになる可能性があるため、有効かどうかを確認してから利用する必要があると読み取れます。このように型を適切に選ぶことは、プログラムを安全にするだけでなく、後からコードを読んだときの分かりやすさにもつながります。
Go言語でデータベースを扱う場合は、テーブルの列がNULLを許可しているかを確認し、それに合わせてGo言語側の型を考えることが重要です。データベースの設計とGo言語の構造体を別々に考えるのではなく、どの列には必ず値が入り、どの列にはNULLが入る可能性があるのかを整理しながら実装すると、エラーの少ないプログラムを作りやすくなります。
Go言語のNULL処理で初心者が覚えておきたい流れ
Go言語でNULLを扱うときは、まずデータベース側の値がNULLになる可能性があるかを確認します。NULLになる可能性がある文字列ならsql.NullString、整数ならsql.NullInt64、真偽値ならsql.NullBoolというように、データに合わせたNULL対応型を選びます。
次に、データベースから値を取得したあと、有効状態を確認します。有効であれば実際の値を利用し、NULLであれば未登録として扱うなど、別の処理を行います。この手順を習慣にすることで、NULLが原因となる予期しない問題を防ぎやすくなります。
Go言語のdatabase/sqlを学習すると、SELECTによるデータ取得や構造体への値の読み込みなど、さまざまな場面でNULLを意識する必要が出てきます。最初はsql.NullStringの構造が少し複雑に見えるかもしれませんが、値と有効状態をセットで管理していると理解すれば難しくありません。
特に大切なのは、NULLを単なるエラーの原因として覚えるのではなく、データベース上で意味を持つ状態として理解することです。登録されていない、まだ決まっていない、値が存在しないといった状態を表現するためにNULLが使われます。その状態をGo言語で安全に受け取るためにsql.NullStringなどの型が用意されています。
Go言語のNULL値、sql.NullString、sql.NullInt64、sql.NullBool、database/sql、空文字とNULLの違い、構造体、データベース操作といった基本を一緒に理解しておくと、データ取得処理を作るときに迷いにくくなります。まずは文字列のNULLをsql.NullStringで扱う簡単な例から練習し、慣れてきたら数値や真偽値にも同じ考え方を広げていくとよいでしょう。
Go言語でデータベースを安全に扱うためには、取得できる値だけを見るのではなく、値が存在しない場合も想定することが大切です。NULLを正しく理解し、適切なNULL対応型を利用できるようになると、データベースから取得した情報をより安全に扱えるようになります。これはGo言語によるデータベースプログラミングを学ぶうえで、早い段階で身につけておきたい基本知識です。
生徒
「最初はNULLと空文字が同じようなものだと思っていました。でも、空文字は値がある状態で、NULLは値そのものがない状態なんですね。」
先生
「その違いが分かれば、Go言語でデータベースを扱うときのNULL処理がかなり理解しやすくなります。」
生徒
「普通の文字列ではNULLをそのまま扱いにくいから、sql.NullStringを使うんですね。」
先生
「そうです。sql.NullStringなら、文字列の内容だけでなく、その値が有効なのか、NULLなのかも一緒に管理できます。」
生徒
「Validを確認してからStringを使えばいいということですね。NULLだった場合は、未登録と表示するような処理に分けられるんですね。」
先生
「その通りです。値がある場合とない場合の両方を考えておけば、安全なデータベース処理になります。」
生徒
「数値や真偽値にも同じようなNULL対応型があるんですよね。」
先生
「はい。数値ならsql.NullInt64、真偽値ならsql.NullBoolのような型があります。考え方はsql.NullStringと同じです。」
生徒
「数値のゼロとNULLも違うし、真偽値の偽とNULLも違うということですね。」
先生
「その理解が大切です。ゼロや偽はきちんと存在している値ですが、NULLは値そのものが存在していません。」
生徒
「これからデータベースの構造体を作るときは、列の型だけじゃなくて、NULLになる可能性があるかも確認したほうがいいんですね。」
先生
「そうですね。データベース側でNULLを許可しているかを確認し、Go言語側でもそれに合った型を選ぶことが重要です。sql.NullStringなどを正しく使えるようになると、Go言語のデータベース操作をより安全に書けるようになります。」
【超入門】ゼロから始めるGo言語プログラミング:最速で「動くアプリ」を作るマンツーマン指導
「プログラミングの仕組み」が根本からわかる。Go言語でバックエンド開発の第一歩を。
本講座を受講することで、単なる文法の暗記ではなく、「プログラムがコンピュータの中でどう動いているか」という本質的な理解につながります。シンプルながら強力なGo言語(Golang)を通じて、現代のバックエンドエンジニアに求められる基礎体力を最短距離で身につけます。
具体的な開発内容と環境
【つくるもの】
ターミナル(黒い画面)上で動作する「対話型計算プログラム」や、データを整理して表示する「ミニ・ツール」をゼロから作成します。自分の書いたコードが形になる感動を体験してください。
【開発環境】
プロの現場でシェアNo.1のVisual Studio Code (VS Code)を使用します。インストールから日本語化、Go言語用の拡張機能設定まで、現場基準の環境を一緒に構築します。
この60分で得られる3つの理解
「なぜ動くのか」という設定の仕組みを理解し、今後の独学で詰まらない土台を作ります。
データの種類やメモリの概念など、他言語にも通じるプログラミングの本質を学びます。
ただ動くだけでなく、誰が見ても分かりやすい「綺麗なコード」を書くための考え方を伝授します。
※本講座は、将来的にバックエンドエンジニアやクラウドインフラに興味がある未経験者のためのエントリー講座です。マンツーマン形式により、あなたの理解度に合わせて進行します。
初めてのGo言語を一緒に学びましょう!