Summary of basic knowledge of Go language (grammar variables numeric types expressions control structures etc.)

  • 2020-05-05 11:22:27
  • OfStack

1.

golang source code USES UTF-8 coding. Spaces include: white space, tab, line feed, and carriage return.

- the identifier consists of letters and Numbers (plus '_'), both of which are Unicode encoded.

- comments:


/* This is a comment; no nesting */
// So is this.

literals (literals) are similar to literals in the C language, but do not require symbols or size flags for numerical values:


23
0x0FF

e7 is similar to the string in C, but the string is encoded in Unicode/ UTF-8. Also, \xNN always has 2 Numbers; \012 is always 3; Both are bytes:

"Hello, world\n"
"\xFF" // 1 byte
"\u00FF" // 1 Unicode char, 2 bytes of UTF-8

Native string: '\n\.abc \t\' == "\\n\\.abc \\t\\"

3. Overview of

golang is basically the syntax for the class C, but with the inverted type and declaration, and the keyword at the beginning of each declaration.


var a int
var b, c *int // Pay attention to and C The different
var d []int
type S struct { a, b int }

The basic control structure is also familiar:


if a == b { return true } else { return false }
for i = 0; i < 10; i++ { ... }

Note: no parentheses, but braces are required.

More on this later.

four, semicolon

A semicolon is used as a statement termination symbol, but:

- if the previous symbol is the end of the statement, the lexical analyzer will automatically insert a semicolon
at the end of the line - note: clearer and simpler than JavaScript rules

Therefore, the following program does not require a semicolon:


package main const three = 3
var i int = three func main() { fmt.Printf("%d\n", i) }

In practice, the Go source code USES almost no semicolons outside the for and if clauses.

5. Numerical type

The golang numeric type (numeric types) is native and built-in and is also known as


int uint
int8 uint8 = byte
int16 uint16
int32 uint32 float32 complex64
int64 uint64 float64 complex128

There is also uintptr, a size large enough to store the value of a pointer.

These are all different types; int is not the same as int32, even on a 32-bit machine.

There is no implicit casting (but don't panic).

Bool

Common Boolean type bool, values true and false (predefined constants).

The if statement and so on use Boolean expressions.

Pointer types and integers are not Boolean types.

string

The native built-in string type represents an immutable array of bytes, that is, text. The string type is delimited by length, not terminated by the end of 0.

The string literal is of type string.

As immutable as an integer. You can reassert a value, but you cannot change its value.

Just as "3" is always 3, "hello" is always "hello".

The Go language provides good support for string manipulation.

vi. Expression (Expressions)

Most are operators of the C language.

binary operator:

The priority operator remarks
5 * / % < < > > & & ^ & ^ is the bit cleanup operator
4 + | ^ ^ is xor (xor)
3 == != < < = > > =
2 & &
1 ||

Unary operators include: & ! * + wok ^(plus < for communication -)
The unary operator ^ is a complement/inverse operation.

Go vs. C expression

C programmers can be pleasantly surprised:

Fewer priority levels (should be easy).
^ instead of ~
++ and wok are no longer expression operators (x++ is a statement, not an expression; *p++ is (*p)++, not * p++))
& ^ is the new operator, which is useful in constant expressions < < And > > An unsigned shift count is required.

No surprises:

The assignment operation is as expected: += < < = & ^ =
, etc The expression overall looks similar (subscripts, function calls, etc.)

Example:


+x
23 + 3*x[i]
x <= f()
^a >> b
f() || g()
x == y + 1 && <-ch > 0
x &^ 7 // x with the low 3 bits cleared
fmt.Printf("%5.2g\n", 2*math.Sin(PI/8))
7.234/x + 2.3i "hello, " + "world" // concatenation
// no C-like "a" "b"

numerical transformations

Converting a value from one type to another is called a transition, and its syntax is somewhat similar to that of a function call:


uint8(intVar) // Truncate to the corresponding size
int(float64Var) // Fragment truncation
float64(intVar) // to float64

Some involve string types of transformations:

string(0 x 1234) // == "\u1234"
string(sliceOfBytes) // bytes -> bytes
string(sliceOfInts) // ints -> Unicode/UTF-8
[]byte("abc") // bytes -> bytes
[]int(" Japan � ") // Unicode/UTF-8 -> ints

Slicing (slice) is related to arrays, more on that later.

The constant

Numerical constants are "ideal Numbers" : there is no size or flag, so there is no end to U, L, or UL.


077 // octal
0xFEEDBEEEEEEEEEEEEEEEEEEEEF // hexadecimal
1 << 100

Below are integers and floating point values, of which the syntax of the literal determines the type:

1.234e5 // Floating point
1e2 // Floating point
3.2i // Floating-point imaginary
100 // The integer

constant expression

Floating point and integer constants can be arbitrarily combined, and the type of the final expression is determined by the type of the constant. The operation itself also depends on the type.


2*3.14 // Floating point : 6.28
3./2 // Floating point: 1.5
3/2 // Integer: 1
3+2i // Plural: 3.0 + 2.0i // High precision
const Ln2 = 0.69314718055994530941723212145817656807
const Log2E = 1/Ln2

The range of values is large enough (the current maximum is 1024 bits).

ideal number results in

The Go language allows constants to be used without explicit transitions, provided that the values can be represented by their type (no transition is necessary; The value is ok) :


var million int = 1e6 //float The syntax can be used here
math.Sin(1)

A constant must be represented by its class. For example, ^0 has a value of -1, not in the range 0-255.

23
0x0FF
4

viii. Declaration

The golang declaration begins with a keyword (var, const, type, func) and is in the reverse order of the declaration in C:


23
0x0FF
5
Why declare in reverse order? An early example:

23
0x0FF
6
p and q are of type *int. And the function reads better and is consistent with other declarations. There's another reason. Come on.

Var

The variable declaration begins with var.

They can have a type or an initialization expression; There should be at least one or both. The initialization expression should match the variable (and the type!). .


23
0x0FF
7

dispatches var

Typing var all the time is annoying. We can declare multiple variables as a group with parentheses:


23
0x0FF
8
This form is suitable for const,type, var, but not for func.

=:" short statement "

Within a function (only if it is within a function), the following form is declared:


23
0x0FF
9
Can be shortened to:

v := value

(this is another reason for the reverse order of name and type)

A type is the type of a value (for an ideal number, the corresponding type is int or float64 or complex128)


a, b, c, d, e := 1, 2.0, "three", FOUR, 5e0i

This form of declaration is used frequently and can also be used in loop initialization expressions such as for.

Const

Constant declarations begin with const.

They must have a constant expression that can be evaluated at compile time and, as an initialization expression, an optional type modifier.


const Pi = 22./7.
const AccuratePi float64 = 355./113
const beef, two, parsnip = "meat", 2, "veg"
const (
Monday, Tuesday, Wednesday = 1, 2, 3
Thursday, Friday, Saturday = 4, 5, 6
)

Iota

Constant declarations can use counters: iota, iota in each const block counts from 0, incrementing itself on each implicit semicolon (end of line).


const (
Monday = iota // 0
Tuesday = iota // 1
)

Shorthand: repeat the previous type and expression.

const (
loc0, bit0 uint32 = iota, 1<<iota //0 . 1
loc1, bit1 //1 . 2
loc2, bit2 //2 . 4
)

Type

The type declaration begins with type.

We'll look at more types later, but here are a few examples:


type Point struct {
x, y, z float64
name
string
}
type Operator func(a, b int) int
type SliceOfIntPointers []*int

We'll come back to functions later.

New

The built-in function new allocates memory. The syntax is similar to a function call, with type as an argument, similar to new in C++. Returns a pointer to the allocated object.


var p *Point = new(Point)
v := new(int) // v The type of *int

Later we will see how to build slices (slice)

There is no delete or free for memory release in Go. Go has a garbage collection feature.

assigns

Assignments are easy and familiar:


a = b

But Go also supports a number of assignments:

x, y, z = f1(), f2(), f3()
a, b = b, a // interaction a,b The value of the

The function supports multiple return values (more on that later) :

nbytes, error := Write(buf)

9. Control structure

Similar to C, but different in many places.

Go supports if, for, and switch.

As I said before, you don't need braces, but braces are necessary.

If you look at them as a group, they are used regularly. For example, if, for, and switch all support initialization statements.

Control structure in the form of

There will be details later, but overall:

The if and switch statements are presented as 1 and 2 elements, which are explained in more detail later.

The for loop has the form of 1 and 3 elements:

The 1-element form is equivalent to while:

in the C language


for a {}

The 3 element form is equivalent to for:

in the C language


var a int
var b, c *int // Pay attention to and C The different
var d []int
type S struct { a, b int }
1

In all of these forms, any element can be empty.

if

The basic form is well known, but there is no "else suspension "problem:


var a int
var b, c *int // Pay attention to and C The different
var d []int
type S struct { a, b int }
2

Supports initialization statements; You need a semicolon.


var a int
var b, c *int // Pay attention to and C The different
var d []int
type S struct { a, b int }
3

More beneficial to use with multivariate functions:


var a int
var b, c *int // Pay attention to and C The different
var d []int
type S struct { a, b int }
4

The ellipsis condition means true, which is of little use here. But it is especially useful in for, switch statements.

for

The basic form is known as


var a int
var b, c *int // Pay attention to and C The different
var d []int
type S struct { a, b int }
5

The omission condition means true:


var a int
var b, c *int // Pay attention to and C The different
var d []int
type S struct { a, b int }
6

And you can omit the semicolon:


var a int
var b, c *int // Pay attention to and C The different
var d []int
type S struct { a, b int }
7

Don't forget multiple assignments:


for i,j := 0,N; i < j; i,j = i+1,j-1 { ... }

There is no comma operator in Go as there is in C

switch details

switch is somewhat similar to switch in C.

However, there are some important differences in syntax and semantics:

- expressions do not have to be constant, or even int.
- there is no automatic fall through
- but instead, syntactically, the final statement can be fallthrough
- multiple case can be separated by a comma


switch count%7 {
case 4,5,6: error()
case 3: a *= v; fallthrough
case 2: a *= v; fallthrough
case 1: a *= v; fallthrough
case 0: return a*v
}

Switch

switch in Go is far more powerful than C. Common form:


switch a {
case 0: fmt.Printf("0")
default: fmt.Printf("non-zero")
}

The switch expression can be of any type; if it is null, true is indicated. The result is similar to an if-else chain:


a, b := x[i], y[j]
switch {
case a < b: return -1
case a == b: return 0
case a > b: return 1
}

Or


if a == b { return true } else { return false }
for i = 0; i < 10; i++ { ... }
2

Break, continue and

The break and continue statements work similarly to those in C.

They can specify an label and affect the outer structure:


Loop: for i := 0; i < 10; i++ {
switch f(i) {
case 0, 1, 2: break Loop
}
g(i)
}

Yes, that's an goto.

x, function

The function begins with the func keyword.

If there is a return type, the return type is placed after the parameter. return means exactly what you would expect.


func square(f float64) float64 { return f*f }

Functions can return multiple values. Thus, the return type is a bracketed list.

func MySqrt(f float64) (float64, bool) {
if f >= 0 { return math.Sqrt(f), true }
return 0, false
}

empty identifier

What if you only care about the first value returned by the MySqrt function? You still need to put the second value in one place.

Solution: use an empty identifier _(underscore). It is pre-declared and can be assigned any useless value.


// Don't care about boolean from MySqrt.
val, _ = MySqrt(foo())

In other USES of the empty identifier, we will still display it.

function

with the result variable (result variable)

If you name the result parameter, you can use it as an actual variable.


func MySqrt(f float64) (v float64, ok bool) {
if f >= 0 { v,ok = math.Sqrt(f), true }
else { v,ok = 0,false }
return v,ok
}

The resulting variable is initialized to "0"(0, 0.0,false, etc.). According to its type; More on that later)


func MySqrt(f float64) (v float64, ok bool) {
if f >= 0 { v,ok = math.Sqrt(f), true }
return v,ok
}

null returns

Finally, an return that does not return an expression returns the current value of the result variable. Here are two other versions of MySqrt:


func MySqrt(f float64) (v float64, ok bool) {
if f >= 0 { v,ok = math.Sqrt(f), true }
return // must be explicit
}
func MySqrt(f float64) (v float64, ok bool) {
if f < 0 { return } // error case
return math.Sqrt(f),true
}

What is 0

The memory in Go is initialized. All variables are initialized when the previous declaration is executed. If there is no explicit initialization expression, we will use the "0 value "of the corresponding type. The following loop:


for i := 0; i < 5; i++ {
var v int
fmt.Printf("%d ", v)
v = 5
}

I'm going to print 0, 0, 0, 0, 0.

The value of 0 depends on the type: the value is 0; Boolean is false; The empty string is ""; Pointer, map, slice, channel is nil; The structure is 0 and so on.

Defer

The defer statement is responsible for executing a function (or method) when its function returns. The parameter is evaluated at the moment it reaches the defer statement; Its function is executed on return.


package main const three = 3
var i int = three func main() { fmt.Printf("%d\n", i) }
1

Useful in closing file descriptors, unlocking mutex, and so on.

One function

is executed per Defer

Go performs a set of defer functions in last in first out (LIFO) order.


package main const three = 3
var i int = three func main() { fmt.Printf("%d\n", i) }
2

The above code will output 4, 3, 2, 1, 0. You can close all file descriptors and unlock all mutexes at the end.

Trace code with defer:


package main const three = 3
var i int = three func main() { fmt.Printf("%d\n", i) }
3

But we can do it a little bit more subtly.

The parameter is evaluated immediately, defer executes
later


func trace(s string) string {

fmt.Println("entering:", s)
return s
}
func un(s string) {
fmt.Println("leaving:", s)
}
func a() {
defer un(trace("a"))
fmt.Println("in a")
}
func b() {
defer un(trace("b"))
fmt.Println("in b")
a()
}
func main() { b() }

letter number par value

As in C, functions cannot be declared inside functions. But a literal numeric value can be assigned to a variable.


func f() {
for i := 0; i < 10; i++ {
g := func(i int) { fmt.Printf("%d",i) }
g(i)
}
}

The numeric value of the letter is the closure (closure)

A function numeric value is actually a closure.


package main const three = 3
var i int = three func main() { fmt.Printf("%d\n", i) }
6
Output 1 21 321 and add x to f.


Related articles: