Back-End/Golang

golang: 배열, 슬라이스, 맵

슝슝이입니다 2024. 10. 27. 10:13
반응형

1. 배열 (Arrays)

  • 정적 크기: 배열은 생성 시 크기가 고정되며, 한 번 설정하면 변경할 수 없습니다.
  • 동일 타입 요소: 모든 요소는 같은 타입이어야 합니다.
  • 메모리 연속성: 배열은 메모리에 연속적으로 저장되므로 특정 인덱스에 빠르게 접근할 수 있습니다.
var arr [5]int                    // 길이가 5인 int 배열, 모든 요소는 0으로 초기화
arr[0] = 1                         // 배열의 첫 번째 요소에 값 할당
arr2 := [3]string{"Go", "is", "fun"} // 리터럴을 사용해 초기화 가능

for i, v := range arr2 {
    fmt.Printf("index: %d, value: %s\n", i, v)
}

 

실전 예시

package main

import "fmt"

func main() {
    // 한 달(30일)의 일일 매출 데이터를 저장
    dailySales := [30]float64{1000.5, 2000.75, 1500.3, /* ... */} // 고정된 크기의 배열

    // 총 매출 계산
    var totalSales float64
    for _, sales := range dailySales {
        totalSales += sales
    }

    fmt.Printf("총 매출: %.2f\n", totalSales)
}

2. 슬라이스 (Slices)

  • 동적 크기: 슬라이스는 배열의 래퍼로, 크기를 유동적으로 조정할 수 있습니다.
  • 배열 참조: 슬라이스는 내부적으로 배열을 참조하므로 새 배열을 할당하지 않아도 슬라이스를 통해 배열 데이터를 다룰 수 있습니다.
  • make와 리터럴: make 함수 또는 리터럴을 통해 생성할 수 있습니다.
var slice []int                    // nil 슬라이스, 길이와 용량이 0
slice = make([]int, 3)             // 길이 3, 용량 3인 슬라이스 생성
slice2 := []int{1, 2, 3, 4, 5}     // 리터럴을 사용해 슬라이스 초기화

// 슬라이싱으로 슬라이스 생성
slice3 := slice2[1:4]              // 인덱스 1~3 요소 포함 (2, 3, 4)

 

  • 슬라이스 속성:
    • len: 슬라이스 길이를 반환
    • cap: 슬라이스 용량을 반환
  • 추가 및 확장:
    • append 함수를 사용하여 슬라이스에 요소 추가 가능
package main

import "fmt"

func main() {
    // 초기 슬라이스
    slice := []int{2, 3, 4}
    fmt.Println("초기 슬라이스:", slice)

    // 1. 슬라이스 뒤에 요소 추가
    slice = append(slice, 5)
    fmt.Println("뒤에 5 추가:", slice)

    // 2. 슬라이스 앞에 요소 추가
    slice = append([]int{1}, slice...)
    fmt.Println("앞에 1 추가:", slice)

    // 3. 슬라이스에서 마지막 요소 제거
    slice = slice[:len(slice)-1]
    fmt.Println("뒤에 요소 제거:", slice)

    // 4. 슬라이스에서 첫 번째 요소 제거
    slice = slice[1:]
    fmt.Println("앞에 요소 제거:", slice)

    // 5. 앞과 뒤 요소를 동시에 제거
    slice = slice[1 : len(slice)-1]
    fmt.Println("앞과 뒤 요소 제거:", slice)
}

 

 

실전 예시

package main

import (
    "fmt"
    "strings"
)

func main() {
    // 예시 데이터: 사용자 의견 (동적으로 추가되는 데이터)
    feedback := []string{
        "서비스가 좋았습니다.",
        "배달이 빨라서 만족스러웠어요.",
        "제품이 기대 이하였습니다.",
    }

    // 새로운 의견 추가
    feedback = append(feedback, "친절한 고객 서비스에 감사해요.")

    // 특정 단어 포함 의견 필터링
    keyword := "좋"
    var filteredFeedback []string
    for _, comment := range feedback {
        if strings.Contains(comment, keyword) {
            filteredFeedback = append(filteredFeedback, comment)
        }
    }

    fmt.Println("특정 단어 포함 의견:", filteredFeedback)
}

3. 맵 (Maps)

  • 키-값 쌍 데이터 구조: 맵은 키-값 쌍을 저장하는 자료형으로, 키로 데이터를 빠르게 조회할 수 있습니다.
  • 동적 크기: 맵은 크기를 동적으로 조정할 수 있습니다.
  • 키-값 타입 정의 필요: 맵을 정의할 때 키와 값의 타입을 명시해야 합니다.
  • make로 초기화: 맵은 make로 초기화하거나 리터럴로 생성합니다.
var personAge map[string]int              // nil 맵, 사용할 수 없음
personAge = make(map[string]int)          // 빈 맵 생성
personAge["Alice"] = 25                   // 키-값 쌍 추가
personAge["Bob"] = 30

// 리터럴 초기화
colors := map[string]string{
    "red":   "#FF0000",
    "green": "#00FF00",
    "blue":  "#0000FF",
}

 

요소 접근 및 삭제:

age := personAge["Alice"]            // 값 읽기
delete(personAge, "Bob")             // "Bob" 키 삭제

키 존재 여부 확인:

age, exists := personAge["Alice"]
if exists {
    fmt.Printf("Alice의 나이는 %d입니다.\n", age)
}

 

실전 예시

package main

import (
    "fmt"
    "time"
)

func main() {
    // 로그인 사용자 관리 (맵 사용)
    userSessions := map[string]time.Time{
        "user1": time.Now().Add(-time.Hour), // 1시간 전 로그인
        "user2": time.Now().Add(-30 * time.Minute), // 30분 전 로그인
    }

    // 새로운 로그인 세션 추가
    userSessions["user3"] = time.Now()

    // 세션 만료 검사 및 삭제 (1시간 초과 시 만료)
    for user, loginTime := range userSessions {
        if time.Since(loginTime) > time.Hour {
            fmt.Printf("%s 세션 만료\n", user)
            delete(userSessions, user)
        }
    }

    fmt.Println("현재 로그인 사용자:", userSessions)
}

 

주요 차이점

반응형