기술나눔

[Go 시리즈] 배열, 슬라이스, 맵

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

이전과 다음을 연결하라

이전 글에서 if와 for를 소개했는데, 연습하면 안 됩니다.continue 100 이내의 짝수의 합을 계산하는 명령문입니다. 우리가 코드를 작성하면서,continue명령문은 필요하지 않은 특정 반복을 건너뛰는 데 도움이 됩니다. 예를 들어 이 예에서는 모든 홀수를 건너뜁니다.

  1. sum := 0
  2. for i := 1; i < 100; i++{
  3. if i & 1 == 0 {
  4. continue
  5. }
  6. sum += i
  7. }
  8. fmt.Println("the sum is",sum)

학습 시작

프로그래밍에서 우리는 동일한 유형의 요소 집합을 처리해야 하는 경우가 많으며 이러한 요소 집합은 Go 언어의 특정 데이터 구조로 표현됩니다. 오늘은 Go의 여러 컬렉션 유형인 배열, 슬라이스, 맵을 자세히 소개하겠습니다.

정렬

먼저 배열부터 시작해 보겠습니다. 배열은 Go에서 가장 기본적인 데이터 구조입니다. 동일한 유형의 요소를 고정 길이로 배열한 것입니다. 배열이 선언되면 길이를 변경할 수 없습니다. 배열의 선언과 초기화는 매우 간단합니다.

배열 선언

배열을 선언할 때 배열 유형과 배열 길이를 지정해야 합니다. 배열을 선언하는 방법은 다음과 같습니다.

var arrayName [arrayLength]elementType

예를 들어, 길이가 5인 정수 배열을 선언합니다.

var numbers [5]int
배열 초기화

다양한 방법으로 배열을 초기화할 수 있습니다.

  • 리터럴 초기화를 사용하십시오.
var numbers = [5]int{1, 2, 3, 4, 5}
  • 사용:=짧은 설명:
numbers := [5]int{1, 2, 3, 4, 5}
  • 배열 길이를 자동으로 추론합니다.
numbers := [...]int{1, 2, 3, 4, 5}
  • 인덱스 초기화를 지정합니다.
numbers := [5]int{0: 1, 4: 5}

배열의 특성

  • 고정 길이: 배열의 길이는 선언할 때 결정되며 나중에 변경할 수 없습니다.
  • 같은 유형의 요소: 배열은 동일한 유형의 요소만 포함할 수 있습니다.
  • 연속적으로 메모리 할당: 배열 요소는 메모리에 연속적으로 할당되므로 배열 요소에 액세스하는 것이 매우 효율적입니다.

배열 요소에 액세스

0부터 시작하는 인덱스로 배열의 요소에 액세스할 수 있습니다.

value := numbers[2] // 获取索引为 2 的元素

트래버스 배열

당신이 사용할 수있는for배열의 모든 요소를 ​​반복합니다.

  1. for i, value := range numbers {
  2. fmt.Printf("Index: %d, Value: %dn", i, value)
  3. }

배열의 길이

내장된 것을 사용할 수 있습니다.len배열의 길이를 가져오는 함수:

length := len(numbers)

배열의 0 값

배열이 명시적으로 초기화되지 않으면 해당 요소는 자동으로 해당 유형의 0 값으로 설정됩니다. 예를 들어 정수 배열의 0 값은 0입니다.

var numbers [5]int // 所有元素都是 0

다차원 배열

Go 언어는 다차원 배열도 지원합니다. 다음은 2x3 정수 배열을 선언하고 초기화하는 예입니다.

  1. var matrix [2][3]int
  2. matrix = [2][3]int{{1, 2, 3}, {4, 5, 6}}

배열의 한계

배열의 길이는 고정되어 있으므로 어떤 경우에는 그다지 유연하지 않을 수 있습니다. 가변 길이 컬렉션이 필요한 경우 슬라이스를 사용할 수 있습니다.

일부분

다음은 동적 배열로 생각할 수 있는 보다 유연한 내장 유형인 슬라이스입니다. 슬라이스의 길이는 가변적이며 배열 기반으로 생성되어 더욱 편리합니다. 슬라이스를 선언하고 초기화하는 방법은 다음과 같습니다.

  1. s := make([]int, 3) // 创建一个长度为3的整型切片
  2. s[0] = 1 // 切片元素赋值
  3. s[1] = 2
  4. s[2] = 3
  5. s = append(s, 4) // 向切片追加元素

Go 언어에서는 배열과 슬라이스가 모두 동일한 유형의 일련의 요소를 저장하는 데 사용되지만 메모리 할당, 크기 가변성 및 사용법에서는 상당한 차이가 있습니다. 배열과 슬라이스의 주요 차이점은 다음과 같습니다.

크기 가변성

  • 정렬 : 배열의 크기는 선언될 때 결정되며 나중에 변경할 수 없습니다.배열의 크기는 해당 유형의 일부이므로[3]int그리고[4]int종류가 다릅니다.
  • 일부분 : 슬라이스는 동적이며 런타임에 늘어나거나 줄어들 수 있습니다.슬라이스의 크기는 해당 유형의 일부가 아니므로[]int모든 정수 슬라이스에 대한 공통 유형입니다.

메모리 할당

  • 정렬 : 배열은 값 유형이며, 배열이 함수 매개변수로 전달되면 해당 값의 복사본이 전달됩니다. 즉, 함수 내부의 배열을 수정해도 원래 배열에는 영향을 주지 않습니다.
  • 일부분 : Slice는 기본 배열에 대한 포인터, 조각의 길이 및 용량을 포함하는 참조 유형입니다. 슬라이스가 함수 매개변수로 전달되면 포인터의 복사본이 전달되므로 함수 내에서 슬라이스를 수정하면 원본 슬라이스에 영향을 미칩니다.

초기화

  • 정렬: 배열을 초기화할 때 크기를 지정해야 하며, 요소값을 바로 할당할 수 있습니다.
  • 일부분: 슬라이스는 리터럴을 통해 전달될 수 있습니다.make초기화할 배열의 함수 또는 슬라이스, 크기가 지정되지 않았습니다.

샘플 코드

다음은 배열 및 슬라이스 초기화의 예입니다.

  1. // 数组
  2. var arr [3]int = [3]int{1, 2, 3}
  3. // 切片
  4. var slice []int = []int{1, 2, 3}
  5. // 或者使用 make 函数
  6. slice := make([]int, 3)

기능적 차이

  • 정렬: 크기가 고정되어 있기 때문에 배열의 크기는 컴파일 타임에 알려지므로 스택에 배열에 대한 메모리 할당이 가능하고 배열 요소에 액세스하는 시간 복잡도는 O(1)입니다.
  • 일부분: 슬라이싱은 다음과 같은 방법으로 더 많은 유연성을 제공합니다.append 함수는 요소를 추가하거나 슬라이싱 작업을 통해 하위 슬라이스를 얻습니다.슬라이스의 기본 배열은 힙에 할당될 수 있으며 슬라이스 요소에 액세스하는 시간 복잡도도 O(1)입니다.append일반적으로 O(n) 작업인 기본 배열의 재할당이 발생할 수 있습니다.

매핑

마지막으로 매핑을 살펴보겠습니다. 맵은 키를 값에 매핑하는 Go의 연관 배열입니다. 맵의 키는 정수, 부동 소수점 숫자, 문자열, 포인터, 인터페이스(인터페이스 내에 포함된 값이 비교할 수 있는 한), 구조체, 배열 등 항등 연산자가 지원하는 모든 유형이 될 수 있습니다. 매핑된 값은 모든 유형이 될 수 있습니다.

선언 및 초기화

지도를 선언하다

맵을 선언하는 구문은 다음과 같습니다.

var mapName map[keyType]valueType

예를 들어, 키를 문자열로, 값을 정수로 사용하여 맵을 선언합니다.

var scores map[string]int
지도 초기화

지도를 선언한 후 통과해야 합니다.make사용할 수 있도록 초기화하는 함수:

scores = make(map[string]int)

또는 짧은 선언을 사용하여 초기화할 수 있습니다.

scores := make(map[string]int)

선언 시 초기화를 위해 리터럴을 사용할 수도 있습니다.

  1. scores := map[string]int{
  2. "alice": 90,
  3. "bob": 85,
  4. "charlie": 88,
  5. }

지도의 특징

  • 주요 고유성: 맵에서 각 키는 고유합니다. 기존 키를 삽입하려고 하면 해당 키에 해당하는 값이 업데이트됩니다.
  • 무질서:map은 순서가 없으며 맵이 반복될 때마다 요소의 순서가 다를 수 있습니다.
  • 동적 크기:맵의 크기는 동적이므로 필요에 따라 키-값 쌍을 추가하거나 제거할 수 있습니다.
  • 참조 유형: Map은 참조 유형입니다. map을 함수에 전달할 때 실제로 전달하는 것은 기본 데이터 구조에 대한 포인터입니다.

작전 지도

요소 추가
scores["alice"] = 90
요소 가져오기
value := scores["alice"]

키가 존재하지 않으면 해당 값 유형에 대해 0 값이 반환됩니다.

키가 존재하는지 확인

쉼표 -ok 관용구를 사용하여 키가 맵에 존재하는지 확인할 수 있습니다.

  1. value, exists := scores["alice"]
  2. if exists {
  3. // 键存在
  4. } else {
  5. // 键不存在
  6. }
요소 삭제

사용delete함수는 맵에서 키-값 쌍을 제거할 수 있습니다.

delete(scores, "alice")

키가 존재하지 않는 경우,delete이 함수는 아무 작업도 수행하지 않습니다.

지도를 횡단하세요

사용for루프는 맵의 모든 키-값 쌍을 순회할 수 있습니다.

  1. for key, value := range scores {
  2. fmt.Printf("%s: %dn", key, value)
  3. }

지도의 0 값

지도의 0 값은 다음과 같습니다.nil .하나nil 지도에는 기본 데이터 구조가 없으며 요소를 추가할 수 없습니다.지도에 요소를 추가하기 전에 다음을 사용해야 합니다.make초기화하세요.

지도의 길이

내장된 것을 사용할 수 있습니다.len맵의 키-값 쌍 수를 가져오는 함수:

length := len(scores)

맵 키 유형

맵의 키는 정수, 부동 소수점 숫자, 문자열, 포인터, 인터페이스(인터페이스 내에 포함된 값이 비교 가능한 한), 구조, 배열 등과 같은 비교 가능한 유형일 수 있습니다. 슬라이스, 맵 및 함수는 동등 비교를 지원하지 않으므로 맵 키로 사용할 수 없습니다.

실수하기 쉽다

Go 언어에서 배열, 슬라이스 및 맵은 일반적으로 사용되는 세 가지 데이터 구조이며 각각 서로 다른 특성과 고려 사항을 가지고 있습니다. 사용할 때 주의할 사항은 다음과 같습니다.

정렬

  • 너무 큰 배열은 스택 공간을 많이 차지하고 스택 오버플로가 발생할 수 있으므로 사용하지 마십시오.
  • 배열은 고정된 크기의 데이터 컬렉션이 필요할 때 사용됩니다.

일부분

  • 슬라이싱을 확장할 때 메모리 재할당이 발생할 수 있으므로 잦은 확장을 피하기 위해 충분한 용량을 미리 할당하십시오.
  • 너무 큰 조각은 힙 공간을 많이 차지할 수 있으므로 사용하지 마십시오.
  • 슬라이스의 0 값은 다음과 같습니다.nil, 사용하기 전에 초기화가 필요합니다.

지도

  • 지도의 0 값은 다음과 같습니다.nilnil맵은 키-값 쌍을 저장하는 데 사용할 수 없으며 사용하기 전에 초기화해야 합니다.
  • 동시 환경에서 맵에 대한 읽기 및 쓰기 작업은 스레드로부터 안전하지 않으며 뮤텍스 잠금 또는 기타 동기화 메커니즘을 사용하여 보호해야 합니다.
  • 사용delete존재하지 않는 키를 삭제해도 오류가 발생하지 않지만, 키가 있는지 확인하는 것이 안전합니다.