Type alias vs type definition in Go
Asked Answered
M

4

22

I have stumbled upon this type alias in code:

type LightSource = struct {
  R, G, B, L float32
  X, Y, Z, A float32
  //...
}

My question is: what would be the reason to use a type alias like that to define a struct, rather than doing this?

type LightSource struct {
  R, G, B, L float32
  //...etc
}
Malayoindonesian answered 28/1, 2019 at 13:4 Comment(0)
H
5

Difference

  • With =, it's alias type. It doesn't create a new type, it just creates a symbol to the same type.
  • Without =, it's type definition. It creates a new type.

In usage

  • When assign value of original type:
    • alias type can assign directly, without cast.
    • new type need cast, because it's a different type.
  • Method on alias type can be used on original type; while method on type definition can't.

Example

type_alias_vs_new_test.go:

package main

import "testing"

type (
    A = int // alias type
    B int   // new type
)

func TestTypeAliasVsNew(t *testing.T) {
    var a A = 1 // A can actually be omitted,
    println(a)

    var b B = 2
    println(b)

    var ia int
    ia = a // no need cast,
    println(ia)

    var ib int
    ib = int(b) // need a cast,
    println(ib)
}
Hormuz answered 12/8, 2023 at 4:29 Comment(0)
B
16

In this case I assume this was done by mistake - the first alternative defines a type "anonymously" and then assigns an alias to it, so the end result is the same in both cases, but still the second alternative is the only correct one.

Type aliases are useful only in a few cases, e.g. as written here, they can be useful for large-scale refactoring.

Byrn answered 28/1, 2019 at 13:22 Comment(0)
B
6

I find type aliases useful for readability. For example, in tests you might compare the output of the JSON decoder like this:

reflect.DeepEqual(r, map[string]interface{}{"a": map[string]interface{}{"b": 42.0}})

but you can use a type alias to improve the readability:

type JsonObject = map[string]interface{}
...
reflect.DeepEqual(r, JsonObject{"a": JsonObject{"b": 42.0}})

Because DeepEqual uses reflection to compare the types (and values) then making the type alias a type definition (by removing the = character) will cause DeepEqual to fail. You can try it in the Go Playground

Barbarity answered 12/12, 2021 at 22:57 Comment(0)
H
5

Difference

  • With =, it's alias type. It doesn't create a new type, it just creates a symbol to the same type.
  • Without =, it's type definition. It creates a new type.

In usage

  • When assign value of original type:
    • alias type can assign directly, without cast.
    • new type need cast, because it's a different type.
  • Method on alias type can be used on original type; while method on type definition can't.

Example

type_alias_vs_new_test.go:

package main

import "testing"

type (
    A = int // alias type
    B int   // new type
)

func TestTypeAliasVsNew(t *testing.T) {
    var a A = 1 // A can actually be omitted,
    println(a)

    var b B = 2
    println(b)

    var ia int
    ia = a // no need cast,
    println(ia)

    var ib int
    ib = int(b) // need a cast,
    println(ib)
}
Hormuz answered 12/8, 2023 at 4:29 Comment(0)
S
3

To add to Rob64's answer, he states that the end result is the same, but do not mistake the fact that you'll end up with two different types.

type LightSource = struct { // Type struct
  R, G, B, L float32
  X, Y, Z, A float32
  //...
}
type LightSource struct { // Type LightSource
  R, G, B, L float32
  //...etc
}

I feel that there's a lot of confusion in the fact that you'll end up with a different type, this means that if somewhere in your code you enforce a type A, and you use the wrong way of type aliasing, you'll end up with absolutely zero restriction on your "type alias"; the end-goal would really be to differentiate your types if you do end up creating a type alias, but that's obviously void if you make this mistake.

Go play<<

Sledgehammer answered 4/3, 2022 at 9:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.