Go language [solid foundation]

createdtime 20211119

updatedtime 20211119

modifiedtime 20211119

author venki.chen

1. Integer
  1. Integer declaration
// Method 1: the default value is 0
var a int

// Method 2
var b int = 10

// Method 3 type push to
var c = 100

// Method 4 type push to
d := 100
// Declare multivariable
fmt.Println("Declare multivariable")
// Method 1
var aa, bb, cc int = 10, 100, 100
fmt.Printf("aa=%v,bb=%v,cc=%v\n", aa, bb, cc)

// Method 2
var dd, ee = 100, "venki.chen"
fmt.Printf("dd=%v,ee=%v\n", dd, ee)
  1. matters needing attention
  • View data type: fmt.Printf("%T\n", d).
  • The fourth declaration method can only be used in function bodies, not global variables.
2. Constant
  1. Constant definition
// Vertical enumeration
    // BEIJING_CODE region code enumeration - continuous
    BEIJING_CODE = iota // 0
    SHANGHAI_CODE		// 1
    TIANJING_CODE		// 2
// Horizontal enumeration
const (
	a, b = iota + 1, iota + 2 // iota = 0,a = iota + 1, b = iota + 2, a = 1, b = 2
	c, d                      // iota = 1,c = iota + 1, d = iota + 2, c = 2, d = 3
	e, f                      // iota = 2,e = iota + 1, f = iota + 2, e = 3, f = 4

	g, h = 2 * iota, 3 * iota // iota = 3,a = 2 * iota, b = 3 * iota, g = 6, h = 9
	i, j                      // iota = 4,i = 2 * iota, j = 3 * iota, i = 8, j = 12
)
  1. matters needing attention
  • Constant values are read-only and cannot be modified in the function body after definition.
  • The default value of iota is 0, which can only appear in const syntax and cannot be applied in function body.
3. Function
  1. Function multiple return values
// Function return value method 4 - return value with formal parameters - the return value type is the same and can be combined
func functionReturnLearn04(a int, b int) (r6, r7 int) {
	fmt.Println("a=", a)
	fmt.Println("b=", b)
	r6 = 10 // No colon
	r7 = 11 // No colon

	return
	// return r6, r7 / / this is OK. The default value is 0,0
}
// Function return value method 3 - return value with formal parameters
func functionReturnLearn03(a int, b int) (r4 int, r5 int) {
	fmt.Println("a=", a)
	fmt.Println("b=", b)
	r4 = 10 // No colon
	r5 = 11 // No colon

	return
}
// Function return value method 2 - anonymous return value
func functionReturnLearn02(a int, b int) (int, int) {
	fmt.Println("a=", a)
	fmt.Println("b=", b)
	c := 10
	d := 11

	return c, d
}
// Function return value mode 1
func functionReturnLearn01(a int, b int) int {
	fmt.Println("a=", a)
	fmt.Println("b=", b)
	c := 10

	return c
}
  1. matters needing attention
  • If the formal parameter is returned directly when the value is returned, even if the final formal parameter is not involved in the actual operation, it is OK. The result is the default value of the corresponding data type. For example, the integer is 0.
4. Package reference
  1. Function multiple return values
# Ignore package
_ fmt

# Alias package
base "20211115/base"
base.test()

# Ignore the package name and call the functions in the package directly
. "20211115/base"
base.test => test()
  1. matters needing attention
  • In the same package, the execution sequence is as follows: import > const > var > init() > main().
  • Methods and variables under the same package can be accessed regardless of case.
  • The method and variable names under the same package cannot have the same name, that is, the method cannot be redeclared; Except for variable names in code blocks.
5. Pointer
  1. Pointer quick pass
// Pointer practice - swap two numbers
func ptrLearn(p1 *int, p2 *int) {
	fmt.Println(p1)// Address value
	fmt.Println(p2)// Address value
	temp := *p1
	*p1 = *p2
	*p2 = temp
}
  1. matters needing attention
  • Pointer is actually an address. If you want to learn pointer well, you must first look at the knowledge related to the operating system.
6. defer
  1. Code practice
func AccessBase() {
	// deferLearn()
	deferAndReturn()
	// Result output
	// return func call!
    // defer func call!

}

func deferAndReturn() int {
	defer deferCall()
	return returnCall()
}

func deferCall() int {
	fmt.Println("defer func call!")
	return 0
}

func returnCall() int {
	fmt.Println("return func call!")
	return 0
}
  1. matters needing attention
  • defer is stored in the form of stack, first in and last out.
  • defer can appear more than one at the same time.
  • The execution sequence of defer and return. Return executes first and defer executes later. Remember that defer is called after the program ends.
7. Array
  1. Code practice
// Array declaration mode 1
var myArray01 [10]int // The default value is 0

// Array declaration mode 2
var myArray02 [4]int{0,1,2,3}
  1. matters needing attention
  • The array belongs to the value copy.
  • The data type breakdown of an array is related to the number of elements. For example, although [4]int and [10]int are arrays, they are different. They are visible when passed as formal parameters.
8. Slicing
  1. Code practice
// Declaration method
func sliceLearn() {
	// Declaration method 1 - and initialization. The default value is 1,2,3,4 and the length is 4
	slice01 := []int{1, 2, 3, 4}
	fmt.Println("Slice declaration method 01, slice01=", slice01)

	// Declaration method 2 - but no space is allocated to slice. If no space is allocated, an error will be reported
	var slice02 []int
	slice02 = make([]int, 3) // Open up 3 spaces, and the initialization value is 0
	fmt.Println("Slice declaration method 02, slice02=", slice02)

	// Declaration method 3 - allocate space to slice at the same time, and the initialization value is 0
	var slice03 []int = make([]int, 3)
	fmt.Println("Slice declaration method 03, slice03=", slice03)

	// Declaration method 4 - type derivation and allocation of space initialization value [declaration in this way shall be the standard or method 3 shall prevail]
	slice04 := make([]int, 3)
	fmt.Println("Slice declaration method 04, slice04=", slice04)
	
	// This declaration is also acceptable, but mode 3 shall prevail
	var slice0 = make([]int,3)
	fmt.Println(slice0)
}

// Mode of use
// How slices are used
	var slice05 []int = make([]int, 3, 5)
	slice05[0] = 1
	slice05[1] = 2
	slice05[2] = 3

	var slice06 []int = make([]int, 3, 5)

	copy(slice06, slice05)
// If the declared slice length is 3 and the capacity is 5, there will be no subscripts 3 and 4 during assignment, and an error will be reported. It can only be added.
var slice05 []int = make([]int, 3, 5)
	slice05[0] = 1
	slice05[1] = 2
	slice05[2] = 3
	slice05[3] = 4
	slice05[4] = 5

	fmt.Println(slice05)
// panic: runtime error: index out of range [3] with length 3

// Change it to the following line
var slice05 []int = make([]int, 3, 5)
	slice05[0] = 1
	slice05[1] = 2
	slice05[2] = 3
	slice05 = append(slice05,4)
	slice05 = append(slice05,5)

	fmt.Println(slice05)
  1. matters needing attention
  • The slice belongs to the value passed by reference.
  • Slicing can be simply understood as a dynamic array.
  • To judge whether slice is empty, you can judge whether slice is nil, for example, when it is only declared as make.
  • The slice can specify the capacity. When the capacity is full, if you continue to add elements to the slice, the go bottom layer will dynamically double the value of the initialization capacity again.
  • When a slice is intercepted and assigned to a new variable, the value is passed by reference. Change one value and the other will change with it. If you want to assign the intercepted slice to a new slice, you can use the copy function.
  • The cut interval of the slice is left closed and right open.
  • The address of the slice is the address of the first element.
9. map
  1. Code practice
// map declaration method
func mapLearn() {
	// Declaration method 1 - just declare that there is no allocated space
	var map01 map[string]string
	map01 = make(map[string]string, 10)
	map01["one"] = "venki"
	map01["two"] = "chen"
	fmt.Println("map Declaration method 01, map01=", map01)

	// Declaration method 02
	map02 := make(map[int]string)
	map02[0] = "poet"
	map02[1] = "chao"
	fmt.Println("map Declaration method 02, map02=", map02)

	// Declaration method 03
	map03 := map[int]string{
		0: "Chen",
		1: "writing",
		2: "Small",
		3: "exceed",
	}
	fmt.Println("map Declaration method 03, map03=", map03)
}
// map usage
// increase
	map04 := make(map[string]string)
	map04["chen"] = "Chen"
	map04["wen"] = "writing"
	map04["xiao"] = "Small"
	map04["chao"] = "exceed"
	fmt.Println("map Additional elements of usage, map04=", map04)
	// delete
	delete(map04, "chen")
	fmt.Println("map Delete elements using, map04=", map04)
	// modify
	map04["xiao"] = "large"
	fmt.Println("map Modification elements of usage mode, map04=", map04)
	// query
	i := 0
	for index, value := range map04 {
		i++
		fmt.Printf("map04 The first%d The index subscript of an element is%v,The corresponding value is%v\n", i, index, value)
	}
  1. matters needing attention
  • map only declares that if there is no make, there is no allocated space, that is, it cannot be used.
  • When the map is full, if you continue to add elements to the map, the go bottom layer will dynamically open up a value of twice the capacity again.
  • The values in the map are unordered, and the underlying map is stored through a hash table.
  • map is passed by reference.
10. struct
  1. Code practice
// Call entry
func structLearn() {
	h := Human{
		name: "Chen Wenxiao Chao",
		sex:  "male",
	}
	h.Eat()
	h.Walk()
    
    // Instantiation method 1
	var superman Superman
	superman.name = "venki.chen"
	superman.sex = "female"
	superman.level = 99
	superman.Eat()
	superman.Walk()
	superman.Fly()
	superman.Print()
	
	// Instantiation mode 2
	superman := Superman{Human{name:"venki.chen",sex:"female"},level:99}
}
// Binding methods for structures
type Human struct {
	name string
	sex  string
}

func (this *Human) Eat() {
	fmt.Println("human.eat()......")
}

func (this *Human) Walk() {
	fmt.Println("human.walk()......")
}
// Inherit the above parent class
type Superman struct {
	Human
	level int
}

func (this *Superman) Eat() {
	fmt.Println("superman eat()...")
}

func (this *Superman) Fly() {
	fmt.Println("superman fly()...")
}

func (this *Superman) Print() {
	fmt.Println("superman is name=", this.name)
	fmt.Println("superman is sex=", this.sex)
	fmt.Println("superman is level=", this.level)
}
  1. matters needing attention
  • struct is value passing. Of course, you can pass values through pointers instead of references.
  • When binding a method to a structure, it is generally passed by reference, otherwise it cannot be modified.
11. Polymorphism
  1. Code practice
type Animal interface {
	Sleep()
	GetColor() string
	GetType() string
}

type Cat struct {
	Color string
	Name  string
}

type Dog struct {
	Color string
	Name  string
}

func AccessBase() {
	fmt.Println("ok")
	// Polymorphic exercise
	cat := Cat{
		Color: "Green",
		Name:  "little cat",
	}

	PolymorphicLearn(&cat)
	fmt.Println("------------------")

	dog := Dog{
		Color: "white",
		Name:  "Little Didi",
	}
	PolymorphicLearn(&dog)
}

func PolymorphicLearn(animal Animal) {
	animal.Sleep()
	animal.GetColor()
	animal.GetType()
}

func (this *Cat) Sleep() {
	fmt.Println("cat is sleeping...")
}

func (this *Cat) GetColor() string {
	fmt.Println("cat's color is", this.Color)
	return this.Color
}

func (this *Cat) GetType() string {
	fmt.Println("cat's type is", this.Name)
	return this.Name
}

func (this *Dog) Sleep() {
	fmt.Println("dog is sleeping...")
}

func (this *Dog) GetColor() string {
	fmt.Println("dog's color is", this.Color)
	return this.Color
}

func (this *Dog) GetType() string {
	fmt.Println("dog's type is", this.Name)
	return this.Name
}
  1. matters needing attention
  • Basic elements of polymorphic implementation
    • There is a parent class (Interface).
    • There are subclasses (all interface methods that implement the parent class).
    • Variables of the parent type point to specific data variables such as.
12. interface
  1. Code practice
func InterfaceLearn(args interface{}) {
	fmt.Println("interfaceLearn is called...")
	// Type Asserts 
	value, ok := args.(string)
	if !ok {
		fmt.Println("args is not string type")

		fmt.Println("args is string type,value=", args)
	} else {
		fmt.Println("args is string type,value=", value)

		fmt.Printf("value type is %T\n", value)
	}
	fmt.Println("-----------------------------")
}
  1. matters needing attention
  • All data types implement empty interfaces.
  • An empty interface can be understood as a universal data type.
  • If the data type of the formal parameter cannot be determined, it can be implemented through an empty interface.
  • The go bottom layer provides a type assertion for the empty interface, which is used to judge what the specific data type of the empty interface implementation is.
13. Variables
  1. Code practice
var a int = 10 // a's pair:<type:int,value:10>

var b interface{}

b = a // b's pair:<type:int,value:10>
  1. matters needing attention
  • Declaring a variable can be divided into type and value. Type can be divided into static type (int string) and concrete type (the specific data type pointed to by the interface and the type visible to the system). type+value is called pair.
  • In the process of variable assignment and transfer, pair is unchanged, which is also the essence of type assertion.
14. reflect
  1. Code practice
func ReflectLearn(arg interface{}) {
	// Reflection exercises for simple data types
	/*fmt.Printf("arg's type is %v\n", reflect.TypeOf(arg))
	fmt.Printf("arg's value is %v\n", reflect.ValueOf(arg))*/

	// Reflection exercises for complex data types

	// Gets the type of arg
	argType := reflect.TypeOf(arg)
	fmt.Println("argType is :", argType.Name())

	// Get value of arg
	argValue := reflect.ValueOf(arg)
	fmt.Println("argValue is :", argValue)

	// Get the fields inside through argType
	// Get the field value through argValue
	// 1. Get the reflect.Type of the interface, get NumField through the type, and traverse
	// 2. Get the field and data type
	// 3. Get the corresponding field value through the Interface {} method of field
	for i := 0; i < argType.NumField(); i++ {
		field := argType.Field(i)
		value := argValue.Field(i).Interface()

		fmt.Printf("%s:%v = %v\n", field.Name, field.Type, value)
	}

	// Get the method inside by type
	for i := 0; i < argType.NumMethod(); i++ {
		m := argType.Method(i)
		fmt.Printf("%s:%v\n", m.Name, m.Type)
	}
}
  1. matters needing attention
  • When obtaining the method related data of the structure through reflection, remember not to use the pointer type (func (this *Cat) Sleep() {} use the latter func (this Cat) Sleep() {}) when binding the method to the corresponding structure, otherwise the structure method related information cannot be obtained.
15. Structure label
  1. Code practice
type person struct {
	Name string `info:"name" sub:"Author's name"`
	Age  int    `info:"age" sub:"Author age"`
}

// Structure label learning
func structLearn(s interface{}) {
	t := reflect.TypeOf(s)
	fmt.Println("--1--,t=", t) // --1--,t= *base.person
	e := t.Elem()
	fmt.Println("--2--,e=", e) // --2--,e= base.person

	for i := 0; i < e.NumField(); i++ {
		tagInfo := e.Field(i).Tag.Get("info")
		tagSub := e.Field(i).Tag.Get("sub")
		fmt.Println("--3--,tageInfo=", tagInfo, "--4--,tagSub=", tagSub)
		// --3--,tageInfo= name --4--,tagSub = author name
		// --3--,tageInfo= age --4--,tagSub = author age
	}
}
  1. matters needing attention
  • Tags are in the form of key value. One attribute can bind multiple tags.
  • Tags can be used to explain the usage of attributes or the specific usage of attributes when they are not referenced by different packages.
16. Structure and json
  1. Code practice
type person struct {
	Name    string   `info:"name" sub:"Author's name"`
	Age     int      `info:"age" sub:"Author age"`
	Address string   `json:"address"`
	Family  []string `json:"family"`
}

func AccessBase() {
	p := person{
		Name:    "Chen Wenxiao Chao",
		Age:     29,
		Address: "Shenzhen, Guangdong",
		Family:  []string{"Beijing", "Shanghai", "Guangzhou"},
	}
	structJson(p)
}

// json and struct
func structJson(p person) {
	// Structure to json
	jsonStr, err := json.Marshal(p)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("jsonStr=%v\n", string(jsonStr)) // jsonStr={"Name": "Chen Wen Xiaochao", "Age":29,"address": "Shenzhen, Guangdong", "family": ["Beijing", "Shanghai", "Guangzhou"]}
    
	// json to structure
	var pp person
	err = json.Unmarshal(jsonStr, &pp)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("pp=%v\n", pp) // pp = {Chen wenxiaochao 29 Shenzhen, Guangdong [Beijing, Shanghai, Guangzhou]}
}
  1. matters needing attention
  • Pay attention to adding a string when turning json.
17. goroutine
  1. Code practice
func goroutineLearn() {
	// Start a collaboration process through an anonymous function. Anonymous functions have return values, but the general return value receiving method is not allowed for a collaboration process.
	go func(a int, b int) bool {
		fmt.Println(a + b)
		return true
	}(10, 20)
    
	for true {
		time.Sleep(time.Second * 1)
	}
}
  1. matters needing attention
  • The process occupies 4GB of virtual memory (32bit OS).
  • Threads occupy memory, about 4MB.
  • User threads can be simply called coprocessors.
  • The coroutine and thread of go language have an M:N relationship.
  • go coroutine optimizes memory. A coroutine only occupies a few KB.
  • The design strategy of scheduler: reusing threads, using parallelism, preemption and global G queue.
  • Exit a coroutine runtime.Goexit()
18. channel
  1. Code practice
// channel learning without cache
func channelLearn() {
	chann := make(chan int)
	go func() {
		defer fmt.Println("go End of collaboration execution...")
		fmt.Println("go Collaborative process execution...")
		chann <- 666
	}()
	num := <-chann
	fmt.Println("num=", num)
	fmt.Println("End of main thread execution...")
}

// go collaboration in progress
// go collaboration execution ends
// num= 666
// End of main thread execution
// channel learning with cache
func channelCacheLearn() {
	chann := make(chan int, 3) // Specifying the pipe capacity means carrying the cache

	go func() {
		defer fmt.Println("go End of collaboration execution...")
		for i := 0; i < 3; i++ {
			chann <- i
			fmt.Println("The coordination process is being implemented...", "Write data is:", i, "The pipe length at this time is:", len(chann), "The pipe capacity is:", cap(chann))
		}
	}()
	time.Sleep(2 * time.Second)
	for i := 0; i < 3; i++ {
		num := <-chann
		fmt.Printf("The first%d individual num Yes:%v\n", i+1, num)
	}

	fmt.Println("End of main thread execution...")
}
// The collaboration is executing... The written data is: 0. At this time, the pipeline length is: 1 and the pipeline capacity is: 3
// The collaboration is executing... The written data is: 1. The pipeline length at this time is: 2. The pipeline capacity is: 3
// The collaboration is executing... The written data is: 2. The pipeline length at this time is: 3. The pipeline capacity is: 3
// go collaboration execution ends
// The first num is: 0
// The second num is: 1
// The third num is: 2
// End of main thread execution
  1. matters needing attention
  • channel ensures a sense of synchronization between the main thread and the coroutine.
  • close closes a channel.
  • You can use range to iterate over continuously operating channel s, because range will block.
  • Unlike the file meaning, the channel needs to be closed frequently. Only when you really don't have any sent data, or you want to explicitly end the range loop, can you close the channel.
  • After the channel is closed, data cannot be sent to the channel again (a panic error is caused, resulting in an immediate return of zero value).
  • After closing the channel, you can continue to receive data from the channel.
  • For nil channel, both sending and receiving will be blocked.
19. select
  1. Code practice
// select learning
func selectLearn() {
	chann1 := make(chan int)
	chann2 := make(chan int)

	go func() {
		for i := 0; i < 10; i++ {
			defer fmt.Printf("go End of collaboration execution%v\n...", i+1)
			fmt.Println(<-chann1)
		}
		chann2 <- 0
	}()
	x, y := 1, 1
	for {
		select {
		case chann1 <- x:
			x = y
			y = x + y
		case <-chann2:
			fmt.Println("go Collaboration end 2...")
			return
		}
	}
}
  1. matters needing attention

Tags: Go Back-end

Posted on Fri, 19 Nov 2021 05:53:28 -0500 by Spikey