This is a creation in Article, where the information may have evolved or changed.
This article for the original article, reprint annotated source, welcome to sweep the code to pay attention flysnow_org
to the public number or website http://www.flysnow.org/, the first time to see the following wonderful articles. Feel good, and share to friends Circle, thank you for your support.
Beijing Time 2017.08.25,go1.9 official version released. Go1.9 through 2 beta, months, finally, released the official version. Go 1.9 contains a lot of changes, such as type alias, security concurrency map, parallel compilation and so on, is a big change, today this article mainly introduces the type alias.
Install Go 1.9
For many well-known reasons, you may not be able to download the latest Go 1.9 SDK, if you do not have a ladder, can be downloaded to my self-built mirror site, there are a lot of common development software, which contains the latest go 1.9. Mirror address: http://mirrors.flysnow.org/
Role
The primary purpose of this feature is to use a defined type that is compatible with the movement of the package. For example, we have an export type that we are flysnow.org/lib/T1
migrating to another package, for example flysnow.org/lib2/T1
in.
Without the type alias when we do this, it will cause other third parties to reference the old package path code, must be uniform modification, otherwise it will not be used.
With a type alias is not the same, the implementation of type T1 we can migrate to lib2, while we in the original Lib under the definition of a lib2 under the T1 alias, so that the third-party reference can not be modified, or normal use, only to be compatible for a period of time, Completely removing the type compatibility in the old package allows you to refactor our code incrementally instead of fits.
12 |
//package:flysnow.org/lib type T1=lib2. T1 |
Type alias vs defintion
We create a new type based on a type, called defintion; Create an alias based on a type called Alias, which is their biggest difference.
The first line of code is based on the primitive type int that created the new type MyInt1, the second line is the type alias MyInt2 created for an int, note that the type alias is defined =
.
1234 |
var int =0var//errorvar i2 MyInt2 = ifmt. Println (I1,I2) |
Looking closely at this example, the second line assigns a variable of type to a int
i
MyInt1
variable of type that i1
is prompted to compile the error: the type cannot be converted. But the third row int
assigns the variable of type to the i
MyInt2
variable of type, i2
and does not prompt the error.
As you can see from this example, the two definitions are different because go is a strongly typed language, so the conversions between types must be cast, because int
and MyInt1
are different types, so there is a compilation error.
But because MyInt2
just int
an alias, is essentially a int
type, so you can assign a value directly, no problem.
Type method
Each type can add its own method through the recipient's way, and we can see if the type alias is possible, and what methods are available.
1234567891011121314151617 |
type MyInt1 int type MyInt2 = int func (i MYINT1) m1 () {fmt. Println ( "myint1.m1" )}func (i MyInt2) m2 () {fmt. Println ( "myint2.m2" )}func main () {var i1 Myint1var i2 myint2i1.m1 () i2.m2 ()} |
The example code above looks no problem, but when we compile we will prompt:
12 |
i2.m2 undefined (typetype int |
There are 2 errors in this, one is that the hint type int
does not have m2
this method, so we cannot call it, because MyInt2
essentially int
.
The second error is that we can't int
add a new method to a type, what does it mean? Because it int
is a non-native type, we cannot add methods to it. In that case, let's customize a struct type to try.
12345678910111213141516171819202122 |
type User struct {} type MyUser1 usertype MyUser2 = Userfunc (i MyUser1) m1 () {fmt. Println ( "myuser1.m1" )}func Span class= "params" > (i MyUser2) m2 () {fmt. Println ( "myuser2.m2" )}//blog:www.flysnow.org //wechat:flysnow_org func main () {var i1 myuser1var i2 myuser2i1.m1 () i2.m2 ()} |
Switch to a struct and run normally. Therefore, the alias of a locally defined type can still be added to the method. Now let's proceed to the above example to see an interesting phenomenon, I add the following code in the main function:
Then run, discover, and run normally. Isn't it strange that we didn't define the method for the type User
, ah, how can it be called? This is due to the type alias, which is MyUser2
exactly equivalent User
, so MyUser2
defining the method equals User
defining the method, and vice versa.
But not for the new defined type, MyUser1
because it is a completely new type, so User
the method MyUser
is not. There is no longer an example, you can try it yourself.
It is also important to note that, because it is MyUser2
completely equivalent User
, User
there are already methods that MyUser2
cannot be declared, and vice versa, if defined as follows:
12 |
in the blockprevious declaration at./main.go:31:6 |
is actually the meaning of repeating the declaration, cannot repeat the declaration again.
Interface implementation
The above summary we can find, User
and MyUser2
is equivalent, and one of the new methods, the other one will have. So based on this derivation, one implementation of an interface, the other will be implemented. Now verify:
1234567891011121314151617181920212223242526 |
type I interface {m2 ()}type User struct {}type MyUser2 = user< Span class= "function" >func (i User) m {fmt. Println ( "USER.M" )}func (i MyUser2) m2 () {fmt. Println ( "myuser2.m2" )}func Span class= "title" >main () {var u uservar u2 myuser2var i1 I =uvar i2 I = U2fmt. Println (I1,I2)} |
Defines an interface, I
from the code point of view, only MyUser2
implemented it, but our code in the demonstration, found User
also implemented the interface I
, so this verifies that our push is correct, and return if User
an interface is implemented, then its type Alias will also implement this interface.
Many of the examples above are aliases of type structs, and we see if the type alias of interface interface is also equivalent.
1234567891011 |
type Interface {m ()} type MyI1 itype MyI2 = itypeintfunc(i MyInt)m (){fmt. Println ("MYINT.M")} |
Defines an interface I
that MyI1
is based on a I
new type, MyI2
is a type alias, and I
MyInt
implements an interface I
. Test the following.
12345678910111213141516 |
//blog:www.flysnow.org //wechat:flysnow_org funcmain() {//Assignment Implementation type MyIntvar i i = MyInt (0)var i1 MyI1 = MyInt (0)var< /c20> i2 MyI2 = MyInt (0)//Interface reciprocal assignment i = i1i = I2i1 = I2i1 = Ii2 = Ii2 = I1} |
The above code is normal, this is the specific type of the preceding (struct,int, etc.) of the type alias is not the same, as long as the implementation of the interface, you can assign value to each other, whether you are the newly defined interface MyI1
, or the interface alias MyI2
.
Types of nesting
We all know that the two types of type alias are equivalent, but they are somewhat different when nested in a type.
1234567891011121314151617181920 |
//blog:www.flysnow.org //wechat: flysnow_org func main () {my:=mystruct{}my. T2.M1 ()}type T1 struct {}func (t T1) m1 () {fmt. Println ( "t1.m1" )}type T2 = t1type mystruct struct {T2} |
The example T2
is T1
the alias, but we put the T2 nested in MyStruct
, when the call can only be T2
called by this name, and cannot pass T1
, will not prompt this field. The reverse is the same.
This is because T1
, T2
two names, although they are equivalent, they are equivalent types with two different names, so when the type is nested, it is two fields.
Of course we can put T1
, T2
at the same time embedded MyStrut
in, to make separate calls.
123456789101112 |
//blog:www.flysnow.org //wechat:flysnow_org funcmain() {my:=mystruct{}my. T2.M1 () My. T1.M1 ()}typestruct {t2t1} |
The above is also able to run normally, proving that this is a field of the same type with two different names.
Let's do an interesting experiment and main
change the code of the method to the following:
123456 |
Blog:www.flysnow.org//wechat:flysnow_orgfunc Main () {my:=mystruct{}my.m1 ()} |
Guess if you can compile and run it properly? The promise may unexpectedly, is unable to compile normally, prompts the following:
1 |
./main.go:25:4: Ambiguous selector my.m1 |
In fact, think very simple, do not know which to call, too vague, can not match, or the use T1
of m1
, T2
or m1
. This result is not limited to the method, the field is also the same, not limited to the type Alias,type defintion is also the same, as long as there are duplicate methods, fields, there is this hint, because do not know which to choose.
Type loop
Type alias declaration, be sure to pay attention to the types of loops, do not produce a loop, once produced, will compile does not pass, then what is the type of loop it. If type T2 = T1
, then T1
absolutely can not direct, or indirect reference to T2
, once there, will type loop.
1234567 |
type T2 = *t2type T2 = mystructtypestruct {t1t2} |
Both of these definitions are type loops, and we want to avoid the emergence of this definition in our own use.
Byte and Rune
These two types are int8 aliases, one is the alias of the Int32, and they are defined before go 1.9.
123 |
type byte byte type Rune Rune |
Now that go 1.9 has the new feature of type alias, their definition becomes the following:
123 |
type byte uint8 type Rune Int32 |
Yes, it's very convenient and concise.
Exporting types that are not exported
Type alias also has a feature to export a type that is not exported.
12345678910111213141516171819 |
Package Lib//blog:www.flysnow.org //wechat:flysnow_org type user struct {name Email string }func (u user) getname () string {return U.name}func (u user) getemail () string {return u. Email}//to export this user to user type user = user |
user
is a non-exported type and cannot be accessed by another package, but we can type User = user
define one through, User
so that this User
can be accessed by other package, you can use user
the fields and methods of the type export, the Email
fields and GetEmail
method, and the fields and methods that are not exported name
getName
are not used by other package.
Summary
The definition of type alias is essentially the same type, just an alias, how the source type is used, how the alias type is used, and all methods, fields, etc. of the source type are preserved.
This article for the original article, reprint annotated source, welcome to sweep the code to pay attention flysnow_org
to the public number or website http://www.flysnow.org/, the first time to see the following wonderful articles. Feel good, and share to friends Circle, thank you for your support.