배열
package main
import (
"fmt"
)
func main() {
var x [5]int // 초기화 하지 않으면 0으로 초기화 됨
var y [5]string // 초기화 하지 않으면 ""으로 초기화 됨
fmt.Println(x) // [0 0 0 0 0]
fmt.Println(y) // [ ]
var z [5]int = [5]int{1, 2, 3, 4, 5}
fmt.Println(z) // [1 2 3 4 5]
a := [...]int{1, 2, 3, 4, 5} // 배열의 크기를 ... 으로 지정하면 초기화 값의 개수만큼 크기가 정해짐
for index, value := range a {
fmt.Println(index, value)
/*
0 1
1 2
2 3
3 4
4 5
*/
}
}
슬라이스
슬라이스는 배열과 비슷하지만 몇 가지 장점을 가지고 있다.
- 크기를 지정하지 않고 생성할 수 있음
- 크기를 동적으로 증가 시킬 수 있음
- 부분 배열을 추출할 수 있음
package main
import (
"fmt"
)
func main() {
a := []int{1, 2, 3, 4, 5} // 슬라이스 a 생성
fmt.Println(a) // [1 2 3 4 5]
b := a[1:3] // 슬라이스 b 생성
fmt.Println(b) // [2 3]
fmt.Println(len(b), cap(b)) // 2 4
a[1] = 20 // 슬라이스 a의 두 번째 요소 변경
fmt.Println(a) // [1 20 3 4 5]
fmt.Println(b) // [20 3]
}
make()를 이용해 슬라이스를 생성할 수 있다.
- make(type, length/capacity) : type 값의 슬라이스를 length/capacity 길이만큼 만든다.
- make(type, length, capacity) : capacity만큼 늘릴 수 있는 type 값의 슬라이스를 length 길이만큼 만든다.
- append() : 슬라이스 끝에 항목을 추가하고 슬라이스의 크기를 늘린다. capacity를 초과해도 자동으로 늘려준다.
package main
import (
"fmt"
)
func main() {
a := make([]int, 0)
fmt.Println(a, len(a), cap(a)) // [] 0 0
a = append(a, 1)
fmt.Println(a, len(a), cap(a)) // [1] 1 1
b := make([]int, 0, 1)
fmt.Println(b, len(b), cap(b)) // [] 0 1
b = append(b, 1)
fmt.Println(b, len(b), cap(b)) // [1] 1 1
b = append(b, 2)
fmt.Println(b, len(b), cap(b)) // [1 2] 2 2
c := make([]int, 2, 4)
fmt.Println(c, len(c), cap(c)) // [0 0] 2 4
c = append(c, 1)
fmt.Println(c, len(c), cap(c)) // [0 0 1] 3 4
}
해시 테이블
장점은 list 보다 빠른 조회가 가능하고 임의의 키를 사용할 수 있다는 것이다.
단점은 충돌(두 개의 키가 같은 슬롯에서 해시되는 것)이 일어날 수 있다.
Map
Map은 Go에서 해시 테이블을 구현한 것이다.
make() 를 이용해서 Map을 만들 수 있다.
package main
import (
"fmt"
)
func main() {
// 맵 선언
m1 := map[string]int{}
m1["a"] = 1
m1["b"] = 2
fmt.Println(m1) // map[a:1 b:2]
fmt.Println(m1["a"]) // 1
// make로 맵 선언
m2 := make(map[string]string)
m2["A"] = "Hi"
m2["B"] = "Hello"
fmt.Println(m2) // map[A:Hi B:Hello]
fmt.Println(m2["A"]) // Hi
// 맵 선언과 동시에 초기화
m3 := map[int]string{
1: "A",
2: "B",
}
fmt.Println(m3) // map[1:A 2:B]
fmt.Println(m3[1]) // A
}
package main
import (
"fmt"
)
func main() {
m := map[int]string{
1: "A",
2: "B",
}
m[3] = "C" // 값 추가
fmt.Println(m) // map[1:A 2:B 3:C]
delete(m, 2) // 값 삭제
fmt.Println(m) // map[1:A 3:C]
v1, ok1 := m[2] // value 값을 가져와서 ok 값으로 존재 여부 확인
fmt.Println(v1, ok1) // "" false
v2, ok2 := m[3] // value 값을 가져와서 ok 값으로 존재 여부 확인
fmt.Println(v2, ok2) // C true
for k, v := range m {
fmt.Println(k, v)
/*
순서는 무작위로 나옴
1 A
3 C
*/
}
}
struct
Go는 객체 지향 언어이지만 클래스, 객체, 상속 개념이 없다.
package main
import (
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
p1 := Person{} // Person 객체 생성
p1.Name = "Lee"
p1.Age = 24
fmt.Println(p1) // {Lee 24}
p2 := Person{"Kim", 25} // Person 객체 생성
fmt.Println(p2) // {Kim 25}
p3 := Person{Name: "Park", Age: 26} // Person 객체 생성
fmt.Println(p3) // {Park 26}
p4 := new(Person) // Person 객체 생성
p4.Name = "Choi" // p가 포인터라도 .을 사용
p4.Age = 27
fmt.Println(p4) // &{Choi 27}
fmt.Println(*p4) // {Choi 27}
}
Go에서 필드 이름이 소문자로 시작하면 해당 필드는 외부 패키지에서 접근할 수 없는 비공개(private) 필드로 간주된다.
그래서 외부 패키지에서 접근이 가능하게 하려면 name 대신 Name으로 작성해야 된다.