【8.0】Go语言基础之可变函数参数、map的使用

发布时间 2023-11-11 21:07:43作者: Chimengmeng

【一】可变长参数

【1】任意长度的指定类型的参数

package main

import "fmt"

func main() {
	// 可变长参数
	// 调用函数
	foo(1, 2, 3, 4, 5, 6)
	// 这是接收到的 参数 a :>>>>  [1 2 3 4 5 6]
	// 这是接收到的 参数 a 的类型 :>>>> []int
}

// 可以接收任意长度的 int 类型参数
func foo(a ...int) { // 可以接收任意长度参数,但是类型必须一致
	fmt.Println("这是接收到的 参数 a :>>>> ", a)
	fmt.Printf("这是接收到的 参数 a 的类型 :>>>> %T", a) // 切片类型
}

【2】任意长度的任意类型的参数

package main

import "fmt"

func main() {
	// 可变长参数
	// 调用函数
	foo(1, 2, 3, 4, 5, 6, "dream")
	// 这是接收到的 参数 a :>>>>  [1 2 3 4 5 6 dream]
	// 这是接收到的 参数 a 的类型 :>>>> []interface {}
}

// 可以接收任意长度的 任意 类型参数
func foo(a ...interface{}) { // 可以接收任意长度参数,但是类型必须一致
	fmt.Println("这是接收到的 参数 a :>>>> ", a)
	fmt.Printf("这是接收到的 参数 a 的类型 :>>>> %T", a) // 空接口类型
}

【3】切片类型的参数传入

package main

import "fmt"

func main() {
	// 可变长参数
	// 调用函数

	// 定义切片类型
	a := []int{1, 2, 3, 4, 5}
	foo(a...) // 相当于将切片 a 打散传入
	// 这是接收到的 参数 a :>>>>  [1 2 3 4 5]
	// 这是接收到的 参数 a 的类型 :>>>> []int
}

// 可以接收任意长度的 int 类型参数
func foo(a ...int) { // 可以接收任意长度参数,但是类型必须一致
	fmt.Println("这是接收到的 参数 a :>>>> ", a)
	fmt.Printf("这是接收到的 参数 a 的类型 :>>>> %T", a) // 切片类型
}

【二】map类型

  • map 是在 Go 中将值(value)与键(key)关联的内置类型。通过相应的键可以获取到值(字典类型)
    • key值只能用数字,字符串,布尔,key值也固定
    • value值可以任意,但是go中value值必须都一致

【1】定义map

package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的定义
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	var m map[string]int

	// 只定义,没有初始化
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[]
	if m == nil {
		fmt.Println("map 类型的 0 值 为 nil")
	}
	// map 类型的 0 值 为 nil

}

【2】初始化map

(1)方式1

package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的定义
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	// 初始化 map
	var m map[string]int = make(map[string]int)
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[]
	if m == nil {
		fmt.Println("map 类型的 0 值 为 nil")
	} else {
		fmt.Println("map 类型的 0 值 不是 nil")
	}
	// map 类型的 0 值 不是 nil 
}

(2)方式2

package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的定义
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	// 初始化 map
	var m map[string]int = map[string]int{"name": 1, "value": 1}
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[name:1 value:1]
}

(3)方式3

package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的定义
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	// 初始化 map
	m := map[string]int{"name": 1, "value": 1}
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[name:1 value:1]
}

【3】map的使用

(1)取值和赋值

package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的使用 : 取值 / 赋值
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	// 初始化 map
	m := map[string]int{"name": 1, "value": 1}
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[name:1 value:1]

	// 取值 , 赋值
	// 根据 key 取值
	fmt.Println("根据 key 取值 :>>>> ", m["name"]) // 根据 key 取值 :>>>>  1

	// 赋值
	m["value"] = 9
	fmt.Println("这是修改后的 map :>>>> ", m) // 这是修改后的 map :>>>>  map[name:1 value:9]

	// 赋值不存在会新增
	m["age"] = 18
	fmt.Println("这是修改后的 map :>>>> ", m) // 这是修改后的 map :>>>>  map[age:18 name:1 value:9]

	// map 可以无限制的添加值 , 前提是内存够用

	// 取值不存在的值 --- 不会报错 , 但是会取出 value 为 int 类型 的 0 值
	fmt.Println("根据 key 取值 :>>>> ", m["gender"]) // 根据 key 取值 :>>>>  0

	// 当某个值 存进去 为 0 值 (不存在也是 0 值 )
	fmt.Println("根据 key(不存在) 取值 :>>>> ", m["gender"]) // 根据 key(不存在) 取值 :>>>>  0
	m["sex"] = 0
	fmt.Println("根据 key(赋 0 值) 取值 :>>>> ", m["sex"]) // 根据 key(赋 0 值) 取值 :>>>>  0

	// 根据 key 取 value , 判断 value 是否存在
	_, ok := m["school"]                     // 可以使用两个值来接收,第二个值为布尔值,如果 ok 为 true ,说明存在,否则不存在
	fmt.Println("根据 key(不存在) 取值 :>>>> ", ok) // 根据 key(不存在) 取值 :>>>>  false
	m["school"] = 999
	_, okk := m["school"]
	fmt.Println("根据 key(存在) 取值 :>>>> ", okk) // 根据 key(存在) 取值 :>>>>  true
}

(2)判断value值是否存在

  • 见上

(3)删除值

package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的使用 : 取值 / 赋值
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	// 初始化 map
	m := map[string]int{"name": 1, "value": 1}
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[name:1 value:1]

	// 删除存在值
	delete(m, "name")                   // 只能根据 key 删除
	fmt.Println("这是删除后的 map :>>>> ", m) // 这是删除后的 map :>>>>  map[value:1]

	// 删除不存在的值
	delete(m, "school")                 // 本来就没有 对应的 value 值 ,所以删除完还是没有
	fmt.Println("这是删除后的 map :>>>> ", m) // 这是删除后的 map :>>>>  map[value:1]
}

【4】map的长度

package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的使用 : 取值 / 赋值
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	// 初始化 map
	m := map[string]int{"name": 1, "value": 1}
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[name:1 value:1]

	// map 的 长度 : 总共有多少个元素
	fmt.Println("map 的长度 :>>>> ", len(m)) // map 的长度 :>>>>  2

	// 没有容量,但是可以无限扩容,前提是内存足够大
}

【5】map类型的零值

  • map是引用类型,零值是 nil,引用类型一定要初始化,值类型不需要初始化就有零值
package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的使用 : 取值 / 赋值
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	// 初始化 map
	m := map[string]int{"name": 1, "value": 1}
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[name:1 value:1]

	// map是引用类型,零值是 nil,引用类型一定要初始化,值类型不需要初始化就有零值

	// 当参数传递 : 原来的 map 会被修改 (引用传递)
	// 调用函数foo
	fmt.Println("这是调用函数之前的 m :>>>> ", m) // 这是调用函数之前的 m :>>>>  map[name:1 value:1]
	bar(m)                               // 这是函数内部的 m :>>>>  map[name:1 value:999]
	fmt.Println("这是调用函数之后的 m :>>>> ", m) // 这是调用函数之后的 m :>>>>  map[name:1 value:999]

}

func bar(m map[string]int) {
	m["value"] = 999
	fmt.Println("这是函数内部的 m :>>>> ", m)
}

【6】map类型之间不能 == 操作

package main

import "fmt"

// map 的 使用
func main() {
	// [1] map 的使用 : 取值 / 赋值
	// 定义map类型 : key 为 string 类型 ; value 为 int 类型
	// 初始化 map
	m := map[string]int{"name": 1, "value": 1}
	n := map[string]int{"name": 1, "value": 1}
	fmt.Println("这是创建的 map :>>>> ", m) // 这是创建的 map :>>>>  map[name:1 value:1]
	fmt.Println("这是创建的 map :>>>> ", n) // 这是创建的 map :>>>>  map[name:1 value:1]

	// map是引用类型,零值是 nil,引用类型一定要初始化,值类型不需要初始化就有零值

	// map 之间不能使用 == 操作符判断,== 只能用来检查 map 是否为 nil
	// fmt.Println(m==n) // Invalid operation: m==n (the operator == is not defined on map[string]int)

	// 引用类型不能比较 ,值类型能比较
	a := [3]int{4, 5, 6}
	b := [3]int{4, 6, 6}
	c := [4]int{4, 6, 6}
	fmt.Println(a)
	fmt.Println(b)
	fmt.Println(c)
	fmt.Println(a == b) // 长度不一样,不是同一个类型
	//fmt.Println(a == c) // Invalid operation: a==c (mismatched types [3]int and [4]int)
}

【补充】各种数据类型的零值

package main

import "fmt"

// map 的 使用
func main() {

	// 补充 :数字 字符串 布尔 切片 数组 map 类型的 0 值
	// 数字 字符串 布尔 数组 ----> 值类型 (有自己的零值 0 "" false 元素类型的零值)
	// 切片 map ----> 引用类型 (零值 是 nil)
	var a int
	fmt.Println("数字类型的 0 值为 :>>>> ", a) // 数字类型的 0 值为 :>>>>  0

	var b float32
	fmt.Println("浮点类型的 0 值为 :>>>> ", b) // 浮点类型的 0 值为 :>>>>  0

	var n bool
	fmt.Println("布尔类型的 0 值为 :>>>> ", n) // 布尔类型的 0 值为 :>>>>  false

	var c string
	fmt.Println("字符串类型的 0 值为 :>>>> ", c) // 字符串类型的 0 值为 :>>>>

	var d []int
	fmt.Println("数组类型的 0 值为 :>>>> ", d) // 数组类型的 0 值为 :>>>>  []

	var e [][]int
	fmt.Println("切片类型的 0 值为 :>>>> ", e) // 切片类型的 0 值为 :>>>>  []

	var m map[int]string
	fmt.Println("map类型的 0 值为 :>>>> ", m) // map类型的 0 值为 :>>>>  map[]
}