Learn to write casually 4

Composite data type (construction type)

map

Golang map is a reference to the Hash table, which is almost a PHP associative array or Python dictionary. Of course, C++ STL also has a map, but golang map should be unordered_map. Map all keys must be of the same type, and values must also be of the same type. This is not as arbitrary as PHP associative arrays. In addition, keys must support = = comparison, so it is usually an original basic type. Because of the imprecision of floating-point comparison, it is not a good idea to use floating-point numbers as keys (golang NaN can be floating-point).

Initialize a map, similar to the following:

ages := map[string]int {
    "Alice":   31,
    "Charlie": 34,
}

There are two ways to create an empty map

ages := map[string]int {}
// or
ages := make(map[string]int)

To remove an element (key value pair) of the map, you can use the built-in function delete, such as

delete(ages, "Alice")

You can safely delete a nonexistent element (the key does not exist), or even safely access the nonexistent key (zero value of this type is returned) or modify it (automatically create the element and then modify it), for example

ages["Bob"] = ages["Bob"] + 1
// or
ages["Bob"] += 1
// or
ages["Bob"]++

The above code will actively create an element with a key of Bob and a value of 0, and then increase the value by 1, which seems to be a little more exaggerated than STL map.

The keys of golang map are unordered, which is different from the internal order of STL map using red black tree. If you really need to sort by pressing keys, you can only traverse the map, take out the keys as an array, sort the array, and then index the map.

map element access and traversal are natural, but nonexistent keys can also be accessed (return zero value). So how to distinguish whether the returned is exactly 0 or 0 because the key does not exist? The answer is that the access key can not only return the value, but also return whether the retrieval is successful:

age, ok := ages["bob"]
if !ok { /* not key! */ }
// or
if age, ok := ages["bob"]; !ok { /* not key! */ }

Like slice, except with = = or= Compared with nil, map is not comparable. If you really want to compare two maps, you can only write the function manually, but the map allows access to nonexistent keys, which brings a small pit to the comparison function

package main

import (
	"fmt"
)

func main() {
	map1 := map[string]int{"A": 0}
	map2 := map[string]int{"B": 42}
	fmt.Println(equal(map1, map2))		// false
}

func equal(x, y map[string]int) bool {
	if len(x) != len(y) {
		return false
	}
	for k, xv := range x {
		if yv, ok := y[k]; !ok || yv != xv { // The absence of k in y is also unequal
			return false
		}
	}
	return true
}

golang does not have a collection type, but you can directly use map[T]bool instead of a collection. What happens when we want the key to be of some non comparable type (such as slice)? Like the previous sorting problem, the alternative implementation is to introduce the auxiliary function k(), ensure that when and only when x and y are equal, k(x) == k(y), and the return type of k() is comparable (usually string type), and then create a map in the form of map[k(T)]T '

The value type of a map can be a composite type, such as slice or another map. make(map[string]map[string]bool) will create a map with a key of string and a value of bool

structural morphology

The golang structure is similar to the C structure, but the members of the golang structure can be empty. In addition, the declaration is made by defining a new type (type alias):

type Employee struct {
	ID			int
	Name		string
	Address		string
	DoB			time.Time
	Position	string
	Salary		int
	ManagerID	int
}

Declare the variable var with this type   john Empoyee

Visit member john.Salary -= 5000

Pointer access position: = & John. Position;    * position = "Senior " + *position

The pointer to the structure also uses a dot. Access!

var  e  *Empoyee = &john  ;    e.Position += "  (proactive team player)"

The names and order of structure members are very important. Without changing the order, members of the same type can be simplified into one line.

The golang structure has an access control mechanism by Wang Yin's tusk, that is, make complaints about capitalization means that the variable is exported and the lowercase is private. This is consistent with the case of package global variables.

Two methods can be used for structure initialization (short structure multi-purpose mode 1 and complex structure multi-purpose mode 2), but they cannot be mixed

package main

import (
	"fmt"
)

func main() {
	p1 := Point{1, 2}		// Mode 1
	p2 := Point{Y: 2, X: 1}	// Mode 2, not in order
	p3 := Point{X: 1}		// Method 2: some members are given values, and the rest are 0 by default
	fmt.Println(p1)			// {1 2}
	fmt.Println(p2)			// {1 2}
	fmt.Println(p3)			// {1 0}
}

type Point struct {
	X, Y int
}

Structure types are copied as function parameters (value transfer). Therefore, for large structures as function parameters, pointer mode is generally used. Creating and initializing a structure variable and obtaining its address can be completed in one step:  

pp := &Point{1, 2}
// Equivalent to
pp := new(Point)
*pp = Point{1, 2}

&Point {1, 2} is completed in one step (a pointer is returned), so it can be used as a function argument.

Whether the structure can use = = or= Comparison is determined by all its members, that is, only when all members can be compared can the structure be compared. When a structure can be compared with = =, it can be used as the key of the map.

golang supports nested anonymous structures and provides quick syntax for members accessing anonymous structures:

package main

import (
	"fmt"
)

func main() {
	var w Wheel
	w.X = 8      // Equivalent to w.Circle.Point.X = 8
	w.Y = 8      // Equivalent to w.Circle.Point.Y = 8
	w.Radius = 5 // Equivalent to w.Circle.Radius = 5
	w.Spokes = 20
	fmt.Println(w) // {{{8 8} 5} 20}
	w1 := Wheel{Circle{Point{8, 8}, 5}, 20}
	w2 := Wheel{
		Circle: Circle{
			Point:  Point{X: 8, Y: 8},
			Radius: 5,                // This comma is required!
		},
		Spokes: 20,                   // This comma is required!
	}
	fmt.Printf("%#v\n", w1)
	fmt.Printf("%#v\n", w2)
}

type Point struct {
	X, Y int
}

type Circle struct {
	Point  // Anonymous structure, automatically embedded members X, Y
	Radius int
}

type Wheel struct {
	Circle // Anonymous structure, auto embedding X, Y, Radius
	Spokes int
}

In the code, when structures are initialized literally, they can only be initialized in the standard way (note that the code contains the comma at the end of the last member when nested structures are initialized, which can be understood as "a structure with sons initializes the last member followed by a comma"). The above code output

{{{8 8} 5} 20}
main.Wheel{Circle:main.Circle{Point:main.Point{X:8, Y:8}, Radius:5}, Spokes:20}
main.Wheel{Circle:main.Circle{Point:main.Point{X:8, Y:8}, Radius:5}, Spokes:20}

For access control of members of nested structures, for example, point is not exportable, but there are exportable members X and Y. when it is passed through circle (not exportable) When embedding Wheel, w.X's package is still available in the Wheel, but w.circle.point.X is not. It is easy to understand that the access control of the embedded member is not the original structure has the final say, it seems that it has become a member of the structure containing inlay.

Embedded anonymous members are not limited to structure types. Any named type or pointer to a named type can be used. The way to access anonymous members by shortcut is not only applicable to the internal variables of anonymous members, but also to its methods. This mechanism helps golang realize OOP of aggregation.

----

Keywords: PHP Python Go

Added by Papalex606 on Sat, 20 Nov 2021 03:55:46 +0200