Как очистить карту в Go?


86

Я ищу что-то вроде функции c ++ .clear() для примитивного типа map.

Или лучше просто создать новую карту?

Обновление: Спасибо за ответы. Посмотрев на ответы, я понял, что иногда создание новой карты может привести к некоторой несогласованности, которой мы не хотим. Рассмотрим следующий пример:

var a map[string]string
var b map[string]string

func main() {
    a = make(map[string]string)
    b=a
    a["hello"]="world"
    a = nil
    fmt.Println(b["hello"])
}

Я имею в виду, что это все еще отличается от .clear()функции в C ++, которая очищает содержимое объекта.


1
также см. это обсуждение: groups.google.com/d/topic/golang-nuts/6yHDC7IYCj4/discussion
perreal

1
есть также обсуждение встроенной продувки
perreal

Ответы:


110

Вам, вероятно, следует просто создать новую карту. Нет никакой реальной причины беспокоиться о попытках очистить существующую, если только на одну и ту же карту не ссылаются несколько частей кода, и одна часть явно не нуждается в очистке значений, чтобы это изменение было видно другим частям кода.

Так что да, тебе, наверное, стоит просто сказать

mymap = make(map[keytype]valtype)

Если вам действительно нужно очистить существующую карту по какой-либо причине, это достаточно просто:

for k := range m {
    delete(m, k)
}

1
Значит, удаление элементов по одному - единственный способ сделать это?
lavin

@lavin: Ага. Для этого нет встроенной функции, и у вас не может быть библиотечной функции, которая делает это для произвольных карт. Но все равно это всего 3 строчки.
Лили Баллард

6
Можно ли изменять содержимое карты, перебирая все значения? Другие языки с этим работать не будут.
Джон Джеффри

5
@JohnJeffery: Я тестировал это перед тем, как опубликовать. Кажется, работает. Фактический язык из спецификации говорит, что The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next. If map entries that have not yet been reached are deleted during iteration, the corresponding iteration values will not be produced. If map entries are inserted during iteration, the behavior is implementation-dependent, but the iteration values for each entry will be produced at most once. If the map is nil, the number of iterations is 0.это означает, что он поддерживается.
Лили Баллард

18
Начиная с Go 1.11, операции очистки карты этой формы оптимизируются компилятором. github.com/golang/go/blob/master/doc/go1.11.html
Бенджамин Б.

21

В отличие от C ++, Go - это язык со сборкой мусора. Вам нужно думать о вещах немного по-другому.

Когда вы делаете новую карту

a := map[string]string{"hello": "world"}
a = make(map[string]string)

исходная карта в конечном итоге будет собрана в мусор; вам не нужно очищать его вручную. Но помните, что карты (и срезы) являются ссылочными типами; вы создаете их с помощью make(). Базовая карта будет собираться мусором только тогда, когда на нее нет ссылок. Таким образом, когда вы делаете

a := map[string]string{"hello": "world"}
b := a
a = make(map[string]string)

исходный массив не будет собираться сборщиком мусора (до тех пор, пока b не будет собран или b не будет ссылаться на что-то еще).


3
// Method - I , say book is name of map
for k := range book {
    delete(book, k)
}

// Method - II
book = make(map[string]int)

// Method - III
book = map[string]int{}

-5

Если вы пытаетесь сделать это в цикле, вы можете воспользоваться инициализацией, чтобы очистить карту для вас. Например:

for i:=0; i<2; i++ {
    animalNames := make(map[string]string)
    switch i {
        case 0:
            animalNames["cat"] = "Patches"
        case 1:
            animalNames["dog"] = "Spot";
    }

    fmt.Println("For map instance", i)
    for key, value := range animalNames {
        fmt.Println(key, value)
    }
    fmt.Println("-----------\n")
}

Когда вы выполняете это, он очищает предыдущую карту и запускается с пустой картой. Это подтверждается выводом:

$ go run maptests.go 
For map instance 0
cat Patches
-----------

For map instance 1
dog Spot
-----------

3
Это не очистка карты, а создание новой карты и привязка к локальной переменной с тем же именем в каждом цикле.
Delaney
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.