映射为方法接收者

Does anyone know why map can be used as a value receiver, but when working with slices only the pointer receiver has to be used? Why the map is changing after the method call?

Example for map:

package main

import (
    "fmt"
)

type hashMap map[string]int

func (s hashMap) Add(k string, v int) {
    s[k] = v
}

func main() {
    var s hashMap
    s = make(hashMap, 0)
    fmt.Println(s)
    s.Add("abc", 15)
    fmt.Println(s)
}

Output:

map[]
map[abc:15]

Example for slice:

package main

import (
    "fmt"
)

type slice []int

func (s *slice) Add(v int) {
    (*s) = append(*s, v)
}

func main() {
    var s slice
    s = make(slice, 0)
    fmt.Println(s)
    s.Add(15)
    fmt.Println(s)
}

Output:

[]
[15]

A map variable, after make, is a pointer to the map header: *hmap. The map pointer is passed by value

// A header for a Go map.
type hmap struct {
    // Note: the format of the Hmap is encoded in ../../cmd/internal/gc/reflect.go and
    // ../reflect/type.go. Don't change this structure without also changing that code!
    count     int // # live cells == size of map.  Must be first (used by len() builtin)
    flags     uint8
    B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
    noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
    hash0     uint32 // hash seed

    buckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
    oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
    nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)

    extra *mapextra // optional fields
}

A slice variable is a struct: slice. The slice struct is passed by value.

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

Map is receiver type while struct is value type,Value type. Hence when you call using map value changes after function call.