Go language quick start notes 01

Keywords: Go

Language characteristics

  1. Simple deployment:

    1. It can be directly compiled into machine code for execution
    2. Do not rely on other libraries
    3. Run directly to deploy
  2. Statically typed languages: hidden problems can be detected at compile time
  3. Concurrency at the language level: it naturally supports concurrency and makes full use of multi-core
  4. Powerful standard library:

    1. runtime system scheduling mechanism
    2. Efficient GC garbage collection
    3. Rich standard library
  5. Easy to learn: 25 keywords, support embedded C syntax, object-oriented and cross platform

configuration setup

Mac download address: https://dl.google.com/go/go1....

Installation path: / usr/local/go

Configure environment variables:

vi ~/.bash_profile

export GOPATH=$HOME/go

source ~/.bash_profile

common problem

1.go.mod file not found in current directory or any parent directory

Solution: go env -w GO111MODULE=auto

Grammatical attention

  1. Semicolons are not recommended at the end of expressions
  2. Import multiple packages

    import (
        "fmt"
        "time"
    )
  3. Curly braces for a function must go with the function name

vim hello.go

package main

import "fmt"
func main() {
    fmt.Println("Hello Go!")
}

Compile and execute

go run hello.go

compile

go build hello.go

implement

./hello

Variable var

  1. Declare a variable (default is 0)

    var a int
  2. Declare a variable and initialize a value

    var b int = 100
  3. The type is omitted during initialization, and the data type is automatically matched through the value (not recommended)

    var c = 100
    var cc = "abcd"
    
    fmt.Printf("cc=%s,cc=%T",cc,cc)//cc=abcd,cc=string
  4. Omit the var keyword and automatically match (common)

    e := 100
    f := "abcd"

Note: Method 1.2.3 can declare global variables outside the function; 4 local variables can only be declared in function bodies

  1. Declare multiline variables

    var xx, yy int = 100, 200
    var mm, nn = 100, "abc"
    
    var (
        cc int = 100
        dd bool = true
    )
    fmt.Println("cc=",cc,"dd=",dd)

Constant const

Constants are not allowed to be modified

const a int = 100
const (
    BEIJING = 1
    SHANGHAI = 2
)

iota: used in conjunction with const. Each line is accumulated. The first line defaults to 0

const (
    BEIJING = 10 * iota //0
    SHANGHAI                         //10
    SHENZHEN                         //20
)
const (
        a, b = iota+1,iota+2//iota=0, a=1, b=2
    c, d                                //iota=1, c=1, d=3
    g, h = iota*2,iota*3//iota=3, g=6, h=9
)

function

Basic function form

func test(a string, b int) int {
        return 100
}

Multiple return values

//anonymous
func test(a string, b int) (int, int) {
        return 666, 777
}
//There is a formal parameter name (initialization defaults to 0)
func test(a string, b int) (r1 int, r2 int) {
        r1 = 1000
        r2 = 2000
        return
}

import and init

hello.go

package main
import (
    "GoStudy/lib1"
    "GoStudy/lib2"
)
func main() {
    lib1.Lib1Test();  //Function names called externally must be capitalized
    lib2.Lib2Test();    
}
//Output results
//lib1.init()...
//lib2.init()...
//Lib1Test()...
//Lib2Test()...

lib1/lib1.go

package lib1
import "fmt"
func Lib1Test()  {
    fmt.Println("Lib1Test()...")
}
func init()  {
    fmt.Println("lib1.init()...")
}

lib2/lib2.go

package lib2
import "fmt"
func Lib2Test()  {
    fmt.Println("Lib2Test()...")
}
func init()  {
    fmt.Println("lib2.init()...")
}

be careful:

  1. Import an anonymous package (do not execute the functions in the package, but execute the init method)

    import _ "GoStudy/lib2"
  2. Import package alias

    import l2 "GoStudy/lib2"
    func main() {
        l2.Lib2Test();    
    }
  3. Import into the current package (function can be called directly)

    import . "GoStudy/lib2"
    func main() { 
        Lib2Test();    
    }

Pointer*

package main
import "fmt"
func changeValue(p *int)  {
   *p = 10;
}
func main() { 
    var a = 1
    changeValue(&a)
    //p = &a
    //*p = 10
    fmt.Println("a =",a) //a = 10
}

defer

The mechanism to execute before the end of the function (first in, then out, after the return method)

package main
import "fmt"
func func1()  {
    fmt.Println("func1()...")
}
func func2()  {
    fmt.Println("func2()...")
}
func func3()  {
    fmt.Println("func3()...")
}
func returnAndDefer() int {
    defer func1()
    defer func2()
    defer func3()
    return returnFunc()
}
func returnFunc() int {
    fmt.Println("returnFunc()...")
    return 0
}
func main() { 
    returnAndDefer()
}
//Execution sequence:
returnFunc()...
func3()...
func2()...
func1()...

Array and dynamic array

Fixed length array
package main
import "fmt"
func test(arr []int)  {
    arr[0] = 111
}
func main() { 
    //Fixed length array
    var myArr []int
    //Array traversal
    test(myArr)//myArr[0] unchanged
    for k, v := range myArr2 {
        fmt.Println("index=",k,"value=",v)
    }
}
Dynamic array (slice)

Dynamic array is passed by reference. In fact, what is passed is an array pointer pointing to the same block of memory

Dynamic array parameters of different lengths are the same

package main
import "fmt"
func test(arr []int)  {
    arr[0] = 111
}
func main() { 
    //Fixed length array
    myArr := []int{1,2,3,4}
    //Array traversal
    test(myArr)//myArr[0] unchanged
    for k, v := range myArr {
        fmt.Println("index=",k,"value=",v)
    }
}
//Output results
index= 0 value= 111
index= 1 value= 2
index= 2 value= 3
index= 3 value= 4

Note:_ Represents an anonymous variable

Declaration of slices
  1. Declare slice1 as a slice and initialize it. The default value is 1,2,3 and the length len is 3

    slice1 := []int{1, 2, 3}
  2. Declare slice2 as a slice, but no space is allocated. make is required to allocate space (the initialization value is 0)

    var slice2 = []int
    slice2 = make([]int, 3)
  3. Declare slice3 as a slice and allocate space through make (the initialization value is 0)

    var slice3 []int = make([]int, 3)
  4. Declare slice4 as a slice and allocate space through make (the initialization value is 0). Deduce slice4 as a slice through: = (common)

    slice4 := make([]int, 3)
Addition of slices

len: length, indicating the distance from the left pointer to the right pointer

cap: capacity, indicating the distance from the left pointer to the end of the underlying array

Capacity expansion mechanism of slice: when append, if the length increases and exceeds the capacity, the capacity will be doubled (5 - > 10 - > 20)

var numbers = make([]int, 3, 5)//Length 3, capacity 5
fmt.Printf("len=%d,cap=%d,slice=%v",len(numbers),cap(numbers),numbers)
//len=3,cap=5,slice=[0 0 0]

Append an element 1 to numbers

numbers = append(numbers, 1)
fmt.Printf("len=%d,cap=%d,slice=%v",len(numbers),cap(numbers),numbers)
//len=4,cap=5,slice=[0 0 0 1]

Append an element 2 to numbers

numbers = append(numbers, 2)
fmt.Printf("len=%d,cap=%d,slice=%v",len(numbers),cap(numbers),numbers)
//len=5,cap=5,slice=[0 0 0 1 2]

Append element to slice with full capacity

numbers = append(numbers, 3)
fmt.Printf("len=%d,cap=%d,slice=%v",len(numbers),cap(numbers),numbers)
//len=6,cap=10,slice=[0 0 0 1 2 3]
Slice interception
s := []int{1,2,3}
s1 := s[0:2]
s2 := make([]int, 3)
copy(s2, s)//copy the values in s to s2
s1[0] = 100
fmt.Println(s)//[100 2 3]
fmt.Println(s1)//[100 2]
fmt.Println(s2)//[1 2 3]

map

Declaration method
  1. Mode 1:

    1. Declare that myMap1 is a map type, key is string and value is string
    2. Before using a map, you need to allocate data space to the map with make
    var myMap1 map[string]string
    myMap1 = make(map[string]string, 10)
    myMap1["a"] = "aaa"
    myMap1["b"] = "bbb"
  2. Mode 2:

    myMap2 := make(map[int]string)
    myMap2[0] = "a"
    myMap2[1] = "b"
    fmt.Println(myMap2) //map[0:a 1:b]
  3. Mode III

    myMap3 := map[int]string {
        0 : "a",
        1 : "b",
    }
    fmt.Println(myMap3) //map[0:a 1:b]
Mode of use

map is also passed by reference. When making parameters, the pointer address is passed

  1. add to

    myMap2 := make(map[int]string)
    myMap2[0] = "a"
    myMap2[1] = "b"
  2. ergodic

    for k, v := range myMap2 {
        fmt.Printf("k=%d,v=%s\n",k,v)
    }
  3. delete

    delete(myMap2, 0)
  4. modify

    myMap2[0] = "c"

object-oriented

structural morphology

  1. definition

    type Book struct {
        title string //Class's property is capitalized to indicate public, otherwise it is private
        auth string
    }
  2. use

    var book1 Book
    book1.title = "Golang"
    book1.auth = "Tom"
    fmt.Println(book1)//{Golang Tom}
    
    book2 := Book{title:"aaa",auth:"bbb"}
    fmt.Println(book2)//{aaa bbb}
    
    book3 := Book{"aaa","bbb"}
    fmt.Println(book3)//{aaa bbb}
  3. Pass (copy passed)

    func changeBook(book Book)  {
        book.title="XXX"
    }
    func main() { 
        var book1 Book
        book1.title = "Golang"
        book1.auth = "Tom"
        changeBook(book1)
        fmt.Println(book1)//{Golang Tom}
    }

class

Encapsulation: class name, property name and method name are capitalized to indicate external access

this is a copy of the object that called the method

func (this *Book) setName(title string)  {
    this.title=title
}
func (this Book) setAuth(auth string)  {
    this.auth=auth
}
func main() { 
    book := Book{title:"aaa",auth:"bbb"}
    book.setName("ccc")
    book.setAuth("ddd")
    fmt.Println(book)//{ccc bbb} 
}
inherit
package main
import "fmt"
type Human struct {
    name string
    sex string
}
type SuperMan struct {
    Human
    level int
}
func (this *Human) Eat()  {
    fmt.Println("Human Eat...")
}
func (this *Human) Walk()  {
    fmt.Println("Human Walk...")
}
func (this *SuperMan) Walk()  {
    fmt.Println("SuperMan Walk...")
}
func (this *SuperMan) Fly()  {
    fmt.Println("SuperMan Fly...")
}
func main() { 
    tom := Human{"aaa","bbb"}
    tom.Eat() //Human Eat...
    tom.Walk()//Human Walk...
    //s :=SuperMan{Human{"ccc","ddd"},100}
    var s SuperMan
    s.name = "Sss"
    s.sex = "man"
    s.level= 88
    s.Walk()//SuperMan Walk...
    s.Fly()//SuperMan Fly...
}
polymorphic

interface is essentially a pointer to the parent class

Basic elements:

  1. There is a parent class (Interface)
  2. A subclass implements all the interface methods of the parent class
  3. The variable (pointer) of the parent type points to (references) the specific data variable of the child class
package main
import "fmt"
type AnimalIF interface {
    Sleep()
    GetColor() string
}
type Cat struct {
    color string
}
func (this *Cat) Sleep()  {
    fmt.Println("Cat Sleep...")
}
func (this *Cat) GetColor() string {
    return this.color
}
type Dog struct {
    color string
}
func (this *Dog) Sleep()  {
    fmt.Println("Dog Sleep...")
}
func (this *Dog) GetColor() string {
    return this.color
}
func showAnimal(animal AnimalIF)  {
    animal.Sleep()
    fmt.Println("color=",animal.GetColor())
}
func main() { 
    var animal AnimalIF//Data type of interface: parent class pointer
    animal = &Cat{"White"}
    animal.Sleep()//Cat Sleep...
    fmt.Println("color=",animal.GetColor())//color= White

    dog := Dog{"Yellow"}
    showAnimal(&dog)
    //Dog Sleep...
    //color= Yellow
}
Universal data type interface {} (empty interface)

interface {} type assertion mechanism: arg.(string)

package main
import "fmt"

type Book struct {
    tile string
}
func test(arg interface{}){
    fmt.Println(arg)
    //Assert
    _, ok := arg.(string)
    if !ok {
        fmt.Println("arg is not string")
    }else{
        fmt.Println("arg is string")
    }
}
func main() { 
    book := Book{"Golang"}
    test(book)//{Golang}
    test(123)//123
    test("hello")//hello
}
Variable type
  1. Variable pair

    1. type

      1. static type: int/string
      2. concrete type: the specific data type referred to by interaction (the type visible to the system runtime)
    2. value
package main
import "fmt"
type Reader interface {
    ReadBook()
}
type Writer interface {
    WriteBook()
}
type Book struct {

}
func (this *Book) ReadBook() {
    fmt.Println("Read a book.")
}
func (this *Book) WriteBook() {
    fmt.Println("Write a book.")
}
func main() { 
    b := &Book{}//b: Pair < type: book, value: Book {} address >
    var r Reader//r: Pair < type: empty, value: empty >
    r = b       //r: Pair < type: book, value: Book {} address >
    r.ReadBook()
    var w Writer  
    w = r.(Writer)//w: Pair < type: book, value: Book {} address >
    //There are two steps to assert: get the dynamic type type and judge whether the type implements the target interface.
    //The assertion here succeeds because the type is book, and Book implements the Writer interface
    w.WriteBook()
}

Reflection

Example 1:

package main
import (
    "fmt"
    "reflect"
)
func reflectNum(arg interface{}){
    fmt.Println("type:", reflect.TypeOf(arg))
    fmt.Println("value:", reflect.ValueOf(arg))
}
func main() { 
    var num float64 = 1.34556
    reflectNum(num)
    //type: float64
    //value: 1.34556
}

Example 2:

package main
import (
    "fmt"
    "reflect"
)
type User struct {
    Id int
    Name string
    Age int
}
func (this User) Call(){
    fmt.Printf("User: %v", this)
}
func DoFieldAndMethod(input interface{}){
    inputType := reflect.TypeOf(input)
    inputValue := reflect.ValueOf(input)
    //traversal attributes 
    for i := 0; i < inputType.NumField(); i++ {
        field := inputType.Field(i)
        value := inputValue.Field(i).Interface()
        fmt.Printf("%s:%v = %v\n",field.Name, field.Type, value)
    }
    //Id:int
    //Name:string = Lilei
    //Age:int = 18
    //Traversal method (note that the structure method of pointer type cannot be printed)
    for i := 0; i < inputType.NumMethod(); i++ {
        inputMethod := inputType.Method(i)
        fmt.Printf("%s:%v\n",inputMethod.Name, inputMethod.Type)
    }
    //Call:func(main.User)
}
func main() { 
    user := User{1, "Lilei", 18}
    DoFieldAndMethod(user)
}

Structure tagtag

package main
import (
    "fmt"
    "reflect"
)
type User struct {
    Name string `info:"name" doc:"full name"`
    Age int `info:"age" doc:"Age"`
}
func findTag(input interface{}){
    inputType := reflect.TypeOf(input).Elem()
    //traversal attributes 
    for i := 0; i < inputType.NumField(); i++ {
        taginfo := inputType.Field(i).Tag.Get("info")
        tagdoc := inputType.Field(i).Tag.Get("doc")
        fmt.Printf("info:%s doc:%s\n",taginfo, tagdoc)
    }
}
func main() { 
    var u User
    findTag(&u)
    //info:name doc: name
    //info:age doc: age
}

Application of structure tag in json

package main
import (
    "fmt"
    "encoding/json"
)
type User struct {
    Name string `json:"name"`
    Age int `json:"age"`
    Hobby []string `json:"hobby"`
}
func main() { 
    user := User{"lilei", 18, []string{"dance","football"}}
    //json encoding
    jsonStr, err := json.Marshal(user)
    if err != nil {
        fmt.Println("Json marshal error.")
        return
    }
    fmt.Printf("json = %s",jsonStr)//json = {"name":"lilei","age":18,"hobby":["dance","football"]}
    //json decoding
    user1 := User{}
    err = json.Unmarshal(jsonStr, &user1)
    if err != nil {
        fmt.Println("Json unmarshal error.")
        return
    }
    fmt.Println(user1)//{lilei 18 [dance football]}
}

Posted by Snake PHP on Sun, 28 Nov 2021 10:55:45 -0800