The title of this paper is grammatical sugar and comparison rules, but the content arrangement is not limited to grammatical sugar. The content is mainly to summarize and sort out grammar points and data comparison rules that are easy to be ignored during the use of Go. This article will continue to be updated.

Syntactic sugar

: =The operator

The short type declaration (derivation declaration) operator := is used only within functions, that is, only temporary variables can be claimed. Declarations of global variables use the var operator.

Example:

// Swap two variables
func exc(a) {
    a, b := 20.21
    b, a = a, b
}
Copy the code

_The operator

1. Empty import of packages

If the imported package name is not referenced in the file, a compilation error is generated. However, sometimes we have to import a package to perform initialization expression evaluation on package-level variables and init. To prevent this error, we use _ rename to import an unused package. Example:

import _ "image/png"
Copy the code

2. Ignore fields

Assigning an unwanted value to an empty identifier, as shown in the following example:

_, ok = m[key] // Query the result of discarding the map
Copy the code

3, structure label

In the structure tag, use _ to ignore fields that do not require serialization. Example:

type User struct {
    ID   int     `json:"-"`            // This field is not serialized
    Name string  `json:name,omitempy`  // If it is of type zero or null, this field is ignored for serialization
}

Copy the code

.The operator

1, “indefinite” array definition

We know that arrays usually have a fixed length, so can we apply for arrays with a fixed length? Declares an indefinite array. The length of the array is determined by the number of elements that initialize the array. It’s not that the length is indeterminate, it’s that the length is indeterminate when you write the code, when you compile the program, it’s already determined, it’s no different than a fixed-length array. Example:

    a := [...]int{1.2.3}
    fmt.Printf("%T\n", n) // [3]int The length of the array is part of the array type a is of type [3]int
    
    r := [...]int{99:1}   // Apply for an array r with 100 elements
    fmt.Printf("%T\n", n) // [100]int All elements are of type 0 except the last element which has a value of 1
Copy the code

2. Slice and unpack

Slice When appending slice data, use… Turn the slice into a parameter list. Example:

    var x []int
    x = append(x, 1)
    x = append(x, 2.3)
    x = append(x, x...) // Appends all elements of x
    fmt.Println(x)      / / ",2,3,1,2,3 [1]"
Copy the code

3. Variable length parameters

When a function is declared, the parameter… Indicates that the function can accept a variable length argument list. Example:

//slice appends the append function declaration
func append(slice []Type, elems ... Type) []Type{... }Copy the code

Three operators

Usually functions use extra return values to indicate some error result, and here are three operators that do something similar.

1. Map query

// Check whether the map key exists special notation
if v, ok := map[key]; ok {
    fmt.Println("There is an element with key in map and the value is.",v)
}
Copy the code

Type assertion

    v, ok := x.(T)
Copy the code

3. Channel reception

    v, ok := ->ch
Copy the code

Compare the rules

conclusion

The data type = =The comparison nilThe comparison instructions
The numerical can
Floating point can
The plural can
Boolean can
character can
An array of can Can not be An array is comparable if its element types are comparable
struct can Can not be ifstructIf all of the fields in thestructIs comparable; ifstructIf the corresponding non-blank fields are equal, they are equal
Pointer to the can can If two Pointers point to the same variable, they are equal; Both Pointers are equal tonilThey are also equal to each other
channel can can If two channels are made up of the samemakeCreated, the two channels are equal; Values of both channels arenilThey are also equal to each other
interface can can Two interfaces are equal if their dynamic values and dynamic types are equal. The value of both interfaces isnilSo they’re equal to each other.
map Can not be can Map is not comparable, and the only valid ones are andnilCompare. Compare the twomapIf they have the same key value, you have to write a loop
slice Can not be can It’s provided in the standard librarybytes.EqualTo compare the two[]bytesSlice is equal or not, for other types need to write their own function implementation
func Can not be can Function type zero value isnil, call anilThe function will cause downtime

Pointer to the

Two Pointers to the same variable, those two Pointers are equal, or if both Pointers are nil, they’re equal. Pointer values can be compared to nil.

    var num1, num2 int
    num1 = 8
    num2 = 8

    pt1 := &num1
    pt2 := &num1
    pt3 := &num2

    var pt4 *int // Define a null pointer

    // Two Pointers are equal only if they point to the same variable
    fmt.Printf("%v %v\n", pt1 == pt2, pt1 == pt3)  //true false

    // Pointers can be compared directly to nil
    fmt.Printf("%v %v\n", pt4 == nil, pt1 == nil) //true false
Copy the code

chan

If both channels are created by the same make, or if both channels have nil values, they are equal.

    ch1 := make(chan int)
    ch2 := make(chan int)
    
    var ch3 chan int
    ch3 = ch1
    
    var ch4 chan int
    var ch5 chan int
    var ch6 chan string
    
    // All channels created by make are equal
    fmt.Printf("%v %v\n", ch1 == ch2, ch3 == ch1) //false true
    
    // Channel values can be compared to nil
    fmt.Printf("%v %v\n", ch4 == ch5, ch5 == ch1) //true true
    
    // There is an error indicating that two channels of different types cannot be compared, even if both are null
    fmt.Printf("%v\n", ch5 == ch6)
Copy the code

map

The key type in the map must be a data type that can be compared by ==, so the map can verify that a key already exists without any restriction on the value type. Although floating-point numbers can be compared with ==, there is a loss of precision in comparing floating-point numbers for equality, so floating-point numbers are not a good choice as a map key either.

    args := make(map[string]int) {
        "alice":   31."charles": 34,}// Check whether the key exists
    if v, ok := args["alice"]; ok {
        fmt.Println(v)
    }
Copy the code
// Compare whether two maps have the same key and value
func equal(x, y map[string]int) bool {
    if len(x) ! =len(y) {
        return false
    }
    for k, xv := range x {
        ifyv, ok := y[k]; ! ok || yv ! = xv {return false}}return true
}
Copy the code

slice

To check if a slice is empty, use Len (s) == 0 instead of s == nil, since S! = nil can also be null.

    var s[]int     // Len (s) == 0, s == nil nil slice
    s = nil        // Len (s) == 0, s == nil nil slice
    s = []int(nil) // Len (s) == 0, s == nil nil slice
    s = []int{}    // len(s) == 0, s ! = nil empty slice
Copy the code

For other types of slice, you need to implement your own function comparison, for example:

func equal(x,y []string) bool {
    if len(x) ! =len(y) {
        return false
    }
    for i := range x {
        ifx[i] ! = y[i] {return false}}return true
}
Copy the code