소개
Go언어에서 배열과 슬라이스는 有序列의 요소로 구성된 데이터 구조입니다. 이러한 데이터 컬렉션은 많은 관련 값들을 동시에 작업하고자 하는 때 사용하기 좋습니다. 데이터를 함께 보관하고자 하는 것, 코드를 단缩하고, 여러 값에 대해 같은 메서드와 操作을 수행하는 것을 가능하게 해줍니다.
Go언어의 배열과 슬라이스는 모두 요소의 序列로 구성되는 데이터 구조이지만, 두 가지 사이에 중요한 차이가 있습니다. Go언어의 배열는 생성 시점에 容积이 정해진 有序列의 요소로 구성된 데이터 구조입니다. 배열이 할당한 사이즈로 끝나고 이 사이즈는 더 이상 변경할 수 없습니다. 그러나 슬라이스는 배열의 변수 길이 버전입니다. 이러한 데이터 구조를 사용하는 開発자들에게 더 많은 유연성을 제공합니다. 슬라이스는 다른 언어의 배열과 마찬가지로 생각하시면 좋습니다.
이러한 차이를 고려하면, 한쪽을 다른 것을 사용하는 특정 상황이 있을 수 있습니다. Go를 처음 보는 것과 다르게, 언어의 유연성이 slices를 대부분의 상황에서 더 적절한 선택이라는 것을 고려하면, 배열을 사용하여 프로그램의 성능을 최적화 시키는 특정 상황이 있을 수 있습니다.
이 글은 배열(array)과 시lices를 상세하게 다루고, 이 두 자료형 사이를 선택할 때 필요한 정보를 제공하게 됩니다. 또한, 배열과 시리스를 선언하고 工作中에 사용하는 가장 一般的な 方法을 다시 한 번 살펴봅니다. 튜토리얼은 시작으로 배열을 描述하고 그를 操作하는 방법을 보여 주고, 그 다음에 시리스를 설명하고 그들의 차이를 보여 줍니다.
Arrays
배열은 고정된 개수의 요소를 갖추는 コレクション 자료구조입니다. 배열의 크기가 고정되어 있어, 데이터 구조가 메모리를 한 번에 할당해야 하며, 変数 길이의 자료구조가 미래에 larger이나 smaller가 될 수 있도록 동적으로 메모리를 할당해야 하는 것と比べて 더 덜 고정적입니다. 배열의 고정 길이가 그들을 某种程度上 고정적으로 工作中에서 사용하기 어렵게 만들지만, 一次性 메모리 할당은 프로그램의 速度과 성능을 향상시키기 위해 사용되며, 이러한 이유로 개발자는 데이터 구조가 변동적인 요소를 가질 것이 아닐 때 프로그램 오timizing를 할 때 배열을 사용합니다.
Array 정의
배열은 인자로 사용할 배열의 크기를 괄호 [ ]
안에 지정하고, 요소의 데이터 형식을 나타내는 것을 이어야 합니다. Go 언어의 배열은 모든 요소가 같은 데이터 형식을 갖아야 합니다. 데이터 형식 다음에, 배열 요소의 개별 값을 괄호 { }
안에 선언할 수 있습니다.
다음은 배열을 선언하는 일반적인 스키마입니다:
주의: 새로운 배열을 선언할 때마다 독특한 형식을 생성하는 것을 기억해야 합니다. 따라서 [2]int
와 [3]int
가 모두 정수 요소를 갖추고 있지만, 그들의 길이가 다르기 때문에 데이터 형식이 서로 호환되지 않습니다.
배열의 요소의 값을 선언하지 않으면 기본적으로 零值(zero-valued)이 들어가며, 정수의 경우 0
로 표시되고, 문자열의 경우 빈 문자열로 표시됩니다.
예를 들어, 다음의 배열 numbers
는 아직 값을 갖추지 않은 三部의 정수 요소가 있습니다:
numbers
를 인쇄하면 다음과 같은 출력이 보입니다:
Output[0 0 0]
요소의 값을 배열을 생성 할 때 지정하고자 하면 괄호 안에 값을 넣습니다. 값을 지정한 문자열 배열은 다음과 같습니다:
배열을 변수에 보관하고 인쇄할 수 있습니다:
이전의 各行을 사용한 프로그램을 실행하면 다음과 같은 출력이 보입니다:
Output[blue coral staghorn coral pillar coral elkhorn coral]
fmt.Printf
함수를 사용하여 숫자를 출력할 때, %q
verb를 사용하여 값에 따옴표를 붙이고, \n
verb를 사용하여 行의 末尾에 换行符을 추가할 수 있습니다.
이렇게 하면 다음과 같은 결과가 나타납니다:
Output["blue coral" "staghorn coral" "pillar coral" "elkhorn coral"]
現在、각 항목은 따옴표로 囲まれています.
arrray를 선언하는 방법과 구성 내용을 이해하면 이제 인덱스 번호로 어떤 엘리먼트를 지정하는 방법을 배우는 것을 계속해서 할 수 있습니다.
인덱스를 사용한 arrray(또는 slice)
arrray(또는 slice) 中的 각 요소는 인덱스를 통해 개별적으로 호출할 수 있습니다. 각 요소는 시작 인덱스가 0
이고 int
값으로 나아가는 인덱스 번호와 일치합니다.
下面的 예제에서는 arrray를 사용하ますが, slice를 사용하는 것도 마찬가지로 인덱스를 사용하여 구분할 수 있습니다.
아래 예제에서 coral
arrray의 인덱스 구성은 다음과 같습니다:
“blue coral” | “staghorn coral” | “pillar coral” | “elkhorn coral” |
---|---|---|---|
0 | 1 | 2 | 3 |
첫 요소, 문자열 "blue coral"
는 인덱스 0
에 시작하며, 자르는 작업은 인덱스 3
까지 continue하여 요소 "elkhorn coral"
를 포함한다.
슬라이스나 배열의 각 요소는 따라서 인덱스 숫자가 assoicated 되어 있으므로, 그들을 같은 방식으로 Acces 하고 조작할 수 있다.
이제 슬라이스의 discrete Element를 통째로 호출할 수 있다.
Outputstaghorn coral
이 슬라이스의 인덱스 숫자는 이전 표에서 보여지는 것처럼 0-3
사이에 있다. 따라서 어느 요소에 대해 개별적으로 호출하면 이러한 인덱스 숫자를 참조해야 한다:
배열 coral
에 인덱스 숫자가 3보다 큰 수를 붙여서 호출하면 범위를 벗어나므로 유효하지 않다:
Outputpanic: runtime error: index out of range
배열 또는 슬라이스를 인덱스 할 때, 항상 正值를 사용해야 한다. 一些的语言에서는 음수를 사용하여 역方向으로 인덱스 할 수 있지만, Go에서는 그렇게 하면 에러가 발생한다:
Outputinvalid array index -1 (index must be non-negative)
문자열 요소끼리 배열 또는 슬라이스를 concatenate할 수 있는데, 이를 하는 것은 + 연산자를 사용한다:
OutputSammy loves blue coral
index number 0
에 있는 문자열 요소와 다른 문자열 "Sammy loves "
을 concatenate할 수 있었다.
array or slice 안의 요소에 대응하는 index number를 통해 각 요소들을 discretely access할 수 있으며, 이러한 요소들로 작업할 수 있다. 이를 示例化하기 위해서, 다음에 index로 element를 수정하는 것을 보겠다.
요소 수정
我們可以使用 인덱싱 来更改 数组 或者 切片 里面的 元素 ,通過 把 编号的元素 设为 不同的值 。这 给了我们更大的控制权 来控制 我们 数组 和 切片 里面的数据 ,并且允许我们 通过编程的方式来操作 个别元素 。
如果我们想 将 数组 coral
中 索引为 1
的元素的字符串值 从 "staghorn coral"
改为 "foliose coral"
,我们可以这样做:
现在当我们打印 coral
数组时,数组将会不同:
Output["blue coral" "foliose coral" "pillar coral" "elkhorn coral"]
现在既然你已经知道如何操作 数组 或 切片 的个别元素,让我们来看一下几个函数,这些函数将在你处理 集合数据类型 时给你更大的灵活性。
使用 len()
计算元素数量
在 Go 语言中,len()
是一个内置函数,用来帮助你操作数组和切片。就像对待字符串一样,你可以通过使用 len()
并传入数组或切片作为参数来计算数组或切片的长度。
例如,要找出 coral
数组中有多少个元素,你会这样做:
다음은 배열에서의 길이를 출력하는 것입니다. 그러면 다음과 같은 결과가 나오게 될 것입니다:
Output4
이는 배열 coral
의 길이가 4입니다, 이는 정수 타입으로 정리되어 있습니다, 이는 正確합니다, 因為 배열 coral
中有四个项目:
만약 당신은 더 많은 요소를 포함한 整型 배열을 만들어야 할 경우, 당신은 同樣도 이 방법을 사용할 수 있습니다:
이는 다음과 같은 결과를 보여줍니다:
Output13
雖然 이 예제 배열은 상대적으로 작다, nonetheless, len()
関数は 특히 非常大的 arrays 에서 非常有用합니다.
다음에는 어떻게 컬LECTION 데이터 형에 새로운 요소를 추가하는지 설명해 드리겠습니다, 그리고 이를 통해 당신은 알아봐 어떤 상황에서 이 static 데이터 형에서 append 이 함수는 실패할 것입니다.
append 함수와 append()
append()
는 Go 에 內建된 메thod 입니다, 그러나 이 メthod은 배열에서 사용할 수 없습니다. aforementioned, arrays are different from slices in that their size cannot be changed. This means that while you can change the values of elements in an array, you can’t make the array larger or smaller after it has been defined.
Consider your coral
array:
`"black coral"
` 아이템을 이 배열에 추가하려고 합니다. `append()` 関数을 배열에 사용하여 다음과 같이 입력하면
에러 정보가 반환되ます:
Outputfirst argument to append must be slice; have [4]string
이러한 문제를 해결하기 위해서, スライス 데이터 유형에 대해 더 알아보고, 스ラ이스를 정의하는 방법以及 배열을 스ラ이스로 변환하는 方法을 배우ましょう.
스라이스
스라이스는 리스izeble(大きさ 변경 가능)의 정렬되た 요소의 ordered sequence(順序 시퀀스)로 구성되는 데이터 유형입니다. 스라이스의 サイズ가 変動性이 있어 더 많은 유연성을 갖추고 있습니다. 未来에 필요한 데이터 수에 따라 옮기거나 변경되는 데이터 コレク션을 다루는 경우, 스라이스를 사용하면 컬렉션의 長さ를 조절하는 도중 코드가 에러를 갱신하는 것을 防ぐ 수 있습니다. 대부분의 경우, 이러한 변경 가능성은 배열과 比较하여 스ラ이스가 필요한 メモ리 재할당을 거의 받지 않는 장점을 가지고 있습니다. 많은 요소를 저장하거나 요소를 이터레이트하고 이러한 요소를 수정하고자 하는 경우, 스ラ이스 데이터 유형과 일하는 것이 좋습니다.
스라이스 정의
슬라이스는 데이터 유형이 선언되어 있는 []; curly brackets ({}) 사이에 있는 리스트의 요소로 정의됩니다. 배열과 달리, 지정적 길이를 나타내기 위해 [], 사이에 int
가 필요한 것을 발견할 수 있으며, 슬라이스는 구두brackets, {} 사이에 있는 리스트의 요소로 정의되며 지정적 길이가 아닌 지정되지 않은 길이를 나타냅니다.
문자열 데이터 유형의 요소를 포함하는 슬라이스를 만들어 봅시다:
슬라이스를 출력하면 슬라이스에 있는 요소를 볼 수 있습니다:
다음과 같은 결과가 나타집니다:
Output["shark" "cuttlefish" "squid" "mantis shrimp" "anemone"]
certain length without populating the elements of the collection yet, you can use the built-in make()
function:
이 슬라이스를 출력하면 다음과 같습니다:
Output["" "" ""]
certain capacity, you can pass in a third argument to make()
:
이这将创建一个长度为3
,预分配容量为5
个元素的零化切片。
이제 어떻게 슬라이스를 선언하는지 알았습니다. 그러나 이전에 있었던 coral
배열의 에러를 解决하기 위해서는 아직 sliced out sections of an array.
append()
function with coral
를 사용하기 전에 배열의 부분을 조각하는 方法을 배워야 합니다.Arrays into Slices
인덱스 번호를 사용하여 시작과 끝 지점을 determine하여 배열 내의 값의 일부를 호출할 수 있습니다. 이것을 slicing이라고 부르며, 이를 실행하기 위해서는 COLON으로 구분된 인덱스 번호 범위를 생성하는 [first_index:second_index]
형식을 사용합니다. 그러나, 배열을 slicing하는 것을 기억하십시오. 결과는 배열이 아닌 슬라이스입니다.
coral
배열의 중간 요소들을 첫 번째 요소와 마지막 요소를 제외하고 prints하고자 하면 인덱스 1
에서 시작하고 index 3
로 이전까지의 슬라이스를 생성할 수 있습니다:
이 program을 실행하면 다음과 같은 결과가 나타납니다:
Output[foliose coral pillar coral]
슬라이스를 생성하는 것은 [1:3]
과 같은 형식입니다. 첫 번째 숫자는 슬라이스의 시작지점(inclusive)이고, 두 번째 숫자는 첫 번째 숫자와 가져오고자 하는 요소의 갯수의 합입니다:
array[starting_index : (starting_index + length_of_slice)]
이 예시에서는 두 번째 요소(또는 index 1)를 시작지점으로 하고 두 개의 요소를 가져오기 위해 지정했습니다. 이러한 계산은 다음과 같습니다:
array[1 : (1 + 2)]
이러한 표현으로 도출되었습니다:
배열의 시작 또는 끝을 슬라이스의 시작 또는 끝 지점으로 설정하고자 하면 array[first_index:second_index]
구문의 하나의 숫자를 생략할 수 있습니다. 예를 들어 coral
배열의 첫 세 요소를 prints하고자 하면, "blue coral"
, "foliose coral"
, 以及 "pillar coral"
가 나타나는 것입니다. 이를 실행하는 方法은 다음과 같습니다:
이렇게 다음과 같이 출력됩니다:
Output[blue coral foliose coral pillar coral]
이 구문은 배열의 시작부터 인덱스 3
직전까지 출력하였습니다.
배열의 모든 아이템을 마지막에 포함하려면, 구문을 반대로 뒤집어야 합니다.
이렇게 하면 다음과 같은 スライス를 얻을 수 있습니다.
Output[foliose coral pillar coral elkhorn coral]
이 섹션은 배열의 일부분을 슬라이싱 기능을 사용해 호출하는 방법을 讨论しました. 次에, 배열 전체를 슬라이스로 변환하는 方法을 배울 것입니다.
배열을 슬라이스로 변환하기
배열을 생성하고 지정한 길이가 아닌 가변적인 길이를 가지고 싶다면, 그 배열을 슬라이스로 변환할 수 있습니다. 배열을 슬라이스로 변환하기 위해서는, 이 튜토리얼의 배열을 슬라이스로 분할하기단계에서 leaned하신 슬라이싱 과정을 사용하세요. 이번 차례는 시작과 끝 지점을 결정하는 인덱스 숫자를 모두 省略하고 전체 슬라이스를 선택하면 됩니다.
하지만 변수 coral
를 슬라이스로 직접 변환할 수 없습니다. 이는 Go에서 변수가 정의 되면 그 형식을 변경할 수 없기 때문입니다. 이를 规避하기 위해서는 배열의 전체 내용을 새로운 변수로 복사하여 슬라이스로 만들 수 있습니다.
coralSlice
를 출력하면 다음과 같은 결과를 얻을 것입니다.
Output[blue coral foliose coral pillar coral elkhorn coral]
이제 black coral
요소를 배열 부분과 마찬가지로 추가하고자 합니다. 이를 위해서는 이제 슬라이스로 변환된 새로운 슬라이스에 append()
함수를 사용합니다.
이렇게 하면 추가된 요소가 포함된 슬라이스가 출력됩니다.
Output["blue coral" "foliose coral" "pillar coral" "elkhorn coral" "black coral"]
我们可以在单个append()
语句中添加多个元素:
Output["blue coral" "foliose coral" "pillar coral" "elkhorn coral" "black coral" "antipathes" "leptopsammia"]
要将两个切片组合在一起,您可以使用append()
,但您必须使用...
扩展语法来扩展第二个参数以进行追加:
Output["blue coral" "foliose coral" "pillar coral" "elkhorn coral" "black coral" "antipathes" "leptopsammia" "massive coral" "soft coral"]
现在您已经学会了如何向您的切片添加元素,我们将来看一下如何删除一个元素。
从切片中删除元素
与其他语言不同,Go没有提供任何内置函数来从切片中删除元素。必须通过切片它们出来来从切片中删除项目。
要删除一个元素,您必须切片掉那个元素之前的项,切片掉那个元素之后的项,然后不包含您想要删除的元素将这两个新切片连接在一起。
如果i
是要删除的元素的位置索引,那么这个过程的格式将如下所示:
从coralSlice
中,让我们删除项"elkhorn coral"
。这个项目位于索引位置3
。
Output["blue coral" "foliose coral" "pillar coral" "black coral" "antipathes" "leptopsammia" "massive coral" "soft coral"]
现在,索引位置3
的元素,字符串"elkhorn coral"
,已不再在我们的切片coralSlice
中。
우리도 같은 방법으로 범위를 삭제할 수 있습니다. 예를 들어, "elkhorn coral"
, "black coral"
및 "antipathes"
같은 것들을 모두 삭제하고 싶다면 同樣한 방법을 사용합니다:
이는 슬라이스에서 index 3
, 4
, 그리고 5
를 삭제합니다:
Output["blue coral" "foliose coral" "pillar coral" "leptopsammia" "massive coral" "soft coral"]
이제 당신은 슬라이스의 크기를 어떻게 측정할 수 있는지 알아보겠습니다.
Measuring the Capacity of a Slice with cap()
Since slices have a variable length, the len()
method is not the best option to determine the size of this data type. Instead, you can use the cap()
function to learn the capacity of a slice. This will show you how many elements a slice can hold, which is determined by how much memory has already been allocated for the slice.
Note: Because the length and capacity of an array are always the same, the cap()
function will not work on arrays.
A common use for cap()
is to create a slice with a preset number of elements and then fill in those elements programmatically. This avoids potential unnecessary allocations that could occur by using append()
to add elements beyond the capacity currently allocated for.
우리는 숫자 목록 0
부터 3
까지를 만들고자 하는 场景을 생각해보자. append()
를 루프를 사용하여 만들 수 있으며, cap()
를 사용하여 미리 할당된 슬라이스를 채우는 것도 가능하다.
まず, append()
를 사용하여 만들 수 있는 것을 보자.
Output[0 1 2 3]
이 예에서, 슬라이스를 생성하고,四次元 for
루프를 생성했다. 각 迭代은 현재 루프 변수 i
의 값을 numbers
슬라이스의 인덱스에 추가했다. 그러나, 이 방법은 프로그램을 느리게 할 수 있는 Needless 메모리 할당을 일어낼 수 있다. 빈 슬라이스에 추가하는 것과 관련이 있으며, append 호출을 하면 프로그램은 슬라이스의 용량을 检查하게 되며, 추가되는 요소가 슬라이스가 이 용량을 초과하게 되면 추가적인 메모리 할당을 行いaturate 한다. 이것은 프로그램에 추가적인 오버heid를 일으키고 프로그램의 실행 速이를 느리게 할 수 있다.
이제, append()
를 사용하지 않고 슬라이스를 채우는 것을 보자. 한 정의 길이/용량을 미리 할당하면서 이를 실행한다.
Output[0 1 2 3]
이 예에서, 슬라이스를 생성하기 위해 make()
를 사용하고 그것이 4
요소를 미리 할당하도록 했다. 그리고 루프를 통해 각 零就地 요소를 이동하고 채우는 것을 실행했다. 각 루프에서는 현재 루PE 변수 i
의 값을 numbers
슬라이스의 인덱스에 배치했다.
append()
및 cap()
전략은 기능적으로 동일하나, cap()
예시는 append()
関数을 사용하는 것을 避け고 추가적인 메모리 할당을 하지 않는다.
다维多维切片 構築
다른 切片을 요소로 가지는 切片을 정의할 수도 있다. 각 괄호로 감싸진 리스트는 親 切片의 larger brackets内에 있다. 이러한 切片 컬렉션들은 다维多维切片라고 부르며, 이들은 다维多维 坐標를 나타내는 것처럼 생각할 수 있다. 예를 들어, 각각 6개의 요소를 갖는 5개의 切片은 水平和Advanced 2차원 격자로 이해할 수 있다.
다维多维切片을 보여주는 다음과 같은 예를 관찰해봐吧:
이 切片 내에서 요소를 접근하려면 각 维에 대한 인덱스를 사용해야 한다는 것을 기억하자.
이전 코드에서, 우선 1
index에 있는 切片의 index 0
处的元素를 식별하고, 그 다음 0
index에 있는 切片의 index 0
处的元素를 지정한다. 이렇게 다음과 같은 값을 얻을 수 있다.
OutputSammy
shark
나머지 개별 요소에 대한 인덱스 값은 다음과 같다.
다차원 시lice를 사용할 때는, 해당 嵌套 시lice에 특정 elemenet을 접근하려면 不止一个 index number が 필요합니다.
마지막으로
이번에는 Go의 array와 slice에 대한 기초적인 知識를 알아보았습니다. 다양한 예제를 통해서 array와 slice의 차이가 어떻게 影響している지 알아보았습니다. array는 長度가 고정되어있지만, slice는 長度가 변화able입니다. 이 차이는 這些 data structure의 사용 상황에 따라 다른 방법을 사용해야 합니다.
要进一步学习 Go 中数据结构的知识,请参阅我们的文章《Go 中的 Map 详解》,或者探索整个《如何用 Go 编程》系列。
Source:
https://www.digitalocean.com/community/tutorials/understanding-arrays-and-slices-in-go