Go 언어에서 배열에 특정 값이 있는지 확인하는 꿀팁! (feat. 슬라이스 활용법)
들어가며: "이 안에 너 있다!" Go 언어에서 특정 값 찾아내기
프로그래밍을 하다 보면 "이 배열(또는 리스트) 안에 내가 찾는 값이 들어있나?" 하고 확인해야 할 때가 정말 많습니다.
Go 언어에서도 마찬가지인데요.
그런데 Go 언어의 배열은 크기가 한번 정해지면 바꿀 수 없어서, 실제로는 크기가 자유롭게 변하는 '슬라이스(Slice)'를 훨씬 더 많이 사용합니다.
이번 글에서는 Go 언어에서 슬라이스 안에 특정 요소가 있는지 확인하는 가장 간단한 방법부터, 조금 더 효율적인 방법까지 쉽고 재미있게 알아보겠습니다.
마치 숨바꼭질하듯 원하는 값을 쏙쏙 찾아내는 방법을 함께 배워볼까요?
가장 기본적인 방법: 하나씩 차근차근 살펴보는 반복문 활용법
슬라이스 안에 특정 요소가 있는지 확인하는 가장 직관적이고 간단한 방법은 바로 반복문(for 루프)을 사용하는 것입니다.
슬라이스 안에 있는 요소들을 처음부터 끝까지 하나씩 꺼내보면서, 내가 찾고 있는 값과 같은지 비교하는 건데요.
만약 똑같은 값을 발견하면 "찾았다!" 하고 알려주고, 끝까지 다 찾아봤는데도 없으면 "아쉽지만 없네요" 하고 알려주는 방식입니다.
자, 코드로 한번 살펴볼까요?
package main
import "fmt"
// 정수형 슬라이스와 찾고 싶은 요소를 받아, 해당 요소가 슬라이스에 있는지 확인하는 함수
func contains(slice []int, element int) bool {
// 슬라이스의 모든 요소를 하나씩 반복해서 살펴봅니다.
for _, v := range slice {
// 현재 요소(v)가 찾고 있는 요소(element)와 같다면
if v == element {
return true // true를 반환하고 함수를 종료합니다 (찾았으니까요!)
}
}
// 반복문이 끝날 때까지 요소를 찾지 못했다면
return false // false를 반환합니다 (결국 못 찾았네요)
}
func main() {
numbers := []int{1, 2, 3, 4, 5} // 1부터 5까지의 정수를 담고 있는 슬라이스
fmt.Println(contains(numbers, 3)) // numbers 슬라이스에 3이 있는지 확인 -> true 출력
fmt.Println(contains(numbers, 6)) // numbers 슬라이스에 6이 있는지 확인 -> false 출력
}
위 코드에서 contains
함수는 slice
라는 정수형 슬라이스와 element
라는 정수 값을 입력받습니다.
그리고 for _, v := range slice
구문을 통해 슬라이스 안의 각 요소 v
를 하나씩 꺼내보죠.
만약 v
가 우리가 찾던 element
와 같다면, 바로 true
를 반환하면서 "찾았다!" 신호를 보냅니다.
반복문이 모두 끝날 때까지 같은 값을 찾지 못하면, 결국 false
를 반환하며 "없다"는 사실을 알려주는 것이죠.
이 방법은 정수형 슬라이스뿐만 아니라 어떤 타입의 슬라이스에도 적용할 수 있습니다.
예를 들어, 문자열 슬라이스에서 특정 단어를 찾고 싶다면 함수를 살짝만 바꿔주면 됩니다.
package main
import "fmt"
// 문자열 슬라이스와 찾고 싶은 문자열을 받아, 해당 문자열이 슬라이스에 있는지 확인하는 함수
func containsString(slice []string, element string) bool {
// 슬라이스의 모든 문자열을 하나씩 반복해서 살펴봅니다.
for _, v := range slice {
// 현재 문자열(v)이 찾고 있는 문자열(element)과 같다면
if v == element {
return true // true를 반환하고 함수를 종료합니다.
}
}
// 반복문이 끝날 때까지 문자열을 찾지 못했다면
return false // false를 반환합니다.
}
func main() {
words := []string{"사과", "바나나", "체리"} // 과일 이름들을 담고 있는 문자열 슬라이스
fmt.Println(containsString(words, "바나나")) // words 슬라이스에 "바나나"가 있는지 확인 -> true 출력
fmt.Println(containsString(words, "포도")) // words 슬라이스에 "포도"가 있는지 확인 -> false 출력
}
어때요? 타입만 바꿔줬을 뿐인데, 문자열 슬라이스에서도 잘 작동하죠?
더 빠른 검색을 원한다면? 맵(Map)을 활용한 탐색 비법!
만약 특정 요소가 있는지 확인하는 작업을 아주 자주 하거나, 매우 큰 슬라이스에서 값을 찾아야 한다면, 반복문을 사용하는 것보다 더 효율적인 방법이 있습니다.
바로 '맵(Map)'을 활용하는 것인데요.
맵은 키(Key)와 값(Value)을 한 쌍으로 저장하는 자료구조인데, 키를 통해 값을 찾아오는 속도가 평균적으로 매우 빠르다는 장점이 있습니다.
마치 책에서 특정 단어를 찾을 때, 처음부터 끝까지 다 읽어보는 것보다 목차나 색인을 이용하는 것이 훨씬 빠른 것과 비슷하다고 생각할 수 있습니다.
어떻게 맵을 활용할 수 있는지 코드로 살펴보겠습니다.
package main
import "fmt"
func main() {
// 키는 슬라이스의 요소 타입, 값은 빈 구조체(struct{})로 맵을 생성합니다.
// 빈 구조체는 메모리를 거의 차지하지 않아 효율적입니다.
elements := map[int]struct{}{
1: {}, 2: {}, 3: {}, 4: {}, 5: {}, // 슬라이스의 요소들을 맵의 키로 사용합니다.
}
// 맵에서 특정 키(요소)가 존재하는지 확인합니다.
// 맵 조회는 두 개의 값을 반환하는데, 첫 번째는 해당 키의 값(여기서는 무시),
// 두 번째는 해당 키의 존재 여부(bool 타입)입니다.
_, exists := elements[3]
fmt.Println(exists) // elements 맵에 키 3이 존재하는지 확인 -> true 출력
_, exists = elements[6]
fmt.Println(exists) // elements 맵에 키 6이 존재하는지 확인 -> false 출력
}
이 코드에서는 슬라이스의 요소들을 맵의 '키(Key)'로 사용하고, '값(Value)'으로는 빈 구조체(struct{}
)를 사용했습니다.
빈 구조체는 메모리를 거의 차지하지 않기 때문에, 단순히 요소의 존재 여부만 확인하고 싶을 때 아주 유용하답니다._, exists := elements[3]
이 부분을 보면, elements
맵에서 키가 3
인 항목을 찾습니다.
이때 exists
변수에는 해당 키가 맵에 존재하는지 아닌지에 대한 true
또는 false
값이 저장됩니다.
맵을 사용하면 요소의 개수가 아무리 많아도 평균적으로 거의 일정한 속도로 값을 찾을 수 있어서, 성능이 중요한 상황에서는 반복문보다 훨씬 유리할 수 있습니다.
잠깐! 배열과 슬라이스, 뭐가 다른 걸까요?
앞에서도 잠깐 언급했지만, Go 언어에서 '배열(Array)'은 크기가 고정되어 있어서 한번 만들면 길이를 바꿀 수 없습니다.
반면에 '슬라이스(Slice)'는 동적으로 크기가 조절될 수 있어서 훨씬 유연하게 사용할 수 있습니다.
그래서 실제 Go 프로그래밍에서는 배열보다는 슬라이스를 훨씬 더 많이 사용한답니다.
우리가 지금까지 살펴본 예제들도 사실은 모두 슬라이스를 사용한 것입니다.
마무리하며: 상황에 맞는 탐색 방법 선택이 중요해요!
지금까지 Go 언어에서 슬라이스 안에 특정 요소가 포함되어 있는지 확인하는 두 가지 주요 방법을 알아봤습니다.
간단하게는 반복문을 사용해서 하나씩 비교하는 방법이 있고, 더 빠른 탐색이 필요할 때는 맵을 활용하는 방법이 있다는 것을 배웠습니다.
어떤 방법을 선택할지는 상황에 따라 달라질 수 있습니다.
슬라이스의 크기가 작거나 확인 작업이 자주 일어나지 않는다면 간단한 반복문으로도 충분하겠지만, 성능이 중요한 대용량 데이터 처리 상황에서는 맵을 활용하는 것이 현명한 선택이 될 수 있습니다.
이 글을 통해 Go 언어로 프로그래밍할 때 원하는 값을 효과적으로 찾아내는 데 도움이 되었기를 바랍니다!
'Go' 카테고리의 다른 글
Go 언어 딕셔너리 완전 정복: 맵(map)으로 데이터 관리 마스터하기! (0) | 2025.06.03 |
---|---|
Go 언어 클로저 완전 정복: 변수를 '기억'하는 똑똑한 함수 만들기! (0) | 2025.06.03 |
Go 언어, 상속 대신 '조합'으로 더 유연하게! 구조체 상속 완벽 이해하기 (2) | 2025.06.03 |
고(Go) JSON 인코딩의 숨은 병기, omitempty 태그 완벽 분석! (깔끔한 JSON 만들기 꿀팁) (0) | 2025.05.30 |
고(Go) 언어의 'goto' 문, 과연 필요악일까? 제대로 알고 사용하기 위한 모든 것! (0) | 2025.05.30 |