“This is the 23rd day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.

Go language learning

This article appears in my column:Let’s Golang

A problem with passing slices as mutable parameters

Let’s look at a piece of code:

package main
​
import "fmt"func Myfunc(num ...int) {
    num[0] = 2
    total := 0
    for _, i := range num {
        total += i
    }
    num[1] = total
}
func Sum(num ...int) {
​
    total := 0
    for _, i := range num {
        total += i
    }
    num[1] = total
}
func main(a) {
    i := []int{1.2.3}
    Myfunc(i...)
    fmt.Println(i)
    Sum(i...)
    fmt.Println(i)
}
​
Copy the code

The result of this code is:

[2 7 3]
[2 12 3]
Copy the code

Is it weird why the values in the slices change? In fact, we pass the slice to the function as a value pass, so the argument we pass to the function is actually a copy of the value of the following slice.

type slice struct{
    value *int 
    length uint 
    capacity uint 
}
Copy the code

However, the value in the slice structure is a pointer, so even if the slice is copied, it and its copied value are the same value, pointing to the same area.

So in the above code, we can operate on the slice of I inside main in Myfunc and Sum.

However, when we expand the num slice, the address pointing to the value of the copied value may change.

For example, let’s do the following:

func Sum(num ...int) {
    num[0] = 8
    total := 0
    for _, i := range num {
        total += i
    }
    num = append(num, total)
    num[1] = total
}
Copy the code

The results are as follows:

[2 7 3]
[8 7 3]
Copy the code

This is a side description of slice’s expansion algorithm.

A variable length argument should be the last argument in the function header.

Some people wonder, isn’t it mutable parameters? Why is a slice passed in? In fact, the underlying variable parameter is implemented with slicing, it is passed one or more parameters into a slice.

2. Different types of data are not allowed to be computed in Go

We all know that Go has extremely strict static type restrictions, and only the same type of data can be evaluated, so how can we solve this problem?

The first point, of course, is cast casting. Such as:

func main(a) {
    var (
        i int     = 3
        j float32 = 3.1
    )
    fmt.Println(float32(i) + j)
}
Copy the code

This program runs without compiling errors and results in 6.1.

There is another method, but it applies to a single scenario. Is to define an untyped constant. Such as:

package main
​
import (
    "fmt"
)
​
func main(a) {
    const i = 1
    const j = 2.1
​
    fmt.Println(i + j)
}
​
Copy the code

When run, no error is reported and the result is 3.1.

Can arrays of different lengths be compared

Take a look at the following code:

package main
​
import (
    "fmt"
)
​
func main(a) {
    a := [2]int{1.2}
    b := [3]int{1.2}
    if a == b {
        fmt.Println("equal")}else {
        fmt.Println("not equal")}}Copy the code

Do you think they are equal?

Ha ha ha ha

The length of the array is part of the array, so the two arrays are not of the same type, so they cannot be compared, so an error will be reported:

invalid operation: a == b (mismatched types [2]int and [3]int)
Copy the code

4. One thing to note about map

Let’s start with this code:

package main
​
import (
    "fmt"
)
​
func main(a) {
    Map := make(map[string]int)
    delete(Map, "map")
    fmt.Println(Map["map"])}Copy the code

Map is empty, do you think it will report an error? If no error is reported, what is output?

The answer is no error, it prints 0.

Are you right? Here’s how to explain:

Go is designed to delete non-existent key-value pairs in a map without an error, and to obtain non-existent key-value pairs in a map, the value type is zero.