[golang] 배열, 슬라이스,맵

20086 단어 gogo

go 언어에서는 두개 이상의 변수를 모아 놓은 것을 '컬렉션'이라고 한다. 컬렉션은 그 기능에 따라 이름이 다른 세 가지 용법이 있다.

배열(array)

  • go언어에서의 배열은 정적이다. 즉 고정된 배열 크기안에 동일한 데이터를 연속적으로 저장한다. 배열의 선언은
    var 배열이름 [배열크기]자료형형식이다. 여기서 배열의 크기는 자료형을 구성하는 한 요소이다. 따라서 [3]int[5]int는 string과 float32처럼 타입 자체가 다르다. 기억해야할 점은 배열은 이후에 크기를 바꿀 수 없다.

- ex)

package main

import "fmt"

func main() {
	
	//1)
	var arr1 [5]int // 길이가 5인 int형 배열 선언
	fmt.Println(arr1) // [0 0 0 0 0] 출력
	 
	arr1 = [5]int{1,2,3,4,5} //배열을 초기화 
	fmt.Println(arr1[0],arr1[1])
	
	
	//2)
	arr2 := [4]int{8,9,10} //:=을 이용해 배열 선언(main안에서만 사용가능)
	arr2[0] = 30 // 인덱스를 이용해 값 초기화 
	fmt.Println(arr2)
	
	//3)
	var arr3 = [...]int{1,2,3,4,5} //[...]를 이용한 배열 크기 자동 설정
	fmt.Println(len(arr3))
	
	
}

슬라이스(slice)

go언어에서의 슬라이스는 배열과 다르게 고정된 크기를 미리 지정하지 않고 필요에 따라 크기를 동적으로 변경할 수 있고, 부분발췌가 가능하다. 지금까지 자료형을 선언할때 var num int와 같은 형태로 선언을 했는데 이는 한개의 int형의 변수가 들어갈 메모리를 만들었다는 뜻이다. 하지만 go에서는 아무런 값을 초기화지 않고 선언만 해도 0,또는 ""(빈칸)이 자동 할당된다. 배열도 마찬가지로 크기를 지정하고 선언하기 때문에 명시한 개수만큼의 메모리가 만들어진다. var arr2 [3]int를 만들면 3개의 int타입의 변수가 들어갈 메모리가 만들어지고, 초기화되지 않아도 자동으로 0이 할당된다. 따라서 선언만 했을 뿐인데 len()을 이용하면 배열의 크기가 3이라는 것을 알 수 있다.

하지만, 슬라이스를 위에서 설명한 것과 같은 방법으로 var a []int와 같이 선언하면 배열의 일부분을 가리키는 포인터를 만든다. 선언만 하고 초기화를 하지 않아서 슬라이스의 정보만 있는 배열만 생성되고, 실질적으로 어떠한 변수가 들어갈 공간(메모리)가 생성되지 않는다. 그 이유는 슬라이스는 크기를 미리 지정하지 않기 때문에 컴퓨터가 어디서 어디서부터 0이나 ""으로 채워야할지 모르기 때문이다. 따라서 슬라이스의 초기값을 지정하지 않고 선언만 한다면 "Nil slice"가 된다. 이는 크기도 용량도 없는 상태를 의미한다.

기본적으로 슬라이스는 아무런 값도 초기화하지않아도 배열의 위치를 가리키는 ptr과 배열의 길이인 len, 전체크기인 cap을 가지고 있다. 따라서 슬라이스를 var a []int와 같인 선언을 할 때는 주로 var a []int = []int{1,2,3,4}와 같이 선언과 동시에 값을 초기화하때만 사용한다. 이때 부터 슬라이스의 길이와 용량을 확인하는 함수를 사용할 수 있다.

이러한 내부구조를 이해한다면 슬라이스의 복사를 더 잘 이해할 수있다. 배열은 다른 배열의 값을 대입하면 값 자체가 대입된다. 하지만 슬라이스는 참조 타입이기 때문에 슬라이스를 복사해온다는 것은 사실 같은 주소를 참조한다는 것과 같다.

- ex)

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
	
	
	//1)
	var a []int // 슬라이스 변수 선언, 아직 변수가 들어갈 메모리 X
	
	a = []int{1,2,3,4} //슬라이스에 값 지정 
	
	a[1] = 10 // 값이 할당되어 메모리가 생겨 이런 방식으로 접근 가능
	
	fmt.Println(a)
	
	//2)
	
	var b []int //nil slice 선언
	if b == nil{
		fmt.Println("용량이",cap(b),"길이가",len(b),"인 nil slice입니다.")
	
}

- make()함수를 이용한 슬라이스 선언

  • make()를 이용하면 슬라이스를 선언만 하면서 크기를 미리 지정할수 있다. 즉 값을 저장할 수 있는 메모리를 선언만 함으로써 생성할수 있다. 이 함수는 슬라이스를 생섬함과 동시에 슬라이스의 길이(len), 슬라이스의 용량(cap)을 저장할 수 있다. 이 함수는 make(슬라이스 타입,슬라이스 길이, 슬라이스 용량) 형태로 선언한다. 여기서 용량(capacity)는 생략 가능하다. 이렇게 make() 함수를 이용해 선언하면 비로소 모든 요소가 0인 슬라이를 만들 수 있다.
  • 길이 : 초기화된 슬라이스의 요소 개수, 만약 값을 추가하거나 삭제한다면 그만큼 길이가 바뀐다.
  • 용량 : 슬라이스는 배열의 길이가 동적으로 늘어날 수 있기 때문에 길이와 용량을 구분한다.
// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
	
	a := make([]int, 0 , 3)// len=3, cap=3인 슬라이스 선언
	
	for i:=1; i <=10; i++{
		a = append(a,i) // 기존의 슬라이스에 하나씩 추가 
	 
	}
	
	fmt.Print(a)
	
}

또한 슬라이스 추가,병합시에 주의해야할 점은 추가하는 슬라이스 뒤에 꼭 "..."를 붙여야한다. ...는 슬라이스의 모든 요소들의 집합을 표현하는 것으로 예시의 {4,5,6}으로 치환된다는 것이다 따라서 슬라이스에 슬라이를 추가하는 것이 아니라 sliceA에 {4,5,6}이 추가되는 것이다.

// You can edit this code!
// Click here and start typing.
package main

import "fmt"

func main() {
	
	//append
	sliceA := []int{1,2,3}
	sliceB := []int{4,5,6}
	
	sliceA = append(sliceA,sliceB...)
	
	fmt.Println(sliceA)
	
	//copy
	sliceC := []int{1,2,3}
	sliceD := make([]int,len(sliceC),cap(sliceC)*2) // sliceC의 용량이 2배
	copy(sliceD, sliceC) // C에 D를 붙여넣는다. 
	
	fmt.Println(sliceD)
	fmt.Println(len(sliceC),cap(sliceD))
	
}

맵(Map)

  • 맵은 파이썬의 dicts와 같이 key값과 그에 해당하는 value를 매핑해 저장하는 hash table이다. 맵의 선언은 var 맵이름 map[key자료형]value 자료형 형식이다. 예를 들어 string형 key와 int형 value를 의 선언은 var 맵이름 map[string]int이다.

- 예시

package main

import "fmt"

func main(){
	var a map[int]string // map 선언
	
	if a == nil{
		fmt.Println("nil map") 
	}
    
    //선언과 동시에 초기화 
	var m = map[string]string{
		
		"apple" : "red",
		"grape" : "purple",
		"banana" : "yellow",
	}
	
	fmt.Println(m)
	fmt.Println(len(m))
}

- 추가,갱신,삭제

  • 맵 컬렉션에 메모리가 할당(make() or {}를 통한 초기화)가 됐으면 값을 추가,갱신,삭제할수 있다. 슬라이스는 값을 추가하기 위해 append()를 사용했지만 맵에서의 key는 특별하기 때문에 맵이름[key] = value형식으로 값을 추가할 수 있다. 주의할 점은 이미 있는 Key값에 다시 다른 value를 저장한다면 최근 저장한 값으로 갱신된다.
package main

import "fmt"

func main(){
	var m = make(map[string]string) //make를 통한 맵 선언0 -> 메모리 할당
	
	m["02"] = "서울특별시"
	m["031"] = "경기도"
	
	fmt.Print(m)
	
	
	m["031"] = "인천" // 동일한 key값을 사용하면 초기화 
	
	delete(m,"02") //삭제
}

좋은 웹페이지 즐겨찾기