“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.