Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map as a method receiver

Tags:

go

Does anyone know why map can be used as a value receiver, but when working with slices only the pointer receiver can 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]
like image 394
zitryss Avatar asked Mar 08 '18 14:03

zitryss


People also ask

What is the receiver of a method?

The Method Receiver and the this Argument. A method's receiver is an implicit formal argument named this representing the expression on which the method is invoked. The receiver's actual argument is specified by the receiver-clause of a method-call-expression as specified in Method Calls.

What is method receiver in golang?

Introduction. A method is just a function with a special receiver type between the func keyword and the method name. The receiver can either be a struct type or non-struct type. The syntax of a method declaration is provided below.


2 Answers

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
}
like image 184
peterSO Avatar answered Sep 30 '22 21:09

peterSO


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

like image 31
Sanjeev Choubey Avatar answered Sep 30 '22 19:09

Sanjeev Choubey