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){}
methods
andfunction
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