映射作为方法接收器

时间:2018-03-08 14:56:57

标签: go

有谁知道为什么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)
}

输出:

map[]
map[abc:15]

切片示例:

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)
}

输出:

[]
[15]

2 个答案:

答案 0 :(得分:7)

make之后的map变量是指向地图标题的指针:*hmap。地图指针按值

传递
// 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
}

切片变量是结构:slice。 slice结构按值传递。

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

答案 1 :(得分:0)

映射是接收者类型,而结构是值类型,值类型。因此,当您使用地图调用时,函数调用后值会发生变化。