key=value
çiftleri şeklinde içinde veri tuttuğumuz, key ekleme, çıkartma ve
silme yapabildiğimiz bir veri tipidir. Python’daki dict
ya da Ruby’deki
Hash
ya da Php’deki Associative Array
gibi düşünülebilir. Key üzerinden
value’ya ulaşmak O(1)
karmaşıklığındadır (complexity) yani çok hızlıdır.
- Hash table algoritmasını kullanır.
- Ekleme, çıkartma (silme), okuma
O(1)
karmaşıklığındadır. Sadece ekleme işlemi amortized karmaşıklık algoritması kullanır. - Key/Value çiftleri sıralanmadan (un-ordered) şekilde tutulur
- Key’ler eşsizdir (unique), bir map’te aynı key’den sadece bir tane olur
make
fonksiyonu ile map literal (map kalıbı) üretilir, hafızaya yerleştirilir, initialize olur- map’lerin initialize değeri
nil
olur,nil
olan map’e key eklenemez! len
bize key/value çiftinin uzunluğunu verir- map
nil
mi diye bakılabilir - map’leri birbiriyle kıyaslamak için
reflection.DeepEqual
fonksiyonu kullanılır.
https://go.dev/play/p/X7zOWsYTuyA
package main
import "fmt"
var m map[string]int // nil map, key’i string, value’su int...
func main() {
fmt.Println(m, len(m)) // map[] 0
// m["foo"] = 5 // panic: assignment to entry in nil map
m = make(map[string]int)
m["foo"] = 5
fmt.Println(m, len(m)) // map[foo:5] 1
}
map
alan fonksiyona nil
geçebiliriz, key var mı? yok mu ? bakabiliriz:
https://go.dev/play/p/difVbLWsdCr
package main
import "fmt"
type myMap map[string]string // key: string, value: string
func printMap(m myMap) {
fmt.Printf("%+v\n", m)
}
func main() {
printMap(nil) // map[]
m := myMap{
"username": "vigo",
}
printMap(m) // map[username:vigo]
fmt.Println(m["username"]) // vigo
fmt.Println(m["foo"]) //
val, ok := m["foo"]
fmt.Println("ok", ok) // ok false
fmt.Println("val", val) // val
}
Ekleme, çıkarma ve hatalı işlemler örneği:
https://go.dev/play/p/YhkzsWMBGBI
package main
import "fmt"
func main() {
m1 := map[string]int{
"ocak": 1,
"şubat": 2,
}
var m2 map[string]int
m2 = make(map[string]int)
m2["ocak"] = 1
m2["şubat"] = 2
fmt.Println(m1) // map[ocak:1 şubat:2]
fmt.Println(m2) // map[ocak:1 şubat:2]
// fmt.Println(m1 == m2)
// error:
// invalid operation: m1 == m2 (map can only be compared to nil)
m1["mart"] = 3
m2["mart"] = 3
fmt.Println(m1) // map[mart:3 ocak:1 şubat:2]
fmt.Println(m2) // map[mart:3 ocak:1 şubat:2]
delete(m1, "mart") // mart key'ini sil
fmt.Println(m1) // map[ocak:1 şubat:2]
for k, v := range m2 {
fmt.Println("key", k, "->", v)
}
// key ocak -> 1
// key şubat -> 2
// key mart -> 3
// m1["mart"] = "ok"
// error
// cannot use "ok" (untyped string constant) as int value in assignment
// m1[1] = "ocak"
// error
// cannot use 1 (untyped int constant) as string value in map index
// cannot use "ocak" (untyped string constant) as int value in assignment
}
Aynı Array ve Slice’daki gibi kapasite kavramı map
içinde var;
https://go.dev/play/p/7azH9ymAbvS
package main
import (
"fmt"
"unsafe"
)
func main() {
m1 := make(map[string]int, 10) // Preallocate, 10 tane yer ayır
fmt.Printf("%#v\n", m1) // map[string]int{}
fmt.Println(len(m1)) // 0
fmt.Println(unsafe.Sizeof(m1)) // 8 byte
m2 := make(map[string]int)
fmt.Println(unsafe.Sizeof(m2)) // 8 byte
}
Karşılaştırma;
https://go.dev/play/p/_XIw23G6bPq
package main
import (
"fmt"
"reflect"
)
func main() {
m1 := make(map[string]int, 10) // Preallocate, 10 tane yer ayır
m2 := make(map[string]int)
m1["foo"] = 1
m2["foo"] = 1
fmt.Println(m1 == nil) // false
fmt.Println(m2 == nil) // false
fmt.Println(reflect.DeepEqual(m1, m2)) // true
}
map
otomatik olarak referans tipindedir (by ref) aynı pointer ve slice’lar
gibi:
https://go.dev/play/p/VZz6a3Sn_QE
package main
import "fmt"
type myMap map[string]string
func modifyMap(m myMap) {
m["foo"] = "modified"
}
func main() {
var m myMap
m = make(myMap)
m["foo"] = "bar"
fmt.Printf("initial: %v, memory: %[1]p\n", m)
// initial: map[foo:bar], memory: 0x14000074180
fmt.Println("foo:", m["foo"])
// foo: bar
modifyMap(m)
fmt.Printf("modified: %v, memory: %[1]p\n", m)
// modified: map[foo:modified], memory: 0x14000074180
fmt.Println("foo:", m["foo"])
// foo: modified
}
Bazen map
’in sadece key
kısmı bize lazım olur, value
ile işimiz yoktur.
Bu durumda value yerine öyle bir şey koymalıyız ki 0 byte
yer kaplasın? Bu
durumda empty struct
tam da aradığımız şeydir:
https://go.dev/play/p/EUmDBlchY5b
package main
import "fmt"
func main() {
// elimizde 100_000 tane isim var
// acaba dışarıdan gelen isim bizimde var mı?
m := map[string]struct{}{
"uğur": {},
"erhan": {},
"turbo": {},
"vigo": {},
}
fmt.Println(m)
// map[erhan:{} turbo:{} uğur:{} vigo:{}]
// uğur var mı?
if _, ok := m["uğur"]; ok {
fmt.Println("uğur tanıdığımız biri")
// uğur tanıdığımız biri
}
}