why map the key type must not be a function, map, or slice

332 views
Skip to first unread message

mount...@gmail.com

unread,
Jan 22, 2019, 10:59:07 PM1/22/19
to golang-nuts
     When i use the func, map slice as the key of map, it isn't work! 
     So  I lookup source  why, i find 

    // spec: "The comparison operators == and != must be fully defined
        // for operands of the key type; thus the key type must not be a
        // function, map, or slice."
        //
        // Delay this check because it requires fully setup types;
        // it is safe to continue in any case (was issue 6667).
        check.later(func() {
            if !Comparable(typ.key) {
                check.errorf(e.Key.Pos(), "invalid map key type %s", typ.key)
            }
        })
// Comparable reports whether values of type T are comparable.
func Comparable(T Type) bool {
    switch t := T.Underlying().(type) {
    case *Basic:
        // assume invalid types to be comparable
        // to avoid follow-up errors
        return t.kind != UntypedNil
    case *Pointer, *Interface, *Chan:
        return true
    case *Struct:
        for _, f := range t.fields {
            if !Comparable(f.typ) {
                return false
            }
        }
        return true
    case *Array:
        return Comparable(t.elem)
    }
    return false
}

Ian Lance Taylor

unread,
Jan 22, 2019, 11:05:30 PM1/22/19
to mount...@gmail.com, golang-nuts
On Tue, Jan 22, 2019 at 7:59 PM <mount...@gmail.com> wrote:
>
> When i use the func, map slice as the key of map, it isn't work!
> So I lookup source why, i find

You don't have to look at the source, you can look at the language
spec. https://golang.org/ref/spec#Map_types "The comparison operators
== and != must be fully defined for operands of the key type; thus the
key type must not be a function, map, or slice."

In Go, function values are not comparable, so they can not be used as
map keys. This is to avoid various sorts of confusion. For example,
given this:

func F() func() int {
i := 0
return func() int {
i++
return i
}
}

should F() == F()? There is no obvious answer that clearly correct in
all cases, so we don't permit comparing function values at all.

Ian

mount...@gmail.com

unread,
Jan 23, 2019, 2:47:30 AM1/23/19
to golang-nuts
exec code:
package main

import "fmt"

func main() {
    fmt.Println(F() == F())
}

func F() func() int {
    i := 0
    return func() int {
        i++
        return i
    }
}


i got :
  # command-line-arguments
./key.go:6:18: invalid operation: F() == F() (func can only be compared to nil)


在 2019年1月23日星期三 UTC+8上午11:59:07,mount...@gmail.com写道:

Ian Lance Taylor

unread,
Jan 23, 2019, 10:26:57 AM1/23/19
to mount...@gmail.com, golang-nuts
On Tue, Jan 22, 2019 at 11:47 PM <mount...@gmail.com> wrote:
>
> i got :
> # command-line-arguments
> ./key.go:6:18: invalid operation: F() == F() (func can only be compared to nil)

Yes, that is what the language spec says and it is what I said: in Go,
function values are not comparable.

I wrote that code as an example to help explain why function values
are not comparable.

Ian
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

mount...@gmail.com

unread,
Jan 23, 2019, 10:47:32 PM1/23/19
to golang-nuts
thanks lan.

在 2019年1月23日星期三 UTC+8下午11:26:57,Ian Lance Taylor写道:

Victor Giordano

unread,
Jan 25, 2019, 9:46:56 AM1/25/19
to golang-nuts
Just wanna say : It would be nice to employ a custom type as a valid key for a map!!! :D

Burak Serdar

unread,
Jan 25, 2019, 10:04:08 AM1/25/19
to Victor Giordano, golang-nuts
On Fri, Jan 25, 2019 at 7:47 AM Victor Giordano <vituc...@gmail.com> wrote:
>
> Just wanna say : It would be nice to employ a custom type as a valid key for a map!!! :D

You can use a struct as a key.

Wagner Riffel

unread,
Jan 25, 2019, 10:04:38 AM1/25/19
to Victor Giordano, golang-nuts
you can "employ" any custom type as key but the ones that doesn't
defines equality operations, see
https://golang.org/ref/spec#Comparison_operators
as Ian already pointed out, you just can't build your custom type on
top of func, map or slice to be a valid key, anything else you can.

Victor Giordano

unread,
Jan 25, 2019, 10:31:57 AM1/25/19
to golang-nuts
Yeah, i got the idea. I had already researched about it and what you can do about it.
I was only repeating what i want as a dev in this community! 

mount...@gmail.com

unread,
Jan 26, 2019, 8:50:07 AM1/26/19
to golang-nuts
I use it often, I don't know what you mean by this.

在 2019年1月25日星期五 UTC+8下午11:04:08,Burak Serdar写道:

mount...@gmail.com

unread,
Jan 26, 2019, 8:56:53 AM1/26/19
to golang-nuts
I looked at your program example, mainly using the reflection type to design the mapped key, perhaps the reflected key is a comparable type, but I mainly propose specific types, such as func, slice, map can not be used as a key use

在 2019年1月25日星期五 UTC+8下午11:31:57,Victor Giordano写道:

Victor Giordano

unread,
Jan 26, 2019, 12:26:47 PM1/26/19
to mount...@gmail.com, golang-nuts
Yup! That's right! At the end of the day i used the enums idioms, employing integer type (the value that supports the "enum" )

(TL;DR;) Ancient History :

The problem arises as i get used to use maps in Java where you can use as a key a class definition (that is custom data type in Java, like the same way an "struct" in Golang is a custom data type). So i get use to work with types as keys, that way i could associate logic and data with an asbtraction (recall that logic and data does not intrinsically belong to that abstraction, so it would be wrong to place all in there).

I wake-up in golang without that capability: i mean how i may refer to a group of well know struct definitions in a generic way, i mean for example this: 

type Person struct {
}

var SpanishTermByStruct map[struct]string = map[struct]string{
Person: "person",
}

? and in that moment the wondering about using "type" for key (or value) comes to my mind... i then i get that is not allowed.


You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/Z0XQueZFoVw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

Wagner Riffel

unread,
Jan 26, 2019, 2:31:35 PM1/26/19
to Victor Giordano, mount...@gmail.com, golang-nuts
i don't quite understand why you're using enums as keys, you can use a anything but what already was pointed out, following your person example:

Victor Giordano

unread,
Jan 26, 2019, 4:37:20 PM1/26/19
to Wagner Riffel, mount...@gmail.com, golang-nuts
Probably i need to reveal the underlying problem i was trying to solve 

At a glande: an appoinment subsystem for a health organization, considering practitioners that work on services offering practices that refers to billables items, the practices may need one or more equipment, also taking into accountg the  practitioners availability expressed in relative periodic terms (weekly for example) and absoulte terms (a given day on the cosmos) and their holidays, and the location where the patient-doctor encounter will occur, also consdiering the center (a heath organization has one or many) holidays.

So  need to resolve availabiltiies to determine when a given practice can be performe. I have several structs represeting the entties involved in the process (the one marked in bold), for each one of these structs there is a theorical availbility and a actual usage that leads you to calculate the actual availlity, so everything related to the availabilty of these enties need to be placed somewhere, so my original idea was to associate each algoritm with the struct but without writing the algorithms as part of the struct, a map comes in handy here. 

robert engels

unread,
Jan 26, 2019, 4:46:17 PM1/26/19
to Victor Giordano, Wagner Riffel, mount...@gmail.com, golang-nuts
Yes, and you can do that.

Victor Giordano

unread,
Jan 26, 2019, 4:56:15 PM1/26/19
to robert engels, Wagner Riffel, mount...@gmail.com, golang-nuts
Thanks for sharing point the view!. And you can bet that i done that!!! :D It was quite a challenge you know!! In nowadays system is working, let keep crossing fingers please...
Reply all
Reply to author
Forward
0 new messages