[Go/Golang] Go언어 배열 다루는 또 다른 방법 slice 알아보기!!

2022. 6. 12. 20:0003. Resources/Go

728x90
반응형

이번엔 go에서 중요하다고 하는 slice에 대해서 알아보자!

https://gobyexample.com/slices

 

Go by Example: Slices

Slices are a key data type in Go, giving a more powerful interface to sequences than arrays. package main import "fmt" func main() { Unlike arrays, slices are typed only by the elements they contain (not the number of elements). To create an empty slice wi

gobyexample.com

 

위의 링크에서 말하길 array보다 sequence를 다루기에 훨씬 좋은 인터페이스라고 한다!

 

그럼 예제 코드를 먼저 같이 보자

package main

import "fmt"

func main() {

    s := make([]string, 3)
    fmt.Println("emp:", s)

    s[0] = "a"
    s[1] = "b"
    s[2] = "c"
    fmt.Println("set:", s)
    fmt.Println("get:", s[2])

    fmt.Println("len:", len(s))

    s = append(s, "d")
    s = append(s, "e", "f")
    fmt.Println("apd:", s)

    c := make([]string, len(s))
    copy(c, s)
    fmt.Println("cpy:", c)

    l := s[2:5]
    fmt.Println("sl1:", l)

    l = s[:5]
    fmt.Println("sl2:", l)

    l = s[2:]
    fmt.Println("sl3:", l)

    t := []string{"g", "h", "i"}
    fmt.Println("dcl:", t)

    twoD := make([][]int, 3)
    for i := 0; i < 3; i++ {
        innerLen := i + 1
        twoD[i] = make([]int, innerLen)
        for j := 0; j < innerLen; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)
}

이번엔 예제코드가 좀 길다.

 

먼저 선언하는 부분을 보면, 비어있는 slice를 make라는 함수를 이용해서 선언할 수 있다.

    s := make([]string, 3)
    fmt.Println("emp:", s)

저렇게 선언해서 실행한 결과는 아래처럼 비어있다고 나온다.

emp: [  ]

그냥 하나의 빈칸으로 보여서 길이를 추가로 출력해보면 아래처럼 나온다.

emp: [  ]
Len emp: 3

원하는대로 3개의 원소를 가질 수 있는 빈 배열이 선언됐다. 

아무런 값도 들어있지 않은 이유는 string의 zero-value가 " ", 빈 값이기 때문이다.

아래 코드처럼 int로 타입을 바꿔서 넣어보면 

    s := make([]int, 3)
    fmt.Println("emp:", s)
    fmt.Println("Len emp:", len(s))

아래처럼 0, 0, 0 이 잘 들어있는 것을 볼 수 있다.

emp: [0 0 0]
Len emp: 3

이전에 봤던 array처럼 각 원소별 접근도 가능하다.
길이도 받아올 수 있다.

 

파이썬의 리스트처럼 append를 이용해서 원소를 추가할 수도 있다.

    s = append(s, "d")
    s = append(s, "e", "f")
    fmt.Println("apd:", s)

조금 다른건 위의 코드처럼 한 번에 여러개를 추가하는 것도 가능하다.

 

slice를 복사하는 것도 쉽게 가능하다

    c := make([]string, len(s))
    copy(c, s)
    fmt.Println("cpy:", c)

동일한 사이즈를 가지는 변수를 하나 선언한 뒤에 copy를 이용해서 복사하면 된다.

 

slicing은 파이썬이랑 아예 동일하다.

    l := s[2:5]
    fmt.Println("sl1:", l)

    l = s[:5]
    fmt.Println("sl2:", l)

    l = s[2:]
    fmt.Println("sl3:", l)

선택되는 범위도 아예 동일하기 때문에 이해하기 훨씬 쉽다.

sl1: [c d e]
sl2: [a b c d e]
sl3: [c d e f]

결과는 위처럼 나온다.

 

    t := []string{"g", "h", "i"}
    fmt.Println("dcl:", t)

변수를 정의하면서 초기값을 설정하는 것도 가능하다.

배열의 사이즈를 정의하지 않고 사용하니까 아래처럼 초기값으로 넣어주는 것만 일단 들어간다.

dcl: [g h i]

2차원 slice도 쉽게 정의할 수 있는데, 2차원 배열을 slice로 선언하는 경우에는, 정해진 사이즈의 테이블을 만드는 것이 아니라, 각 원소별로 다른 사이즈를 가지는 배열을 만들 수 있다.

    twoD := make([][]int, 3)
    fmt.Println("2d: ", twoD)
    for i := 0; i < 3; i++ {
        innerLen := i + 1
        twoD[i] = make([]int, innerLen)
        for j := 0; j < innerLen; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)

궁금해서 처음엔 어떻게 생겨먹었나 출력을 해봤고, 결과를 조회해봤는데 아래처럼 나온다.

2d:  [[] [] []]
2d:  [[0] [1 2] [2 3 4]]

인트로 선언했는데 0이 들어가진 않고있다. 2차원 배열의 경우 zero-value를 초기에 설정하지 않는 것 같다.

그리고 각 원소별로 다른 사이즈를 가지고 있는 것을 볼 수 있다.

 

아래처럼 강제로 innerLen에 단일 값을 넣으면 단일 사이즈로 구성되는 것도 확인할 수 있다.

    twoD := make([][]int, 3)
    fmt.Println("2d: ", twoD)
    for i := 0; i < 3; i++ {
        // innerLen := i + 1
        innerLen := 3
        twoD[i] = make([]int, innerLen)
        for j := 0; j < innerLen; j++ {
            twoD[i][j] = i + j
        }
    }
    fmt.Println("2d: ", twoD)
2d:  [[] [] []]
2d:  [[0 1 2] [1 2 3] [2 3 4]]

slice를 이용하면 다양한 데이터를 쉽게 처리할 수 있는 것 같다.

사실 파이썬처럼 쉽게 생각하면 그냥 list안에 list를 넣는 것이라고 볼 수 있다.

 

반응형