Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are typedefs for primitive values equivalent in golang?

Tags:

go

Given this code:

type Philosopher int
const (
    Epictetus Philosopher = iota
    Seneca
)

func Quote(who Philosopher) string {
    fmt.Println("t: ", reflect.TypeOf(who))
    switch who {
    case Epictetus:
        return "First say to yourself what you would be; 
                and do what you have to do"
    case Seneca:
        return "If a man knows not to which port he sails, 
                No wind is favorable"
    }
    return "nothing"
}

Calling Quote(5) will print Foo.Philosopher as the type for 5. Why didn't the type checker complain since that is what a type safe enums are supposed to do i.e. limit the scope of values ?

like image 268
canadadry Avatar asked Mar 17 '14 21:03

canadadry


3 Answers

These are not enums as you think of them. Type Philosopher is more or less an alias of an int. More or less, because it is a fundamentally distinct type, which can define its own methods.

The point of it is to provide semantic grouping of constants in a way that is clear to the programmer. Additionally, one gets the benefit of Go's type checker during compile time. But only to the degree that a value passed into a func(Philosopher) can not be implicitly interpreted as such. Passing a literal 5 as the parameter works, because constants like that in Go are inherently untyped. This will not work;

n := 5
Quote(n)  // Compile error -> int is not Philosopher

Reason being that n is defined as int. There exists no implicit conversion between type int and Philosopher. However, this will work:

n := 5
Quote(Philosopher(n))

Because the type cast is valid. Go does not care whether or not 5 is a valid and pre-defined Philosopher constant.

like image 63
jimt Avatar answered Oct 17 '22 08:10

jimt


Go doesn’t make any guarantees about valid values, except for those implied by int. The use of iota is just a convenience for defining a series of constants; it doesn’t say anything about valid values.

5 is a valid int, and therefore a valid Philosopher. You could also create const Plato = Philosopher(5).

like image 45
Matt Sherman Avatar answered Oct 17 '22 10:10

Matt Sherman


Shorter answer should be like :

An untyped constant takes the type needed by its context.

like image 20
noonex Avatar answered Oct 17 '22 10:10

noonex