Why does the Go language put the type behind?

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

This article organizes the self-knowledge, the original author @ lin built into.

Not to be different. But to be more clear and understandable.

Rob Pike Once explained the problem in the Go official blog (original address: Http://blog.golang.org/gos-declaration-syntax), briefly translated as follows (the wrong place of the horizontal limited translation is forgiven):

Introduction

Go language newcomers often wonder why the language's declarative grammar (declaration syntax) differs from the traditional C-family language. In this blog post, we will make a comparison and answer.

The syntax of C

First, let's look at the syntax of C. C uses a clever and unusual declarative syntax. When declaring a variable, simply write out an expression with the name of the target variable, and then indicate the type of the expression itself in an expression. Like what:

int x;

The above code declares a x variable, and its type is int --that is, the expression x is of int type. In general, in order to indicate the type of a new variable, we have to write an expression that contains the variable we want to declare, the result value of the expression operation is of a basic type, and we write the base type to the left of the expression. Therefore, the following statement:

int *p;int a[3];

Indicates that a p pointer is a int type, because *p the type is int . aIt is an int array, because a[3] the type is int (regardless of the index value that appears here, it is only used to indicate the length of the array).

Let's look at the case of the function declaration next. The type of the parameter in the function declaration of C is written outside the parentheses, as follows:

int main(argc, argv)    int argc;    char *argv[];{ /* ... */ }

As mentioned earlier, we can see that the main reason is a function because the expression main(argc, argv) returns int . In modern notation we write:

int main(int argc, char *argv[]) { /* ... */ }

Although it may seem a little different, the basic structure is the same.

On the whole, when the type is relatively simple, C's syntax seems very clever. But unfortunately, once the type begins to get complicated, this grammar of C can quickly become confusing. Well-known examples such as function pointers, we have to write as follows:

int (*fp)(int a, int b);

Here, the fp reason is a pointer because if you write (*fp)(a, b) such an expression will call a function that returns the int value of the type. What happens if fp one of the arguments itself is a function?

int (*fp)(int (*ff)(int x, int y), int b)

It's a bit hard to read.

Of course, we can declare a function without specifying the name of the parameter, so the main function can be declared as:

int main (int, char *[])

Think back, it argv was the following.

char *argv[]

Did you notice that you removed the variable name from the "middle" of the declaration and then constructed its variable type? Although this is not obvious, when you declare a char *[] variable of a type, you need to insert the name into the middle of the variable type.
Let's take a look at what happens if we don't name fp the arguments:

int (*fp)(int (*)(int, int), int)

This thing is difficult to understand is not only to remember that the name of the parameter is originally placed in the middle

int (*)(int, int)

It's even more confusing, and it may not be clear that this is a function pointer declaration. Let's take a look at what happens if the return value is also a function pointer type

int (*(*fp)(int (*)(int, int), int))(int, int)

It's hard to see what fp the statement is about.

You can build more complex examples yourself, but this is enough to explain some of the complexities introduced by C's declarative syntax.
It is also important to point out that because the type syntax and the declarative syntax are the same, it can be difficult to parse an expression with a type in the middle. That's why C is always putting the type in parentheses when doing type conversions, like this

(int)M_PI

The Grammar of Go

Non-c-family languages typically use a different type syntax when declaring. Usually the name appears first, followed by a colon. According to this, the example we've shown above will turn out to be the following:

x: intp: pointer to inta: array[3] of int

Such statements, even if they are lengthy, are at least clear-you just need to read from left to right. The go language approach is based on this, but for the sake of simplicity, the go language loses the colon and removes some of the keywords, as follows:

x intp *inta [3]int

[3]int a There is no direct correspondence to the usage in the expression (we will go back to the question of pointers in the next section). At this point, you gain the clarity of the code, but the cost is that the syntax needs to be treated differently.

Let's consider the problem of the function. Although in the Go language, main functions do not actually have parameters, we first copy the declaration of the previous main function:

func main(argc int, argv *[]byte) int

A rough look and C are nothing different, but reading from left to right is good.

mainThe function accepts one int and one pointer and returns one int .

If you remove the name of the parameter at this point, it is clear-because the parameter name is always in front of the type, it does not cause confusion.

func main(int, *[]byte) int

One of the values of this self-left-to-right statement is that it remains relatively simple when the type becomes more complex. The following is a declaration of a function variable (equivalent to a function pointer in the C language)

f func(func(int,int) int, int) int

Or when it returns a function:

f func(func(int,int) int, int) func(int, int) int

The above statement reads clearly, from left to right, and it is easy to understand which variable name is currently declared-because the variable name is always in the first place.

The difference between type syntax and expression syntax makes it easier to call closures in the Go language:

sum := func(a, b int) int { return a+b } (3, 4)

Pointer

There are some exceptions to pointers. Note that in arrays (array) and slices (slice), Go's type syntax places the square brackets on the left side of the type, but in the expression syntax it puts the square brackets to the right:

var a []intx = a[1]

Similarly, the pointer to Go follows the notation of C * , but when we write it is also declared * on the right side of the variable name, but in the expression has to be put * to the left:

var p *intx = *p

Can't be written down like this

var p *intx = p*

Because the suffix * may be confused with the multiplication operation, maybe we can use Pascal's ^ tag, like this

var p ^intx = p^

We might really want to * change this to ^ (of course, the notation for the XOR operation), because prefixes in types and expressions * do complicate things a bit, for example, although we can write them like this.

[]int("hi")

However, if the type is at the * beginning of the conversion, parentheses are added:

(*int)(nil)

If one day we are willing to give up use * as the pointer syntax, then the above parentheses can be omitted.

As can be seen, the pointer syntax for GO is similar to C. But this similarity also means that we cannot completely avoid the need to supplement parentheses in grammar sometimes in order to avoid the ambiguity of types and expressions.

In a word, despite the shortcomings, we believe that the type grammar of Go is easier to understand than C. Especially when the type is more complex.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.