Go Learning Notes (2) Start in Ten Minutes

Add Golang Learning QQ Group to Learn Progress, Start a Family and Start a Business Job ^-^ Group Number: 96933959

Variable-Constant

variable

Variable names consist of letters, numbers and underscores, and cannot begin with numbers.

...
var (
    A int    //Default is 0
    B string //Default is""
    C bool   //Default is false

    Name string = "suoning"
    Age         = 18 // Automatic recognition of types
)

func main() {
    sex := "man"          //Equivalent to var sex string = "man"
    var girlfriend string //Declare variables
    girlfriend = "Dawn"   //Variable assignment

    Name := "Nick" //Correct
    //girlfriend := "Jenny"    //FALSE! Can't declare twice
    ...
}

 

constant

Constants are modified with const, which means they are always read-only and cannot be modified.

Data types in constants can only be Boolean, numeric (integer, floating-point and complex) and string types.

Syntax: const identifier [type] = value, where type can be omitted.

iota

iota, a special constant, can be considered a constant that can be modified by the compiler.

When each const keyword appears, it is reset to 0, and before the next const appears, the number represented by iota increases automatically by 1 for each occurrence.

...
const (
    A = 'a'    //97
    B = iota   //1
    C          //2
    D = "nick" //"nick"  iota += 1
    E          //"nick"  iota += 1
    F = 618    //618  iota +=1
    G          //618  iota +=1
    H = iota   //7
    I          //8
)
...

 

Basic data types

Boolean type

Boolean values can only be constant true or false.

var a bool
var a bool = true
var a = false

 

Number type

int:

  • uint8 (unsigned 8-bit integers (0-255))
  • uint16 (unsigned 16-bit integers (0-65535))
  • uint32 (unsigned 32-bit integer (0 to 429467295)
  • uint64 (unsigned 64-bit integer (0 to 18446744073709551615))
  • int8 (signed 8-bit integers (-128 to 127))
  • int16 (signed 16-bit integers (-32768 to 32767))
  • int32 (signed 32-bit integers (-2147483648 to 2147483647))
  • int64 (signed 64-bit integer (-9223372036854775808 to 9223372036854775807))

float:

  • float32 (IEEE-754 32-bit floating-point number)
  • float64 (IEEE-754 64-bit floating-point number)
  • complex64 (32-bit real and imaginary)
  • complex128 (64-bit real and imaginary)

Other:

  • byte (similar to uint 8)
  • rune (similar to int32)
  • uint (32 or 64 bits)
  • int (the same size as uint)
  • uintptr (unsigned integer for storing a pointer)

Type Conversion

package main

func main() {
    var a int
    var b int32
    var c int64
    a = 15
    //b = a + a // compiler error
    b = int32(a + a) // ok
    b = b + 5 // ok: 5 is a constant
    c = c + 5 // ok
}

 

Character type

Stored as ascii code

var a byte = 'a'
fmt.Println(a)    //97

 

String type

Strings are represented in two ways:

  1. Double quotation marks
  2. `` (Antiquotation marks, not escape)

The bottom of string is an array of byte s

String itself is immutable, so to change the characters in string, the following operations are needed:

str := "hello world"
s := []byte(str)
s[0] = 'o'
str = string(s)

 

Operator

Arithmetic operator

  • + Addition
  • - Subtraction
  • * Multiplication
  • / Division
  • % Remainder
  • ++ self-increasing
  • - Self-reduction

 

Relational operator

  • == Check if the two values are equal and return True if they are equal or False if they are not.
  • != Check if the two values are not equal, return True if they are not equal or False if they are not.
  • > Check whether the left margin is larger than the right margin and return False if True is returned.
  • <Check if the left value is less than the right value and return False if True is returned.
  • >= Check whether the left margin is greater than or equal to the right margin and return False if True is returned.
  • <= Check if the left margin is less than or equal to the right margin, or if True is returned, False is returned.

 

Logical Operator

  • && Logical AND operator. If both operands are True, then condition True, otherwise False.
  • || Logical OR operator. If the operands on both sides have a True, then condition True, otherwise False.
  • Logical NOT operator. If the condition is True, the logical NOT condition is False, otherwise it is True.

 

Bitwise Operators

Bit operators operate on the binary bits of integers in memory.

  • & Bit-by-bit and operator "&" are binary operators. Its function is to participate in the operation of the two corresponding binary phase sum.
  • | The bitwise OR operator "|" is a binary operator. Its function is to participate in the operation of the two corresponding binary phases or.
  • ^ The bitwise exclusive or operator "^" is a binary operator. Its function is that the corresponding binary bits of the two numbers involved in the operation are different or when the corresponding binary bits are different, the result is 1.
  • The left shift operator "<" is a binocular operator. A left shift of N bits is multiplied by the n th power of 2. Its function is to move all the binary bits of the arithmetic number on the left side of "<" to a number of bits. The number on the right side of "<" specifies the number of bits to move. The high bits are discarded and the low bits are complemented by 0.
  • The right shift operator ">" is a binocular operator. To move n bit to the right is to divide it by the n th power of 2. Its function is to move all the binary bits of the arithmetic number on the left side of ">" to the right, and the number on the right side of ">" specifies the number of moving bits.

 

Assignment operator

  • = A simple assignment operator assigns the value of an expression to a left value
  • += Add and assign (C+= A equals C = C + A)
  • -= Subtraction and assignment (C-= A equals C = C - A)
  • *= Multiplication and assignment (C*= A equals C = C* A)
  • /= Divide and assign (C/= A equals C = C/A)
  • %= Re-assignment after the remainder (C%= A equals C = C%-A)
  • <<= left-shifted assignment (C <= 2 equals C = C << 2)
  • "= Right-shifted assignment (C >>= 2 equals C = C >> 2)
  • &= Bit-by-bit and post-assignment (C &= 2 equals C = C & 2)
  • ^= Bit exclusive or post-assignment (C ^= 2 equals C = C ^ 2)
  • |= Bit-by-bit or post-assignment (C |= 2 equals C = C | 2)

 

Process Control

If/else & for & range

Note else if/else location

if condition1 {
} else if condition2 {
} else if condition3 {

} else {
}

for loop condition without parentheses

for i := 0; i < 10; i++ {
}

Dead cycle

for true {
}
It can be abbreviated as:
for {
}

range

for i, v := range str {
}
package main

import (
    "fmt"
)

func ran(str string) {
    for i, v := range str {
        fmt.Printf("index[%d] val[%c] len[%d]\n", i, v, len([]byte(string(v))))
    }
}

func main() {
    ran("Love, Suo Ning")
}


//Output results:
index[0] val[L] len[1]
index[1] val[o] len[1]
index[2] val[v] len[1]
index[3] val[e] len[1]
index[4] val[,] len[1]
index[5] val[ ] len[1]
index[6] val[Cable] len[3]
index[9] val[Ning] len[3]
range chestnuts

 

switch case

The default switch in Go is that each case has a break at the end of the match. When the match is successful, it will not automatically execute other cases downward, but jump out of the whole switch.

switch var {
case var1:
case var2:
case var3:
default:
}
func sw(num int) {
    switch num {
    case 1, 2, 3:
        fmt.Printf("%s in 1,2,3\n", num)
    case 4, 5, 6:
        fmt.Printf("%s in 4,5,6\n", num)
        fallthrough
    case 7, 8, 9:
        fmt.Printf("%s big 789\n", num)
    default:
        fmt.Printf("default...\n")
    }
}
switch chestnut
func sw2(num int) {
    switch {
    case num > 0 && num < 4:
        fmt.Printf("%s in 1,2,3\n", num)
    case num > 4 && num < 7:
        fmt.Printf("%s in 4,5,6\n", num)
        fallthrough
    case num > 7 && num < 10:
        fmt.Printf("%s big 789\n", num)
    default:
        fmt.Printf("default...\n")
    }
}
switch chestnut II
func sw3() {
    switch num := 5; {
    case num > 0 && num < 4:
        fmt.Printf("%s in 1,2,3\n", num)
    case num > 4 && num < 7:
        fmt.Printf("%s in 4,5,6\n", num)
        fallthrough
    case num > 7 && num < 10:
        fmt.Printf("%s big 789\n", num)
    default:
        fmt.Printf("default...\n")
    }
}
switch chestnut three

fallthrough

You can use fallthrough to enforce the following case code.  

package main

import "fmt"

func main() {

    switch {
    case false:
            fmt.Println("The integer was <= 4")
            fallthrough
    case true:
            fmt.Println("The integer was <= 5")
            fallthrough
    case false:
            fmt.Println("The integer was <= 6")
            fallthrough
    case true:
            fmt.Println("The integer was <= 7")
    case false:
            fmt.Println("The integer was <= 8")
            fallthrough
    default:
            fmt.Println("default case")
    }
}


//Operation results:

The integer was <= 5
The integer was <= 6
The integer was <= 7
fallthrough chestnuts

 

label & goto

The label is written at the beginning of the for loop, not at the end. Direct break exits to the specified location.

func lab() {
LABLE:
    for i := 0; i < 10; i++ {
        for true {
            i++
            if i == 6 {
                break LABLE
            }
            fmt.Println(i)
        }
    }
}

The goto statement can jump to a tag in this function

func got() {
    i := 0
HERE:
    fmt.Println(i)
    i++
    if i == 5 {
        return
    }
    goto HERE
}

 

select

select is similar to switch, but it has more limitations.

Each case statement must be a channel operation;

select {
case ch <- 0:
    //If 0 is written, the case
case <- ch:
    //If you read the data, do this case
default:
    //If none of the above is successful, enter default Handle
}
package main

import (
    "fmt"
    "time"
)

/*
The process of writing a zero or a one to ch randomly is, of course, a dead cycle.
*/

func main() {
    ch := make(chan int, 1)
    for {
        select {
        case ch <- 0:
        case ch <- 1:
        }
        i := <-ch
        fmt.Println(i)
        time.Sleep(time.Second)
    }
}
select chestnuts
package main

import (
    "fmt"
    "time"
)

/*
channel timeout handler
We haven't read data from ch, but we read data from timeout.
*/

func main() {
    ch := make(chan bool)
    timeout := make(chan bool, 1)

    go func() {
        time.Sleep(time.Second*2)
        timeout <- true
    }()

    select {
    case <- ch:
        fmt.Println("This is ch.")
    case <- timeout:
        fmt.Println("This is timeout.")
    }
}
select chestnut 2 (channel timeout)

 

function

The Go language has at least one main() function.

The function declaration tells the compiler the name of the function, the return type, and the parameters.

Overloading is not supported. A package cannot have two functions with the same name.

func function_name( [parameter list] ) [return_types] {
   Function Body
}

 

Name the name of the return value (return may not specify variables):

func add(a, b int) (c int) {
        c = a + b
        return

}
Chestnut
func calc(a, b int) (sum int, avg int) {
        sum = a + b
        avg = (a +b)/2
        return

}
Chestnut II

 

_ Identifier used to ignore the return value:

func calc(a, b int) (sum int, avg int) {
        sum = a + b
        avg = (a +b)/2
        return
}
func main() {
      sum, _ := calc(100, 200)
}
Chestnut

 

A function is also a type, and a function can be assigned to a variable.

package main

import "fmt"

//Declare a function type
type add_func func(int, int) int

func add(a, b int) int {
    return a + b
}

func operator(op add_func, a int, b int) int {
    return op(a, b)
}

func main() {
    c := add
    fmt.Println(c)    //0x1087050
    sum := operator(c, 1, 2)
    fmt.Println(sum)    //300
}

 

Variable parameters

Arg is a slice, we can access all parameters by arg[index] in turn, and judge the number of parameters passed by len(arg).

0 Number or more parameters
func add(arg...int) int {
}
1 Number or more parameters
func add(a int, arg...int) int {
}
2 Number or more parameters
func add(a int, b int, arg...int) int {
}
package main

import (
    "fmt"
)

//The return value is specified as sum Variable, default return This variable
func add(a int, b int, arg ...int) (sum int) {
    sum = a + b
    for i := 0; i < len(arg); i++ {
        sum += arg[i]
    }
    return
}

func concat(s string, arg ...string) string {
    str := s
    for i := 0; i < len(arg); i++ {
        str += arg[i]
    }
    return str
}

func main() {
    sum := add(1, 2, 3, 4, 5, 6, 7)
    fmt.Println(sum)    //28
    str := concat("nick", " ", "and", " ", "dawn", ".")
    fmt.Println(str)    //nick and dawn.
}
Multi-parameter chestnut

 

main & init & defer

main & init

init() method can appear in any package.
The main() method can only be used in package main.
The Go program automatically calls init() and main(), so you don't need to call these two functions anywhere.
The init function in each package is optional, but the package main must contain a main function.
The main() function cannot take parameters or define return values. The parameters passed in from the command line are saved in the os.Args variable. If you need to support command line switches, you can use the flag package.  
 

defer

  1. When the function returns, defer statement is executed.
  2. Several defer statements are executed in a first-in-last-out manner.
  3. Variables in defer statements that determine variables when defer is declared.
package main

import "fmt"

//statement defer When, variable i It's zero.
func test1()  {
    i := 0
    defer fmt.Println(i)
    i++
    return
}

//Stack, FIFO
func test2()  {
    for i := 0; i < 5; i++ {
        defer fmt.Printf("->%d", i)
    }
}

func main() {
    test1()
    test2()
}


//Output:
0
->4->3->2->1->0
defer chestnut
 

Scope

  1. Variables declared within a function are called local variables, and the life cycle is limited to the inside of the function.
  2. Variables declared outside a function are called global variables, and the lifecycle acts on the entire package, and if capitalized, on the entire program.
package main

import "fmt"

var name string

func main() {
    name = "Nick"
    fmt.Println(name)
    f1()
}
func f1() {
    name := "Dawn"
    fmt.Println(name)
    f2()
}
func f2() {
    fmt.Println(name)
}

//Output:
Nick
Dawn
Nick
Scope Chestnut

 

Anonymous function-closure

Anonymous function

Anonymous functions are composed of a function declaration and body without function name.

package main

func main()  {

    f := func(x, y int) int {
        return x + y
    }
    f(1,1)

    ch := make(chan int)
    func (ch chan int)  {
        ch <- 9
    }(ch)
}

 

closure

Closure is an entity composed of a function and its associated reference environment.

Functions can be stored in variables and passed as parameters to other functions, which can be dynamically created and returned by functions.

func Adder() func(int) int {
    var x int
    return func(d int) int {
        x += d
        return x
    }
}

f := Adder()
fmt.Println(f(1))    //1
fmt.Println(f(10))    //11
fmt.Println(f(100))    //111
package main

import (
    "fmt"
    "strings"
)

func makeSuffix(suffix string) func(string) string {
    return func(name string) string {
        if !strings.HasSuffix(name, suffix) {
            return name + suffix
        }
        return name
    }
}

func main() {
    f1 := makeSuffix(".png")
    fmt.Println(f1("name1"))    //name1.png
    fmt.Println(f1("name2"))    //name2.png

    f2 := makeSuffix(".jpg")
    fmt.Println(f2("name1"))    //name1.jpg
    fmt.Println(f2("name2"))    //name2.jpg
}
Closed chestnut II

 

Value Passing & Reference Passing

Whether it is a value transfer or a reference transfer, it is a copy of the variable that is passed to the function.

Value passing is a copy of the value, and reference passing is a copy of the address.

Generally speaking, address copy is more efficient. The value copy depends on the size of the object being copied. The larger the object, the lower the performance.

map, slice, chan, pointer, and interface are passed by default by reference.

new built-in functions are used to allocate memory, mainly to allocate value types, such as int, struct, and return pointers.

make built-in functions are used to allocate memory, mainly to allocate reference types, such as chan, map, slice.

 

Program initialization and execution process

Initialization and execution of programs start with the main package.
If the main package also imports other packages, they are imported sequentially at compile time.
Sometimes a package will be imported by multiple packages at the same time, so it will only be imported once (for example, many packages may use fmt packages, but it will only be imported once, because there is no need to import multiple packages).
When a package is imported, if it imports other packages, it imports other packages first, then initializes the package level constants and variables in these packages, and then executes init functions (if any), and so on.
When all imported packages are loaded, the package level constants and variables in the main package are initialized, then the init function in the main package (if it exists) is executed, and finally the main function is executed.
 

 

Pointer type (&*)

Common type, the variable store is the value, also known as the value type;

Pointer type, variable store is an address, this address store is the value.

Variables are placeholders that refer to computer memory addresses.

The addressing character of Go language is &, which returns the memory address of the corresponding variable before putting it into a variable.

Gets the value pointed to by the pointer type, using: *.

 

A pointer variable can point to the memory address of any value and it points to the memory address of that value.

Affirms the following:

var age *int // / pointing to integer
var height *float32 // / pointing to floating point type

When a pointer is defined and not assigned to any variable, its value is nil.

A nil pointer is also called a null pointer.

 

Chestnut

package main

import "fmt"

func main() {
    var ptr *int
    num := 100
    ptr = &num
    fmt.Println(ptr)    //0xc42000e1f8
    fmt.Println(*ptr)   //100
    *ptr = 200
    fmt.Println(num)    //200
}
package main

import "fmt"

func change(num *int) {
    fmt.Println(num)    //0xc42000e1f8
    fmt.Println(*num)   //100
    *num = 1000
    fmt.Println(num)    //0xc42000e1f8
    fmt.Println(*num)   //1000
}

func main() {
    num := 100
    fmt.Println(&num)    //0xc42000e1f8
    change(&num)
    fmt.Println(&num)    //0xc42000e1f8
    fmt.Println(num)     //1000
}

Keywords: Go less ascii

Added by biscutty on Fri, 14 Jun 2019 01:09:30 +0300