Go言語(Golang)で配列やスライスを使っていると、「特定の値が入っているか調べたい」「その値がどこにあるか知りたい」といった場面によく出くわします。
しかし、GoにはPythonやJavaScriptのような便利なindexOf
関数が最初から用意されていません。そのため、検索の処理は自分で作る必要があります。
この記事では、Goで配列・スライスを検索する基本的な方法を、実際の例といっしょにていねいに説明します。
配列とスライスの違いを確認しよう

配列とスライスってなに?
Go言語には、似ているけれど少し違う2つのデータ型があります。
- 配列:大きさが決まっている。プログラムを作るときにサイズが決定される
- スライス:大きさを変えられる。配列のように使えるが、より自由
Goでは実際のプログラム開発でスライスを使う場面が多いため、この記事でもスライスを中心に説明します。
実際に見てみよう
package main
import "fmt"
func main() {
// 配列:サイズが3で固定
arr := [3]int{1, 2, 3}
// スライス:サイズを後から変えられる
slice := []int{1, 2, 3, 4, 5}
fmt.Println("配列:", arr) // 配列: [1 2 3]
fmt.Println("スライス:", slice) // スライス: [1 2 3 4 5]
}
検索処理は主にスライスに対して行うことが多いです。次では、値が含まれているかを確認する方法を紹介します。
値がスライスに含まれているかを確認する方法
基本的な考え方
Goには直接contains
のような関数がないため、自分でループを使って実装します。ループでスライスの中身を一つずつ確認して、目的の値があるかどうかを調べます。
実際に作ってみよう
package main
import "fmt"
// 数値のスライスに特定の値が含まれているかチェックする関数
func contains(slice []int, target int) bool {
for _, v := range slice {
if v == target {
return true // 見つかったらtrueを返す
}
}
return false // 最後まで見つからなかったらfalseを返す
}
func main() {
nums := []int{10, 20, 30, 40}
// 30があるかチェック
fmt.Println(contains(nums, 30)) // 出力: true
// 50があるかチェック
fmt.Println(contains(nums, 50)) // 出力: false
}
コードの説明
for _, v := range slice
:スライスの要素を一つずつ取り出す_
:インデックス(位置)は使わないので_
で無視v
:取り出した値if v == target
:取り出した値と探している値が同じかチェック
このように、シンプルなループで確認できます。次は、要素の位置(インデックス)を取得する方法を見ていきます。
要素の位置(インデックス)を取得する方法
なぜ位置を知りたいの?
値があるかどうかだけでなく、「何番目にあるか」を知りたい場合があります。たとえば、その位置の値を変更したり、その位置から別の処理をしたりするときに便利です。
実際に作ってみよう
package main
import "fmt"
// 数値のスライスで特定の値の位置を探す関数
func indexOf(slice []int, target int) int {
for i, v := range slice {
if v == target {
return i // 見つかったら位置を返す
}
}
return -1 // 見つからなかった場合は-1を返す
}
func main() {
nums := []int{100, 200, 300, 400}
// 300の位置を探す
position := indexOf(nums, 300)
fmt.Println(position) // 出力: 2(0から数えて2番目)
// 500の位置を探す(存在しない)
position2 := indexOf(nums, 500)
fmt.Println(position2) // 出力: -1(見つからない)
// 実際に使ってみる
if position != -1 {
fmt.Printf("300は%d番目にあります\n", position)
}
}
コードの説明
for i, v := range slice
:今度は位置(i)も使うreturn i
:見つかったら位置を返すreturn -1
:見つからなかった場合は-1を返す(Goでよく使われる慣習)
検索だけでなく、位置を特定できるとより高度な処理ができるようになります。続いては、文字列スライスの検索方法を紹介します。
文字列スライスの検索

文字列も同じように検索できる
数値だけでなく、文字列のスライスも同じような方法で検索できます。プログラムの構造は基本的に同じです。
実際に作ってみよう
package main
import "fmt"
// 文字列のスライスに特定の文字列が含まれているかチェックする関数
func containsStr(slice []string, target string) bool {
for _, v := range slice {
if v == target {
return true
}
}
return false
}
// 文字列のスライスで特定の文字列の位置を探す関数
func indexOfStr(slice []string, target string) int {
for i, v := range slice {
if v == target {
return i
}
}
return -1
}
func main() {
names := []string{"Alice", "Bob", "Charlie", "David"}
// "Bob"があるかチェック
fmt.Println(containsStr(names, "Bob")) // 出力: true
// "Bob"の位置を探す
fmt.Println(indexOfStr(names, "Bob")) // 出力: 1
// "Eve"があるかチェック
fmt.Println(containsStr(names, "Eve")) // 出力: false
// 実際の使用例
searchName := "Charlie"
if containsStr(names, searchName) {
position := indexOfStr(names, searchName)
fmt.Printf("%sは%d番目にいます\n", searchName, position)
} else {
fmt.Printf("%sは見つかりませんでした\n", searchName)
}
}
型が違っても、基本的な構造は同じです。より便利な検索関数を作ることも可能です。
より便利な検索関数を作ってみよう
汎用的な関数の作成
毎回似たような関数を書くのは大変なので、いろいろなデータ型で使える関数を作ることもできます。
package main
import "fmt"
// 複数の条件で検索する関数
func findAll(slice []int, condition func(int) bool) []int {
var result []int
for _, v := range slice {
if condition(v) {
result = append(result, v)
}
}
return result
}
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// 偶数だけを探す
evenNums := findAll(nums, func(n int) bool {
return n%2 == 0
})
fmt.Println("偶数:", evenNums) // 出力: 偶数: [2 4 6 8 10]
// 5より大きい数を探す
bigNums := findAll(nums, func(n int) bool {
return n > 5
})
fmt.Println("5より大きい数:", bigNums) // 出力: 5より大きい数: [6 7 8 9 10]
}
よくある使用場面と実践例
ユーザー管理システムの例
package main
import "fmt"
type User struct {
ID int
Name string
Age int
}
// ユーザーIDで検索
func findUserByID(users []User, id int) *User {
for i, user := range users {
if user.ID == id {
return &users[i] // 見つかったユーザーのポインタを返す
}
}
return nil // 見つからなかった場合
}
// 年齢で絞り込み
func findUsersByAge(users []User, minAge int) []User {
var result []User
for _, user := range users {
if user.Age >= minAge {
result = append(result, user)
}
}
return result
}
func main() {
users := []User{
{ID: 1, Name: "田中", Age: 25},
{ID: 2, Name: "佐藤", Age: 30},
{ID: 3, Name: "鈴木", Age: 20},
}
// ID2のユーザーを探す
user := findUserByID(users, 2)
if user != nil {
fmt.Printf("見つかったユーザー: %s\n", user.Name)
}
// 25歳以上のユーザーを探す
adults := findUsersByAge(users, 25)
fmt.Println("25歳以上のユーザー:")
for _, u := range adults {
fmt.Printf("- %s (%d歳)\n", u.Name, u.Age)
}
}
よくある間違いと注意点

1. インデックスの範囲外アクセス
// ❌ 危険な例
func badExample(slice []int) {
// スライスが空の場合、エラーになる
fmt.Println(slice[0])
}
// ✅ 安全な例
func safeExample(slice []int) {
if len(slice) > 0 {
fmt.Println(slice[0])
} else {
fmt.Println("スライスが空です")
}
}
2. nilスライスの処理
func safeContains(slice []int, target int) bool {
if slice == nil {
return false
}
for _, v := range slice {
if v == target {
return true
}
}
return false
}
まとめ
Goでは、配列やスライスに対する検索処理を自分でループを使って書く必要があります。標準の関数がない分、検索のやり方を自分好みにカスタマイズしやすいとも言えます。
この記事で学んだポイント
- スライスの要素を一つずつチェックする基本的な検索方法
- 値の存在確認と位置取得の実装方法
- 数値と文字列の両方での検索テクニック
- より高度な検索条件の実装方法
- 実際のプログラムでの活用例
コメント