start

Basic start point here


Structure judgment, etc


The judgment operation can be performed only when all field types of the structure support direct equalization.

Map, slice does not support direct equalization, so reflect.DeepEqual is used for comparison (map is a pointer (*hmap), slice is a pointer to SliceHeader Data field)

package main

import "fmt"

func main(a) {
	type data struct {
		x int
	}

	d1 := data{
		x: 100,
	}

	d2 := data{
		x: 100,
	}
	fmt.Println(d1 == d2)
}
Copy the code

The result is true

package main

import "fmt"

func main(a) {
	type data struct {
		x int
		y map[string]int // Dictionary type does not support ==,
	}

	d1 := data{
		x: 100,
	}

	d2 := data{
		x: 100,
	}
	fmt.Println(d1 == d2) //struct containing map[string]int cannot be compared
}
Copy the code

Struct map[string]int cannot be compared :invalid operation: d1 == d2 (struct map[string]int cannot be compared)


Empty structure


Empty struct{} is a structure type with no fields. Can be a channel element type for event notification.

package main

import (
	"fmt"
	"time"
)

func main(a) {
	exit := make(chan struct{})

	go func(a) {
		for {
			fmt.Println("hello, world!")
			exit <- struct{}{}

		}
	}()

	<-exit

	time.Sleep(2e9)
	fmt.Println("end.")}Copy the code

The output is:

hello, world!
hello, world!
end.
Copy the code



Pointer to the operating


package main

import (
	"fmt"
	"reflect"
)

func main(a) {
	type user struct {
		name string
		age  int
	}

	p := &user{ // Get the pointer
		name: "fliter",
		age:  26,
	}

	fmt.Println(p) //&{fliter 26}

	p.name = "jack" // Find the corresponding program entity through the pointer
	p.age--
	fmt.Println(p) //&{jack 25}

	fmt.Println(*p) //{jack 25}

	p2 := &p                        //&p is a second-order pointer
	fmt.Println(p2)                 //0xc00000e020
	fmt.Println(reflect.TypeOf(p2)) //**main.user
	//*p2.name = "john" //p2.name undefined (type **user has no field or method name)
}
Copy the code

The output is:

&{fliter 26}
&{jack 25}
{jack 25}
0xc00007c010
**main.user

Copy the code

The tag in the Struct


You can add a tag for each field in the struct. This tag can be obtained through the reflection mechanism, and the most common scenario (including but not limited to this, such as format validation, database relational mapping, etc.) is JSON serialization and deserialization.

package main

import (
	"fmt"
	"reflect"
)

type User struct {
	name string ` name `
	sex  string ` gender `
	age  int    ` age `
}

func main(a) {
	u := User{"Messi"."Male".32}
	v := reflect.ValueOf(u)
	t := v.Type()

	for i, n := 0, t.NumField(); i < n; i++ {
		fmt.Printf(For "% s: % v \ n", t.Field(i).Tag, v.Field(i))
	}
}
Copy the code

The output is:

Name: Messi Gender: male age: 32Copy the code


For JSON serialization


When converting a struct to JSON, the first letter of the field name in the struct must be capitalized; otherwise, it cannot be parsed properly. If you want to make the field name of a struct converted to JSON lowercase, you can specify it with a tag


package main

import (
	"encoding/json"
	"fmt"
)

type FiveAlevelArea struct {
	Name        string  `json:"name"`
	Location    string  `json:"address"`
	Price       float32 `json:"entrance ticket"`
	englishName string  `json:"english_name"`
}

func main(a) {

	heBei := FiveAlevelArea{
		Chengde Summer Resort and Surrounding Temple Scenic Area, Shuangqiao District, Chengde City."South Shanshan Road, Chengde City".100.00."Chengde Imperial Summer Resort",
	}

	j, err := json.Marshal(heBei)

	iferr ! =nil {
		fmt.Println(Error as follows:, err)
		return
	}

	fmt.Println(The json string is:.string(j))

}
Copy the code

The output is:

{"name":" Chengde Mountain Resort and its adjacent temples ","address":" Chengde Mountain Resort South Road ","entrance ticket":100}Copy the code

The name of a field whose first letter is not uppercase is not parsed. The last key displayed in the JSON string is the name specified in the tag tag


Anonymous fields


An anonymous field is a field that has no name but only a type. It is also called an embedded field or an embedded type. From the compiler’s point of view, this simply implicitly uses the type name as the field name. Members of anonymous fields can be referenced directly, but must be initialized as stand-alone fields.

Anonymous fields can be not only structures, but also any named type other than “interface pointer” and “multilevel pointer”.

Strictly speaking, Go is not an object-oriented programming language in the traditional sense, or implements only minimal object-oriented mechanisms. Anonymous embedding is not inheritance and does not allow polymorphic processing. While interfaces can be used in conjunction with a set of methods to show some similar operations, the nature is quite different.

package main

import "fmt"

type attr struct {
	perm int
}

type file struct {
	name string
	attr // An anonymous field with only the type name (but the IDE formatting this field does not align with the type of other fields, but with the name of other fields)
}

func main(a) {

	/ / way 1:
	var c file
	c.name = "my.txt"
	var a attr
	a.perm = 777
	c.attr = a
	fmt.Println(c, c.perm) // Read anonymous field members directly

	/ / way 2:
	// If a structure containing an anonymous field is assigned in this way, the type name must be used as the field name
	f := file{
		name: "test.dat",
		attr: attr{ // Use the type name as the field name
			perm: 755,
		},
	}
	f.perm = 500           // Set the anonymous field member directly
	fmt.Println(f, f.perm) // Read anonymous field members directly

}
Copy the code

usingAnonymous fieldsImplementing what’s called inheritance


Fields in a structure can have no name (only type), that is, anonymous fields;

If A struct(A) is nested with another anonymous struct(B), then A can access the methods of the anonymous struct(B) directly, thus implementing inheritance.

See above for how Golang uses composition to implement inheritance and how it differs from PHP or Java object-oriented inheritance


methods


Definition: func (recevier type) methodName(parameter list)(return value list){}


methodsandfunction


The relationship between “methods” and “functions” in Golang differs from that in other languages.

Method to add a new behavior to a user-defined type. Methods are declared with an argument added between the keyword func and the method name compared to functions

package main

import "fmt"

type user struct {
	name string
	age  int
}

func (u user) say(a) {
	fmt.Println("hello", u.name)
	fmt.Println("How old will you be in ten years?", u.age+10)}func (u *user) run(a) {
	fmt.Printf("%s is a great runner \n", u.name)

}

func main(a) {
	c := user{"Trump".73}
	c.say()

	s := &user{"Bolt".0}

	s.run()

}
Copy the code

Output:

Bolt is a great runnerCopy the code
  • A base type is prefixed with an & and becomes a pointer type.
  • When * is a verb, it must be followed by a pointer type, called dereferencing ~

The * (& a) = a

  • When used as an adjective, this type is a pointer type

Method is applied to the structure


package main

import (
	"fmt"
)

type FiveAlevelArea struct {
	Name        string  `json:"name"`
	Location    string  `json:"address"`
	Price       float32 `json:"entrance ticket"`
	englishName string  `json:"english_name"`
}

func (cs FiveAlevelArea) set(Name, Location, englishName string, Price float32) {

	cs.Name = Name
	cs.Location = Location
	cs.Price = Price
	cs.englishName = englishName

	fmt.Println(The value of the current structure is:, cs)
}

func (shuang FiveAlevelArea) get(a) FiveAlevelArea {
	return shuang
}

func main(a) {
	var heBei FiveAlevelArea
	heBei.set(Baoding City anxin County Baiyangdian Scenic Spot.Anxin County, Baoding City."Bai-yang Lake".40.00)

	heBei2 := heBei.get()

	fmt.Println(heBei)
	fmt.Println(heBei2)
}
Copy the code

The output is:

The value of the current structure is: {40 Bai-yang Lake, Baoding Anxin County} {0} {0}Copy the code

The value of the original variable is not changed because it is passed by value;

Change the set() method on line 14 to cs *FiveAlevelArea, and the result of the program is:

The value of the current structure is: &{Baoxin Baoxin 40 Bai-yang Lake} {Baoxin baoxin 40 Bai-yang Lake} {Baoxin baoxin 40 Bai-yang Lake}Copy the code

You might wonder why the set() method called on line 32 was compiled with a variable of type FiveAlevelArea, not a pointer. Actually go automatically adds the ampersand (&), line 32:

HeBei. Init (" Baiyangdian Scenic Spot ", "Baoding Anxin County "," Bai-Yang Lake", 40.00)

Is equal to:

(&heBei).init("保定市安新县白洋淀景区", "保定市安新县", "Bai-yang Lake", 40.00)


Methods apply to other variables


package main

import "fmt"

type cInt int

func (cui cInt) f1(a) {
	fmt.Println("The variable value is :", cui)
}

func (c *cInt) f2(args cInt) {
	*c = args + 6
}

func main(a) {

	var a1 cInt = 10086

	fmt.Println(a1)

	// Call the cInt type f1() method
	a1.f1()



	var a2 cInt

	/ / & a2 a2 memory address is to obtain the variable value is a pointer, if the pointer to a parameter needs to receive (*) must be a pointer type behind method so the f2 () by value a2, go automatically converts a2 & a2 namely variable a2 memory address, so the following two kinds of writing can be
	a2.f2(12300)
	fmt.Println(a2)

	(&a2).f2(12300)
	fmt.Println(a2)


	// Pass the pointer to change the value of the original variable
	var a3 cInt = 12360
	a3.f2(a3)
	fmt.Println(a3)
	(&a3).f2(a3)
	fmt.Println(a3)

}
Copy the code

The output is:

10086 The value of the variable is 10086 12306 12306 12366 12372Copy the code

String () method


If a variable implements the String() method, fmt.println calls the variable’s String() method by default.

package main

import "fmt"

type Transportation struct {
	name  string
	speed string
}

func (o *Transportation) Run(a) {

	fmt.Printf("The vehicle %s is running! \n", (*o).name) // Here "o.name" is also compiled (o is a pointer,*o is dereferenced to the variable corresponding to the memory address), and go is automatically converted to (*o).name
}

// Trains inherit transportation
type Train struct {
	Transportation
	InventedTime int // Time of invention
}

func (cs *Train) String(a) string {
	str := fmt.Sprintf("The speed of %s can reach %s\n", cs.name, cs.speed)
	return str
}

func main(a) {
	var train Train

	train.name = "The train"
	train.speed = "350km/h"
	train.InventedTime = 1804

	fmt.Println(train)

	fmt.Println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
	train.Run()

	fmt.Println("* * * * * * * * * * * * * * * * * *")
	fmt.Printf("%s", &train)

	fmt.Println("# # # # # # # # # # # # # # # # # #")
	fmt.Println("String() method \n is automatically called", &train)

}

Copy the code

The output is:

{1804} {350 km/h train} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- transport train run! * * * * * * * * * * * * * * * * * * the speed of the train can reach 350 km/h # # # # # # # # # # # # # # # # # # will automatically call the String () method of the speed of the train can reach 350 km/hCopy the code

For more tips on struct use, click here