수색…
소개
맵은 정렬되지 않은 키 - 값 쌍을 저장하는 데 사용되는 데이터 유형이므로 주어진 키와 연관된 값을 찾는 것이 매우 효율적입니다. 키는 고유합니다. 기본 데이터 구조는 새로운 요소를 수용하기 위해 필요할 때마다 커지므로 프로그래머는 메모리 관리에 대해 걱정할 필요가 없습니다. 다른 언어에서 해시 테이블, 사전 또는 연관 배열이라고하는 것과 유사합니다.
통사론
- var mapName map [KeyType] ValueType //지도를 선언하십시오.
- var mapName = map [KeyType] ValueType {} // 빈 Map을 선언하고 할당합니다.
- var mapName = map [KeyType] ValueType {key1 : val1, key2 : val2} //지도를 선언하고 할당합니다.
- mapName : = make (map [KeyType] ValueType) // 기본 크기 맵을 선언하고 초기화합니다.
- mapName : = make (map [KeyType] ValueType, length) // 길이의 크기를 선언하고 초기화한다 map
- mapName : = map [KeyType] ValueType {} // 자동으로 선언하고 빈지도를 지정합니다. =
- mapName : = map [KeyType] ValueType {key1 : value1, key2 : value2} //지도를 자동 선언하고 지정하려면 : =
- value : = mapName [key] // 키로 값을 가져옵니다.
- 값, hasKey : = mapName [key] // 키로 값을 가져오고, 맵에 키가 있으면 'hasKey'는 'true'입니다.
- mapName [key] = value // 키로 값 설정
비고
Go는 해시 테이블 을 구현하는 기본 제공 map
유형을 제공 합니다 . 지도는 Go의 내장 연관 데이터 유형 (다른 언어의 해시 또는 사전 이라고도 함)입니다.
지도 선언 및 초기화
키워드 map
과 키 유형 및 값을 사용하여 맵을 정의합니다.
// Keys are ints, values are ints.
var m1 map[int]int // initialized to nil
// Keys are strings, values are ints.
var m2 map[string]int // initialized to nil
지도 참조 형식, 그리고 정의하면 그들은이 제로 값 nil
. nil 맵에 대한 쓰기는 패닉 상태가 되고 읽기는 항상 0 값을 리턴합니다.
맵을 초기화하려면 make
함수를 사용하십시오.
m := make(map[string]int)
make
의 두 매개 변수 형식을 make
하면 기본 용량을 무시하고지도의 초기 입력 용량을 지정할 수 있습니다.
m := make(map[string]int, 30)
또는지도를 선언하고 나중에 0 값으로 초기화 한 다음 나중에 리터럴 값을 할당 할 수 있습니다. 이렇게하면 구조체를 json으로 마샬링하여 반환 할 빈지도를 만드는 데 도움이됩니다.
m := make(map[string]int, 0)
중괄호 ( {}
)를 사용하여지도를 만들고 초기 값을 설정할 수도 있습니다.
var m map[string]int = map[string]int{"Foo": 20, "Bar": 30}
fmt.Println(m["Foo"]) // outputs 20
다음의 모든 명령문은 변수가 동일한 값에 바인드되도록합니다.
// Declare, initializing to zero value, then assign a literal value.
var m map[string]int
m = map[string]int{}
// Declare and initialize via literal value.
var m = map[string]int{}
// Declare via short variable declaration and initialize with a literal value.
m := map[string]int{}
또한 지도 리터럴 을 사용하여 초기 키 / 값 쌍이있는 새지도 를 만들 수 있습니다.
키 유형은 모든 비교 가능한 유형이 될 수 있습니다. 특히 이것은 함수, 맵 및 조각을 제외합니다 . 값 유형은 사용자 정의 유형 또는 interface{}
포함하여 모든 유형이 될 수 있습니다.
type Person struct {
FirstName string
LastName string
}
// Declare via short variable declaration and initialize with make.
m := make(map[string]Person)
// Declare, initializing to zero value, then assign a literal value.
var m map[string]Person
m = map[string]Person{}
// Declare and initialize via literal value.
var m = map[string]Person{}
// Declare via short variable declaration and initialize with a literal value.
m := map[string]Person{}
지도 만들기
복합 리터럴을 사용하여 단일 명령문에서 맵을 선언하고 초기화 할 수 있습니다.
자동 유형 단축 변수 선언 사용 :
mapIntInt := map[int]int{10: 100, 20: 100, 30: 1000}
mapIntString := map[int]string{10: "foo", 20: "bar", 30: "baz"}
mapStringInt := map[string]int{"foo": 10, "bar": 20, "baz": 30}
mapStringString := map[string]string{"foo": "one", "bar": "two", "baz": "three"}
동일한 코드이지만 변수 유형이있는 경우 :
var mapIntInt = map[int]int{10: 100, 20: 100, 30: 1000}
var mapIntString = map[int]string{10: "foo", 20: "bar", 30: "baz"}
var mapStringInt = map[string]int{"foo": 10, "bar": 20, "baz": 30}
var mapStringString = map[string]string{"foo": "one", "bar": "two", "baz": "three"}
지도에 자신의 구조체를 포함시킬 수도 있습니다.
사용자 정의 유형을 값으로 사용할 수 있습니다.
// Custom struct types
type Person struct {
FirstName, LastName string
}
var mapStringPerson = map[string]Person{
"john": Person{"John", "Doe"},
"jane": Person{"Jane", "Doe"}}
mapStringPerson := map[string]Person{
"john": Person{"John", "Doe"},
"jane": Person{"Jane", "Doe"}}
구조체는지도의 키 가 될 수도 있습니다.
type RouteHit struct {
Domain string
Route string
}
var hitMap = map[RouteHit]int{
RouteHit{"example.com","/home"}: 1,
RouteHit{"example.com","/help"}: 2}
hitMap := map[RouteHit]int{
RouteHit{"example.com","/home"}: 1,
RouteHit{"example.com","/help"}: 2}
대괄호 {}
안에 값을 입력하지 않고 단순히 빈지도를 만들 수 있습니다.
mapIntInt := map[int]int{}
mapIntString := map[int]string{}
mapStringInt := map[string]int{}
mapStringString := map[string]string{}
mapStringPerson := map[string]Person{}
변수를 변수에 할당하지 않고지도를 직접 만들고 사용할 수 있습니다. 그러나 선언과 내용을 모두 지정해야합니다.
// using a map as argument for fmt.Println()
fmt.Println(map[string]string{
"FirstName": "John",
"LastName": "Doe",
"Age": "30"})
// equivalent to
data := map[string]string{
"FirstName": "John",
"LastName": "Doe",
"Age": "30"}
fmt.Println(data)
지도의 0 값
map
의 0 값은 nil
이며 길이는 0
입니다.
var m map[string]string
fmt.Println(m == nil) // true
fmt.Println(len(m) ==0) // true
nil
맵은 키가 없으며 키를 추가 할 수 있습니다. nil
맵은 읽혀지면 빈 맵처럼 작동하지만 작성된 경우 런타임 패닉이 발생합니다.
var m map[string]string
// reading
m["foo"] == "" // true. Remember "" is the zero value for a string
_, ok = m["foo"] // ok == false
// writing
m["foo"] = "bar" // panic: assignment to entry in nil map
0 값지도를 읽거나 쓰지 마십시오. 대신에, (와지도 초기화 make
을 사용하기 전에 또는 할당).
var m map[string]string
m = make(map[string]string) // OR m = map[string]string{}
m["foo"] = "bar"
지도 요소 반복하기
import fmt
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for key, value := range people {
fmt.Println("Name:", key, "Age:", value)
}
범위 루프를 사용하여 맵을 반복 할 때 반복 순서는 지정 되지 않으며 한 반복에서 다음 반복까지 동일하지 않을 수 있습니다.
키를 잡거나 값을 잡으려고하는 경우 키 또는지도 값을 무시할 수도 있습니다.
지도의 키 반복하기
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for key, _ := range people {
fmt.Println("Name:", key)
}
키를 찾고있는 경우에는 첫 번째 값이므로 밑줄을 단순히 삭제할 수 있습니다.
for key := range people {
fmt.Println("Name:", key)
}
범위 루프를 사용하여 맵을 반복 할 때 반복 순서는 지정 되지 않으며 한 반복에서 다음 반복까지 동일하지 않을 수 있습니다.
지도 요소 삭제하기
delete
내장 함수는 지정된 키가있는 요소를 맵에서 제거합니다.
people := map[string]int{"john": 30, "jane": 29}
fmt.Println(people) // map[john:30 jane:29]
delete(people, "john")
fmt.Println(people) // map[jane:29]
map
이 nil
이거나 그러한 요소가없는 경우, delete
는 효과가 없습니다.
people := map[string]int{"john": 30, "jane": 29}
fmt.Println(people) // map[john:30 jane:29]
delete(people, "notfound")
fmt.Println(people) // map[john:30 jane:29]
var something map[string]int
delete(something, "notfound") // no-op
지도 요소 계산 중
내장 함수 len
은 map
의 요소 수를 반환합니다.
m := map[string]int{}
len(m) // 0
m["foo"] = 1
len(m) // 1
변수가 nil
지도를 가리키는 경우 len
은 0을 반환합니다.
var m map[string]int
len(m) // 0
지도의 동시 액세스
이동중인지도는 동시성에 안전하지 않습니다. 동시에 액세스 할 경우 잠금을 사용하여 읽기 및 쓰기 작업을 수행해야합니다. 일반적으로 가장 좋은 방법은 잠금을 읽고 쓸 수 있기 때문에 sync.RWMutex
를 사용하는 sync.RWMutex
입니다. 그러나 sync.Mutex
사용할 수도 있습니다.
type RWMap struct {
sync.RWMutex
m map[string]int
}
// Get is a wrapper for getting the value from the underlying map
func (r RWMap) Get(key string) int {
r.RLock()
defer r.RUnlock()
return r.m[key]
}
// Set is a wrapper for setting the value of a key in the underlying map
func (r RWMap) Set(key string, val int) {
r.Lock()
defer r.Unlock()
r.m[key] = val
}
// Inc increases the value in the RWMap for a key.
// This is more pleasant than r.Set(key, r.Get(key)++)
func (r RWMap) Inc(key string) {
r.Lock()
defer r.Unlock()
r.m[key]++
}
func main() {
// Init
counter := RWMap{m: make(map[string]int)}
// Get a Read Lock
counter.RLock()
_ = counter.["Key"]
counter.RUnlock()
// the above could be replaced with
_ = counter.Get("Key")
// Get a write Lock
counter.Lock()
counter.m["some_key"]++
counter.Unlock()
// above would need to be written as
counter.Inc("some_key")
}
랩퍼 기능의 절충은 기본 맵의 공개 액세스와 적절한 잠금 사용 사이에 있습니다.
슬라이스가있는 맵을 값으로 만들기
m := make(map[string][]int)
존재하지 않는 키에 액세스하면 nil 슬라이스가 값으로 반환됩니다. nil 슬라이스는 append
또는 다른 내장 함수와 함께 사용할 때 길이가 0 인 슬라이스처럼 동작하기 때문에 일반적으로 키가 있는지 확인하지 않아도됩니다.
// m["key1"] == nil && len(m["key1"]) == 0
m["key1"] = append(m["key1"], 1)
// len(m["key1"]) == 1
맵에서 키를 삭제하면 키가 nil 슬라이스로 다시 설정됩니다.
delete(m, "key1")
// m["key1"] == nil
지도에서 요소 확인
지도에서 가치를 얻으려면 다음과 같이해야합니다. 00
value := mapName[ key ]
지도에 키가 포함되어 있으면 해당 값을 반환합니다.
그렇지 않은 경우는, 맵의 값 형의 제로 치를 int
치의 맵의 경우는 0
, string
치치의 경우는 ""
...」)
m := map[string]string{"foo": "foo_value", "bar": ""}
k := m["foo"] // returns "foo_value" since that is the value stored in the map
k2 := m["bar"] // returns "" since that is the value stored in the map
k3 := m["nop"] // returns "" since the key does not exist, and "" is the string type's zero value
빈 값과 존재하지 않는 키를 구별하기 위해 map 액세스의 두 번째 반환 값을 사용할 수 있습니다 (같은 value, hasKey := map["key"]
).
이 두 번째 값은 boolean
입력이며 다음과 같습니다.
- 값이 맵 내에있는 경우는
true
, - 맵에 지정된 키가없는 경우는
false
다음 예를보십시오.
value, hasKey = m[ key ]
if hasKey {
// the map contains the given key, so we can safely use the value
// If value is zero-value, it's because the zero-value was pushed to the map
} else {
// The map does not have the given key
// the value will be the zero-value of the map's type
}
지도의 값 반복하기
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for _, value := range people {
fmt.Println("Age:", value)
}
범위 루프를 사용하여 맵을 반복 할 때 반복 순서는 지정 되지 않으며 한 반복에서 다음 반복까지 동일하지 않을 수 있습니다.
지도 복사
슬라이스처럼 맵은 기본 데이터 구조에 대한 참조 를 보유합니다. 따라서 다른 변수에 값을 할당하면 참조 만 전달됩니다. 지도를 복사하려면 다른지도를 만들고 각 값을 복사해야합니다.
// Create the original map
originalMap := make(map[string]int)
originalMap["one"] = 1
originalMap["two"] = 2
// Create the target map
targetMap := make(map[string]int)
// Copy from the original map to the target map
for key, value := range originalMap {
targetMap[key] = value
}
지도를 세트로 사용
일부 언어는 집합에 대한 기본 구조를 가지고 있습니다. Go에서 세트를 만들려면 세트의 값 유형에서 빈 구조체 ( map[Type]struct{}
)로 맵을 사용하는 것이 가장 좋습니다.
예를 들어, 문자열의 경우 :
// To initialize a set of strings:
greetings := map[string]struct{}{
"hi": {},
"hello": {},
}
// To delete a value:
delete(greetings, "hi")
// To add a value:
greetings["hey"] = struct{}{}
// To check if a value is in the set:
if _, ok := greetings["hey"]; ok {
fmt.Println("hey is in greetings")
}