Why can I type alias functions and use them without casting?

jsdw

In Go, if you define a new type e.g.:

type MyInt int

You can't then pass a MyInt to a function expecting an int, or vice versa:

func test(i MyInt) {
    //do something with i
}

func main() {
    anInt := 0
    test(anInt) //doesn't work, int is not of type MyInt
}

Fine. But why is it then that the same does not apply to functions? e.g.:

type MyFunc func(i int)
func (m MyFunc) Run(i int) {
    m(i)
}

func run(f MyFunc, i int) {
    f.Run(i)
}

func main() {
    var newfunc func(int) //explicit declaration
    newfunc = func(i int) {
        fmt.Println(i)
    }
    run(newfunc, 10) //works just fine, even though types seem to differ
}

Now, I'm not complaining because it saves me having to explicitly cast newfunc to type MyFunc, as I would have to do in the first example; it just seems inconsistent. I'm sure there is a good reason for it; can anyone enlighten me?

The reason I ask is mainly because I would like to shorten some of my rather long function types in this way, but I want to make sure it's expected and acceptable to do this :)

jsdw

Turns out, this is a misunderstanding that I had about how Go dealt with types, which can be resolved by reading the relevant part of the spec:

http://golang.org/ref/spec#Type_identity

The relevant distinction that I was unaware of was that of named and unnamed types.

Named types are types with a name, such as int, int64, float, string, bool. In addition, any type you create using 'type' is a named type.

Unnamed types are those such as []string, map[string]string, [4]int. They have no name, simply a description corresponding to how they are to be structured.

If you compare two named types, the names must match in order for them to be interchangeable. If you compare a named and an unnamed type, then as long as the underlying representation matches, you're good to go!

e.g. given the following types:

type MyInt int
type MyMap map[int]int
type MySlice []int
type MyFunc func(int)

the following is invalid:

var i int = 2
var i2 MyInt = 4
i = i2 //both named (int and MyInt) and names don't match, so invalid

the following is fine:

is := make([]int)
m := make(map[int]int)
f := func(i int){}

//OK: comparing named and unnamed type, and underlying representation
//is the same:
func doSlice(input MySlice){...}
doSlice(is)

func doMap(input MyMap){...}
doMap(m)

func doFunc(input MyFunc){...}
doFunc(f)

I'm a bit gutted I didn't know that sooner, so I hope that clarifies the type lark a little for someone else! And means much less casting than I at first thought :)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

In Typescript, how can I use functions defined in another TS file without puting them in a module?

From Dev

How can I make a class that type-erases objects until a function is called on them without specifying the list of possible functions up front?

From Dev

Why can you use just the alias to declare a enum and not the .NET type?

From Dev

Why can't I use my column alias in WHERE clause?

From Dev

why can not i use the transpose function without :?

From Dev

Why can we assign a literal integer of 32 bit to a variable of type short without casting?

From Dev

Casting an alias template to the aliased type

From Dev

Casting an alias template to the aliased type

From Dev

Why can't virtual functions use return type deduction?

From Dev

Type casting on arrow functions

From Dev

Type Casting / Callback Functions

From Dev

Why does casting from JSON literal to type not include functions

From Dev

Why can't I declare templated type aliases inside of functions?

From Dev

How can I execute Lua functions from C++ without having to find them each time?

From Dev

How can I execute Lua functions from C++ without having to find them each time?

From Dev

Can't use my "type" ComplexNumber without "new"--why?

From Dev

Why can functions in Python print variables in enclosing scope but cannot use them in assignment?

From Dev

Why I can use private methods from template functions

From Dev

Why can't I use ._doc_ attribute for built in functions?

From Dev

How can I use XMLAgg function without an alias in the following SQL example?:

From Dev

Type Casting Issue, I'm not able to use the type members

From Dev

Can I export constructors along with a type alias?

From Dev

Why can the type arguments not be inferred, and how can I specify them explicitly?

From Dev

Can I divide my tests into separate specs and then call them from another or is it better to use helper functions?

From Dev

Why this type casting?

From Dev

Can I use edge type without connection types in GraphQL?

From Dev

Why does casting different pointer types cause TBAA (Type-Based Alias Analysis) violation?

From Dev

Why can I use the Date class without requiring 'date'?

From Dev

Why can I use `>>=` without an explicit or implicit definition?

Related Related

  1. 1

    In Typescript, how can I use functions defined in another TS file without puting them in a module?

  2. 2

    How can I make a class that type-erases objects until a function is called on them without specifying the list of possible functions up front?

  3. 3

    Why can you use just the alias to declare a enum and not the .NET type?

  4. 4

    Why can't I use my column alias in WHERE clause?

  5. 5

    why can not i use the transpose function without :?

  6. 6

    Why can we assign a literal integer of 32 bit to a variable of type short without casting?

  7. 7

    Casting an alias template to the aliased type

  8. 8

    Casting an alias template to the aliased type

  9. 9

    Why can't virtual functions use return type deduction?

  10. 10

    Type casting on arrow functions

  11. 11

    Type Casting / Callback Functions

  12. 12

    Why does casting from JSON literal to type not include functions

  13. 13

    Why can't I declare templated type aliases inside of functions?

  14. 14

    How can I execute Lua functions from C++ without having to find them each time?

  15. 15

    How can I execute Lua functions from C++ without having to find them each time?

  16. 16

    Can't use my "type" ComplexNumber without "new"--why?

  17. 17

    Why can functions in Python print variables in enclosing scope but cannot use them in assignment?

  18. 18

    Why I can use private methods from template functions

  19. 19

    Why can't I use ._doc_ attribute for built in functions?

  20. 20

    How can I use XMLAgg function without an alias in the following SQL example?:

  21. 21

    Type Casting Issue, I'm not able to use the type members

  22. 22

    Can I export constructors along with a type alias?

  23. 23

    Why can the type arguments not be inferred, and how can I specify them explicitly?

  24. 24

    Can I divide my tests into separate specs and then call them from another or is it better to use helper functions?

  25. 25

    Why this type casting?

  26. 26

    Can I use edge type without connection types in GraphQL?

  27. 27

    Why does casting different pointer types cause TBAA (Type-Based Alias Analysis) violation?

  28. 28

    Why can I use the Date class without requiring 'date'?

  29. 29

    Why can I use `>>=` without an explicit or implicit definition?

HotTag

Archive