Golang map 사용 주의사항

6108 단어 Go기초
1. 프로필
map 는 Golang 에서 편리 하고 강력 한 내장 데이터 구조 로 같은 유형의 요소 의 무질서 한 그룹 입 니 다. 요 소 는 다른 유형의 유일한 키 를 통 해 색인 을 합 니 다.그 키 는 정수, 부동 소수점, 복수, 문자열, 포인터, 인터페이스 (동적 유형 이 같은 판단 을 지원 한다 면), 구조 와 배열 등 모든 동일 한 조작 부호 가 지원 하 는 유형 일 수 있 습 니 다.절편 은 맵 키 로 사용 할 수 없습니다. 왜냐하면 그들의 동일성 이 아직 정의 되 지 않 았 기 때 문 입 니 다.절편 과 마찬가지 로 맵 도 참조 형식 입 니 다.함수 에 맵 을 전송 하고 이 맵 의 내용 을 변경 하면 호출 자 에 게 도 보 입 니 다.초기 화 되 지 않 은 맵 값 은 nil 입 니 다.
사용 예 는 다음 과 같다.
package main

import "fmt"

func main() {
        nameAge := make(map[string]int)
        nameAge["bob"] = 18                     // 
        nameAge["tom"] = 16                     // 
        delete(nameAge, "bob")                  // 
        nameAge["tom"] = 19                     // 
        v := nameAge["tom"]                     // 
        fmt.Println("v=",v)
        v, ok := nameAge["tom"]                 // ,    
        if ok { 
            fmt.Println("v=",v,"ok=",ok)
        }   
        for k, v :=range nameAge {      		//  
                fmt.Println(k, v)
        }   
}

출력 결과:
v= 19
v= 19 ok= true
tom 19

2. 주의사항
2.1 map 의 요 소 는 취 할 수 없 는 주소 입 니 다.
map 의 요 소 는 변수 가 아니 라 값 입 니 다.따라서, 우 리 는 맵 의 요소 에 대해 주소 지정 작업 을 할 수 없습니다.
var m = map[int]int {
	0 : 0,
	1: 1,
}

func main() {
        fmt.Println(&m[0])
}

실행 오류:
cannot take the address of m[0]

따라서 맵 의 요소 가 구조 체 형식의 값 이면 구조 체 의 필드 값 을 직접 수정 할 수 없습니다.다음 과 같은 예 를 고찰 한다.
package main

import (
        "fmt"
)

type person struct {
    name   string
    age    byte
    isDead bool
}

func whoIsDead(personMap map[string]person) {
    for name, _ := range personMap {
        if personMap[name].age < 50 {
            personMap[name].isDead = true
        }   
    }   
}

func main() {
    p1 := person{name: "zzy", age: 100}
    p2 := person{name: "dj", age: 99} 
    p3 := person{name: "px", age: 20} 
    personMap := map[string]person{
        p1.name: p1, 
        p2.name: p2, 
        p3.name: p3, 
    }   
    whoIsDead(personMap)
    
    for _, v :=range personMap {
        if v.isDead {
            fmt.Printf("%s is dead
", v.name) } } }

컴 파일 오류:
cannot assign to struct field personMap[name].isDead in map

맵 요 소 는 주 소 를 찾 을 수 없 기 때문에 personMap [name] 을 얻 을 수 있 지만 수정 할 수 없습니다.해결 방법 은 두 가지 가 있 습 니 다. 하 나 는 map 의 value 는 struct 의 포인터 형식 을 사용 하고 다른 하 나 는 임시 변 수 를 사용 하여 매번 꺼 낸 후에 다시 설정 합 니 다.
(1) 맵 의 요 소 를 struct 의 지침 으로 변경 합 니 다.
package main

import (
        "fmt"
)

type person struct {
    name   string
    age    byte
    isDead bool
}

func whoIsDead(people map[string]*person) {
    for name, _ := range people {
        if people[name].age < 50 {
            people[name].isDead = true
        }   
    }   
}

func main() {
    p1 := &person{name: "zzy", age: 100}
    p2 := &person{name: "dj", age: 99} 
    p3 := &person{name: "px", age: 20} 
    personMap := map[string]*person {
        p1.name: p1, 
        p2.name: p2, 
        p3.name: p3, 
    }   
    whoIsDead(personMap)
    
        for _, v :=range personMap {
                if v.isDead {
                        fmt.Printf("%s is dead
", v.name) } } }

출력 결과:
px is dead

(2) 임시 변 수 를 사용 하여 원래 요 소 를 덮어 씁 니 다.
package main

import (
        "fmt"
)

type person struct {
    name   string
    age    byte
    isDead bool
}

func whoIsDead(people map[string]person) {
    for name, _ := range people {
        if people[name].age < 50 {
            tmp := people[name]
            tmp.isDead = true
            people[name] = tmp 
        }   
    }   
}

func main() {
    p1 := person{name: "zzy", age: 100}
    p2 := person{name: "dj", age: 99} 
    p3 := person{name: "px", age: 20} 
    personMap := map[string]person {
        p1.name: p1, 
        p2.name: p2, 
        p3.name: p3, 
    }   
    whoIsDead(personMap)
    
        for _, v :=range personMap {
                if v.isDead {
                        fmt.Printf("%s is dead
", v.name) } } }

출력 결과:
px is dead

2.2 map 동시 읽 기와 쓰기 문제
공유 맵 은 읽 기와 쓰기 에 자 물 쇠 를 추가 해 야 합 니 다.먼저 잘못된 예 시 를 보십시오.
package main

import (
        "fmt"
        "time"
)

var m = make(map[int]int)

func main() {
        //  go  map 
        go func(){
                for i := 0; i < 10000; i++ {
                        m[i] = i    
                }   
        }() 

        //  go  map 
        go func(){
                for i := 0; i < 10000; i++ { 
                        fmt.Println(m[i])    
                }   
        }() 
        time.Sleep(time.Second*20)
}

실행 오류:
fatal error: concurrent map read and map write

읽 기와 쓰기 자물쇠 (sync. RWMutex) 를 사용 하여 상호 배척 접근 을 실현 할 수 있 습 니 다.
package main

import (
        "fmt"
        "time"
        "sync"
)

var m = make(map[int]int)
var rwMutex sync.RWMutex

func main() {
        //  go  map 
        go func(){
                rwMutex.Lock()
                for i := 0; i < 10000; i++ {
                        m[i] = i    
                }   
                rwMutex.Unlock()
        }() 

        //  go  map
        go func(){
                rwMutex.RLock()
                for i := 0; i < 10000; i++ { 
                        fmt.Println(m[i])    
                }   
                rwMutex.RUnlock()
        }() 
        time.Sleep(time.Second*20)
}

정상 실행 출력:
0
1
...
9999

참고 문헌
[1] 실효 Go 프로 그래 밍. 맵 [2] Go 프로 그래 밍 언어 규범. 맵 형식 [3] golang 초보 자가 범 하기 쉬 운 3 가지 오류 [4] golang map 에서 구조 체 요 소 는 주 소 를 찾 을 수 없습니다.

좋은 웹페이지 즐겨찾기