go语言基础--杂谈

go语言基础--杂谈_第1张图片
常量运行期间,不可以改变的值

const PI float64 = 3.14

字面常量
所谓字面常量,是值程序中硬编码的常量

123 //整型类型常量
156.78 //浮点类型的常量
true  //布尔类型的常量
“abc”//字符串类型的常量
//const PI float64 = 3.14
const PI = 3.14 //
//PI = 3.15 //cannot assign to PI 不允许修改常量的值
//fmt.Printf("%p", &PI)//: cannot take address of PI 不允许打印常量的地址
fmt.Printf("%f\n", PI)

算术运算符

go语言基础--杂谈_第2张图片

var num1 int = 20
	var num2 int = 10
	//num1+num2 =  30
	//num1-num2 =  10
	//num1*num2 =  200
	//num1/num2 =  2
	//num1%num2 =  0
	fmt.Println("num1+num2 = ", num1+num2)
	fmt.Println("num1-num2 = ", num1-num2)
	fmt.Println("num1*num2 = ", num1*num2)
	fmt.Println("num1/num2 = ", num1/num2)
	fmt.Println("num1%num2 = ", num1%num2)

除法运算和取余预算除数不能为0

自增自减运算符

var num int = 10
num++
fmt.Println(num)

赋值运算符

go语言基础--杂谈_第3张图片

var num int = 10
num += 10
fmt.Println(num)
num -= 10
fmt.Println(num)

num %= 2 + 3 //先算+ 后算%=
fmt.Println(num)

算术>赋值

关系运算符

go语言基础--杂谈_第4张图片

var num1 int = 10
var num2 int = 20
fmt.Println("num1 == num2 ", num1 == num2) //false
fmt.Println("num1 != num2 ", num1 != num2) //true
fmt.Println("num1 >=num2 ", num1 > num2) //false
fmt.Println("num1 < num2 ", num1 < num2) //true
fmt.Println("num1 >= num2 ", num1 >= num2) //false
fmt.Println("num1 <= num2 ", num1 <= num2) //true

关系运算符只能是true或者false

sum := num1+20 > num2	//先算算术 算术>关系>赋值
fmt.Println("sum = ", sum)

逻辑运算符

go语言基础--杂谈_第5张图片

var num1 int = 10
var num2 int = 20

isResult := num1 > num2
fmt.Println("isResult = ", isResult)
fmt.Println("isResult = ", !isResult)
// 逻辑运算符不能跟整型 逻辑非后面的变量是布尔布尔类型 。逻辑非的运算符优先级高于关系运算符
fmt.Println(!(num1 > num2)) //invalid operation: operator ! not defined on num1   括号的优先级要高于逻辑非

//逻辑与
fmt.Println(num1 > num2 && num1 == 10) //false 逻辑与运算符优先级低于关系运算符

//逻辑或
fmt.Println(num1 > num2 || num1 == 10) //true 逻辑或运算符优先低于关系运算符

fmt.Println(num1 > num2 || num1 > num2 && num1 != 0) //false 逻辑与的优先级高于逻辑或
fmt.Println(num1 < num2 || num1 > num2 && num1 != 0) //true 逻辑与的优先级高于逻辑或

go语言基础--杂谈_第6张图片
Switch中fallthrough,如果写了这个就往下执行fallthrough

// TestSum 不定参数
// 如果只写一个变量,该变量中存储的是集合的编号
// _:匿名变量。匿名变量不会保存具体的数据
func TestSum(args ...int) {
	for i := 0; i < len(args); i++ { //len 可以获取参数的存储的数据的个数
		fmt.Println(args[i])
	}

	//集合
	for i, v := range args { //
		fmt.Println("i = ", i) //i集合的编号。
		fmt.Println("v = ", v) //v存储的是具体的值
	}
}
/*
func AddResult(num1 int,num2 int) int { // 表示指定函数返回的数据的类型。
	var sum int
	sum = num1+num2
	return sum //将变量sum中存储的值返回。
}
*/
// 表明:最终会返回整型变量sum中的值。
// 在函数体中没有必要在重新创建sum变量。
/*
func AddResult(num1 int,num2 int) (sum int) {
	// var sum int
	sum = num1+num2
	return sum //将变量sum中存储的值返回。
}
*/
func AddResult(num1 int,num2 int) (sum int) {
	// var sum int
	sum = num1+num2
	return  //如果已经指定了返回的变量的名称,那么return后面可以不用在加上变量的名称。
}
func GetResult()(num1 int,num2 int){
	//var num1 int = 10
	// var num2 int = 20
	num1=10
	num2=20
	//return num1,num2 //表明返回两个变量的值。
	return 
}
func GetResult()(int,int){
	//var num1 int = 10
	// var num2 int = 20
	num1=10
	num2=20
	//return num1,num2 //表明返回两个变量的值。
	return 
}

数组

	/*
	var Numbers[5] int = [5]int{1,2,3,4,5} // 下标是从0开始计算的。
	fmt.Println(Numbers[3])
	*/
	//  部分赋值
	/*
	Numbers := [5]int{1,2}
	fmt.Println(Numbers[4])
	*/
	// 指定某个元素初始化
	/*
	Numbers :=[5]int{2:5,3:6}
	fmt.Println(Numbers[3])
	*/
	//通过初始化确定数组长度
	/*
	Numbers :=[...]int{7,8,5}
	//fmt.Println(len(Numbers))
	fmt.Println(Numbers[0])
	*/
	var Numbers [5] int
	/*
	Numbers[0]=1
	Numbers[1]=2
	fmt.Println(Numbers[3])
	*/
	for i := 0; i < len(Numbers); i++ {
		Numbers[i] = i + 1
	}
	fmt.Println(Numbers[0])

数组比较

package main

import "fmt"

func main() {
	// 完成两个数组中元素的比较,判断其相同下标对应的元素是否完全一致。
	// 1: 判断两个数组的长度是否一致。
	// 2: 判断值是否一致。
	var num1 [5]int = [5]int{1, 2, 3, 4, 5}
	var num2 [5]int = [5]int{3, 2, 3, 4, 5}
	fmt.Println(num1!=num2)
	/*
	b := compareValue(num1, num2)
	if b {
		fmt.Println("数组一致")
	} else {
		fmt.Println("数组不一致")
	}
	*/

}
func compareValue(n1 [5]int, n2 [5]int) bool {
	var b bool = true
	// 1: 判断两个数组的长度是否一致。
	if len(n1) == len(n2) {
		// 2: 判断值是否一致。
		for i := 0; i < len(n1); i++ {
			if n1[i] == n2[i] {
				continue
			} else {
				b = false
				break
			}
		}
	} else {
		b = false
	}
	return b
}

二维数组

package main

import "fmt"

func main() {
	// var arr [2][3]int = [2][3]int{{1, 2, 3}, {5, 6, 7}} // 全部初始化
	// 部分初始化
	// var arr [2][3]int = [2][3]int{{1,2},{6}}
	// 指定元素初始化
	// var arr [2][3]int = [2][3]int{0:{1:6}}
	// 通过初始化确定二维数组行数
	// arr := [...][3]int{{1, 2, 3}, {5, 6}} // 行的下标可以用"..."来代替,但是列的下标不能用"..."来代替。
	// fmt.Println(arr)

	// 通过循环遍历的方式输出打印二维数组中的值。
	var arr [2][3]int = [2][3]int{{1, 2, 3}, {5, 6, 7}}
	// fmt.Println(len(arr)) // 输出的是有几行。
	//fmt.Println(len(arr[0])) // 输出有几列。
	// fmt.Println(arr[0])
	/*
	for i := 0; i < len(arr); i++ {  // 遍历的行
		for j := 0; j < len(arr[0]); j++ { // 遍历的是列。
			fmt.Println(arr[i][j])
		}
	}
	*/
	for _, v := range arr {
		//fmt.Println("i", i)
		//fmt.Println("v", v)
		for j, data := range v {
			fmt.Println("j:",j)
			fmt.Println("data:",data)
		}
	}
	/*
	arr[0][1]=123
	arr[1][1]=456
	fmt.Println(arr[0][1])
	*/

}

切片

切片与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大,
所以可以将切片理解成“动态数组”,但是,它不是数组。

3. 使用make( )函数创建

长度是已经初始化的空间。容量是已经开辟的空间,包括已经初始化的空间和空闲的空间。

//var s []int
	//s := []int{}
s := make([]int, 3, 5) //长度已经初始化的空间为3,容量是已经开辟的空间5,包括已经初始化的空间和空闲的空间 长度不能大于容量
fmt.Println(s)
fmt.Println(len(s))
fmt.Println(cap(s))

1 make(切片类型, 长度, 容量)
2.长度是已经初始化的空间。容量是已经开辟的空间,包括已经初始化的空间和空闲的空间。
3.在使用make( )函数定义切片时,一定要注意,切片长度要小于容量
4 len( )函数返回长度,cap( )返回容量
5 make( )函数中的容量参数是可以省略掉的,这时容量与长度是相等的。

切片初始化

//var s []int
	//s = append(s, 1, 2, 3, 4, 5)
	//fmt.Println(s)

	//s := []int{8, 9, 7, 10, 12}
	//s = append(s, 99, 100)
	//s[0] = 78
	//fmt.Println(s)

	s := make([]int, 3, 10)
	s[0] = 10
	s[1] = 20
	s[2] = 30
	//s[4] = 80下标越界
	fmt.Println(s)
	s := make([]int, 3, 10)
	for i := 0; i < len(s); i++ {
		s[i] = i + 1
	}
	s = append(s, 80)
	fmt.Println(s)

切片截取

go语言基础--杂谈_第7张图片

s := []int{3, 5, 6, 7, 8, 9}
//第一个值:截取的起始位置
//第二个值:截取的终止位置(不包含该值的)
//第三个值:用来计算容量,容量值的是切片中最多能够容纳多少元素
//容量=第三个值减去第一个值
//长度=第二个值减去第一个值
//s1 := s[1:3:5]
//fmt.Println(s1) // 3 5 6
//fmt.Println(cap(s1))
//fmt.Println(len(s1))

//s1 := s[:]
//fmt.Println(s1)      //[3 5 6 7 8 9]
//fmt.Println(len(s1)) //6
//fmt.Println(cap(s1)) //6

//s1 := s[3:]
//fmt.Println(s1)      //[7 8 9]
//fmt.Println(len(s1)) //3
//fmt.Println(cap(s1)) //3

//s1 := s[:3]
//fmt.Println(s1)      //[3 5 6]
//fmt.Println(len(s1)) //3
//fmt.Println(cap(s1)) //6是切片s的容量

s1 := s[1:3]
fmt.Println(s1)      //[5 6]
fmt.Println(len(s1)) //2
fmt.Println(cap(s1)) //5

切片值的修改

切片截取后返回新切片,对新切片的值进行修改,会影响原切片吗?
会影响。

s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
s[0] = 30
fmt.Println(s) //[30 2 3 4 5 6 7 8 9 10]

s1 := s[2:5]
fmt.Println(s1) //[3 4 5]

s1[0] = 40
fmt.Println(s) //[30 2 40 4 5 6 7 8 9 10]
fmt.Println("s1 = ", s1) //s1 =  [40 4 5]

s1只是指向切片s

append函数的使用

一般扩容方式为上一次:容量*2, 如果超过1024字节 每次扩容上一次的1/4

s := make([]int, 5, 8) //len是5
fmt.Println(s)
fmt.Println(len(s)) //5
fmt.Println(cap(s)) //8

s = append(s, 1)
fmt.Println(s)
fmt.Println(len(s)) //6
fmt.Println(cap(s)) //8

s = append(s, 2)
fmt.Println(s)
fmt.Println(len(s)) //7
fmt.Println(cap(s)) //8

s = append(s, 3)
fmt.Println(s)
fmt.Println(len(s)) //8
fmt.Println(cap(s)) //8

s = append(s, 4)
fmt.Println(s)
fmt.Println(len(s)) //9
fmt.Println(cap(s)) //16

copy函数

copy(切片1,切片2)
注意事项:拷贝的长度为两个切片中长度较小的长度值。

s1 := []int{1, 2}
s2 := []int{3, 4, 5, 6, 7}
//copy(s1, s2)    //将s2拷贝到s1中去
//fmt.Println(s1) //[3 4] 拷贝是原有位置相同的两个值
copy(s2, s1)
fmt.Println(s2) //[1 2 5 6 7]

切片作为函数参数,切片是引用类型

func Init(num []int) {
	for i := 0; i < len(num); i++ {
		num[i] = i
	}
}
func main() {
	//s := []int{1, 2, 3, 4, 5}
	s := make([]int, 10)
	Init(s)
	fmt.Println(s) //[0 1 2 3 4 5 6 7 8 9]
}

冒泡排序

s := []int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}

var temp int
for i := 0; i < len(s)-1; i++ { //十个数比较9趟
	for j := 0; j < len(s)-1-i; j++ { //交换多少次
		if s[j] > s[j+1] {
			temp = s[j]
			s[j] = s[j+1]
			s[j+1] = temp
		}
	}
}
fmt.Println(s)

选择排序

//考虑第一趟的情况
//找出切片中最小的数据
//和切片中的第一个数进行位置交换
s := []int{5, 9, 0, 2, 7}
for j := 0; j < len(s)-1; j++ { //比较趟数
	min := s[j]   //假设最小
	minIndex := j //最小值的下标

	for i := j + 1; i < len(s); i++ {
		if min > s[i] {
			min = s[i]
			minIndex = i //记录一下下标
		}
	}
	if minIndex != j {
		s[j], s[minIndex] = s[minIndex], s[j]
	}
}

fmt.Println(s)

map概念

Go语言中的字典结构是有键和值构成的。
所谓的键,就类似于新华字典的部首或拼音,可以快速查询出对应的数据。
字典中的键是不允许重复的,就像身份证号一样
map 是一种无序的键值对的集合。
map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

map创建与初始化

var m map[int]string = map[int]string{1: "ziye", 2: "woai", 3: "ni"} //键不能重复
fmt.Println(m)                                                       //map[1:ziye 2:woai 3:ni]

m1 := map[int]string{1: "ziye", 2: "woai", 3: "ni"}
fmt.Println(m1) //map[1:ziye 2:woai 3:ni]
m2 := make(map[string]int)
fmt.Println(m2) //map[]

m3 := make(map[string]int, 10)
m3["ziye"] = 1
m3["lisi"] = 2
m3["wangwu"] = 3
fmt.Println(m3)      //map[lisi:2 wangwu:3 ziye:1]
fmt.Println(len(m3)) //0 返回的是map中已有的键值对个数
m3["ziye"] = 5
fmt.Println(m3) //map[lisi:2 wangwu:3 ziye:5] 完成数据的修改

map键与值

通过key获取值时,判断是否存在
变量1,变量2 := map名字[键]
如果键是存在的”变量1”中存储对应的值,并”变量2”的值为true,否则为false

 var m map[int]string = map[int]string{1: "王五", 2: "李四"}

	fmt.Println(m[2]) //李四

	value, ok := m[1]
	if ok {
		fmt.Println(value)
	} else {
		fmt.Println("不存在")
	}

通过for…range方式进行遍历

var m map[int]string = map[int]string{1: "王五", 2: "李四"}
	
	for key, value := range m {
		fmt.Println(key) //键
		fmt.Println(value) //值
	}

通过key删除某个值

delete(map名字,键)

var m map[int]string = map[int]string{1: "王五", 2: "李四"}
delete(m, 2)
fmt.Println(m)

map作为函数参数—引用类型

在函数中修改map的值,会影响到原map

func PrintMap(m map[int]string) {
	for key, value := range m {
		fmt.Println(key)
		fmt.Println(value)
	}
}

func DeleteMap(m map[int]string) {
	delete(m, 2)
}

func main() {
	var m map[int]string = map[int]string{1: "王五", 2: "李四"}
	fmt.Println(m)
	PrintMap(m)
	DeleteMap(m)
	fmt.Println(m) //map[1:王五]
	PrintMap(m)
}

结构体简介

通过定义变量的信息,进行存储,这种方式,比较麻烦,并且不利于数据的管理。
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
结构体可以很好地管理一批有联系的数据,使用结构体可以提高程序的易读性

结构体的创建与初始化

//成员名称前面不能添加var
	type Student struct {
		id   int
		name string
		age  int
		addr string
	}

	var s Student = Student{1, "ziye", 18, "bj"} //顺序初始化
	fmt.Println(s)                               //{1 ziye 18 bj}

	//部分初始化
	var s1 Student = Student{name: "ziye", age: 18}
	fmt.Println(s1) //{0 ziye 18 }

	//通过“结构体变量.成员” 完成初始化
	var stu Student
	stu.id = 102
	stu.name = "ziye"
	stu.age = 18
	stu.addr = "wh"
	fmt.Println(stu) //{102 ziye 18 wh}

结构体与数组

package main

import "fmt"

// Student 成员名称前面不能添加var
type Student struct {
	id   int
	name string
	age  int
	addr string
}

func main() {
	var arr [3]Student = [3]Student{
		{1, "ziye", 18, "bj"},
		{2, "ziye1", 18, "bj"},
		{3, "ziye2", 18, "bj"},
	}

	fmt.Println(arr) //[{1 ziye 18 bj} {2 ziye1 18 bj} {3 ziye2 18 bj}]

	fmt.Println(arr[0])     //{1 ziye 18 bj}
	fmt.Println(arr[0].age) //18
	arr[0].age = 20
	fmt.Println(arr)

	//通过循环来输出结构体数组的内容
	//for i := 0; i < len(arr); i++ {
	//	fmt.Println(arr[i])
	//}

	for key, value := range arr {
		fmt.Println(key)
		fmt.Println(value)
	}
}

结构体与切片

var s []Student = []Student{
		{1, "ziye", 18, "bj"},
		{2, "ziye1", 18, "bj"},
		{3, "ziye2", 18, "bj"},
	}

	//fmt.Println(s[0])
	//fmt.Println(s[0].age)
	//s[0].age = 20
	//fmt.Println(s)
	//
	循环遍历
	//for i := 0; i < len(s); i++ {
	//	fmt.Println(s[i].name)
	//}
	//
	//for key, value := range s {
	//	fmt.Println(key)
	//	fmt.Println(value.id)
	//}
	s = append(s, Student{19, "aaa", 18, "bj"})

	fmt.Println(s)

结构体与map

package main

import "fmt"

// Student 成员名称前面不能添加var
type Student struct {
	id   int
	name string
	age  int
	addr string
}

func main() {
	m := make(map[int]Student)
	m[1] = Student{1, "ziye", 18, "bj"}
	m[2] = Student{2, "ziye1", 18, "bj"}
	//fmt.Println(m)
	//fmt.Println(m[1].name)
	delete(m, 1)
	
	for key, value := range m {
		fmt.Println(key)
		fmt.Println(value.name)
	}
}

结构体作为函数的参数

在函数中修改结构体成员值,不会影响到原结构体—值传递

package main

import "fmt"

// Student 成员名称前面不能添加var
type Student struct {
	id   int
	name string
	age  int
	addr string
}

func PrintDemo(stu Student) {
	fmt.Println(stu)
	stu.age = 20
}

func main() {
	stu := Student{1, "ziye", 18, "bj"}
	PrintDemo(stu)
	fmt.Println(stu)

}

输出年龄最大的学生的详细信息

package main

import "fmt"

// Student 成员名称前面不能添加var
type Student struct {
	id   int
	name string
	age  int
	addr string
}

func InitData(stu []Student) {
	for i := 0; i < len(stu); i++ {
		fmt.Printf("请输入%d个学生的详细信息\n", i+1)
		fmt.Scan(&stu[i].id, &stu[i].name, &stu[i].age, &stu[i].addr)
	}
}

func GexMax(stu []Student) {
	var max int = stu[0].age
	var maxIndex int //记录最大年龄学生信息在整个切片中下标
	for i := 0; i < len(stu); i++ {
		if stu[i].age > max {
			max = stu[i].age
			maxIndex = i
		}
	}

	fmt.Println(stu[maxIndex])
}

func main() {
	stu := make([]Student, 3) //结构体切片
	InitData(stu)
	GexMax(stu)
}

指针简介

在函数中修改变量值,会影响到原有变量的值吗?

指针也是一个变量,但它是一种特殊的变量,因为它存储的数据不仅仅是一个普通的值,如简单的整数或字符串,而是另一个变量的内存地址

内存地址

go语言基础--杂谈_第8张图片

指针的定义

var 指针变量名 *类型

指针间接修改变量的值

指针变量 = 值

var a int = 10
var p *int
p = &a                 //拿到变量a的内存地址
fmt.Printf("%p\n", &a) //0xc00000a188
fmt.Printf("%p\n", p)  //0xc00000a188
fmt.Printf("%p\n", &p) //0xc000050038 ===>p的内存地址
fmt.Println(*p)        //根据地址取出相对应的值  10
*p = 222
fmt.Println(a) //222

指针操作注意事项

1:空接口

var p *int
fmt.Println(p) //nil

2:不要操作没有合法指向的内存

var p *int
*p = 78 // invalid memory address or nil pointer dereference
fmt.Println(p)

3:new 函数使用
开辟数据类型对应的内存空间 返回值为数据类型指针

var p *int
p = new(int) //开辟数据类型的内存空间
*p = 78
fmt.Println(p)
fmt.Println(*p)

指针变量作为函数参数

package main

import "fmt"

func main() {
	var num int = 10
	fmt.Println(num) //10
	Update(&num)
	fmt.Println(num) //60
}

func Update(num *int) {
	*num = 60
}

数组指针

var 数组指针变量 *[下标] 类型

package main

import "fmt"

func UpdateArr(p *[10]int) {
	p[0] = 100
}

func main() {
	nums := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	var p *[10]int //指针变量
	p = &nums
	//fmt.Println(p)
	//fmt.Println(*p)      //*p获取整个数组中的内容
	//fmt.Println((*p)[0]) //先算*p []运算优先级高于*
	//fmt.Println(p[0])    //简化了
	//
	//for i := 0; i < len(p); i++ {
	//	fmt.Printf("%d = ", p[i])
	//}

	UpdateArr(p)
	fmt.Println(*p) //会进行修改
}

指针数组

数组元素是指针类型
指针数组指的是一个数组中存储的都是指针(也就是地址)。也就是一个存储了地址的数组。
根据具体地址获取对应的值

  • 指针数组名[下标]
 	var p [2]*int //指针数组
	var i int = 10
	var j int = 20
	p[0] = &i
	p[1] = &j
	fmt.Println(p)     //[0xc00000a188 0xc00000a1a0]
	fmt.Println(*p[0]) //10 不要加[]
	fmt.Println(*p[1])

	//for i := 0; i < len(p); i++ {
	//	fmt.Println(*p[i])
	//}
	for key, value := range p {
		fmt.Println(key)    // 0 1
		fmt.Println(value)  //打印地址
		fmt.Println(*value) //取值
	}

指针与切片

定义指针,指向切片

s := []int{1, 2, 3, 4, 5, 6}

var p *[]int

p = &s //切片指针p指向了切片s
//fmt.Println(*p) //[1 2 3 4 5 6]
//fmt.Println(&p)
//fmt.Println((*p)[0])
//fmt.Println(&s[0]) //0xc00000e480
//fmt.Println(p[0]) 切片不支持这种写法
(*p)[0] = 200
//fmt.Println(s) //[200 2 3 4 5 6]
//
//for i := 0; i < len(*p); i++ {
//	fmt.Println((*p)[i])
//}
for key, value := range *p {
	fmt.Println("key = ", key)     //下标
	fmt.Println("vakue = ", value) //对应的值
}

指针与结构体

package main

import "fmt"

type Student struct {
	id   int
	name string
	age  int
}

func UpdateStudent(p *Student) {
	p.name = "ziyeye"
}

func main() {
	stu := Student{1, "ziye", 18}
	var p *Student
	p = &stu
	//fmt.Println(*p)
	//fmt.Println(p)
	//fmt.Println(&p) //0xc000050038
	//
	//fmt.Println((*p).name) //ziye
	//
	//fmt.Println(p.name) //ziye
	//
	//p.age = 20
	//
	//fmt.Println(stu) //{1 ziye 20}
	//fmt.Println(*p)
	UpdateStudent(p)
	fmt.Println(stu)
}

多级指针

var a int = 10
var p *int //一级指针
p = &a

var pp **int //二级指针 //可以用来保存一级指针的内存地址
pp = &p
**pp = 200

fmt.Println(a) //200

go语言基础--杂谈_第9张图片

深浅拷贝

浅拷贝:仅仅拷贝的是变量的值,没有对指向的空间进行任何的拷贝
深拷贝:将原有的变量的空间全部拷贝一份。
go语言中赋值,函数传参, 函数返回值都是浅拷贝。
go语言基础--杂谈_第10张图片
浅拷贝

package main

import "fmt"

func main() {
	var num int = 10
	ap := &num
	Update(ap)
	fmt.Println(num)
}
func Update(p *int) {
	*p = 60
}

函数中修改切片值影响原有切片原因分析

go语言基础--杂谈_第11张图片

package main

import "fmt"

func main() {
	s := make([]int, 5, 5)
	Modify(s)
	fmt.Println(s)
}
func Modify(sli []int) {
	for i := 0; i < 5; i++ {
		// sli[i] = i //这个是指向一个指针,这样会影响到原有切片
		sli = append(sli, i) //这样不会影响到原有的切片
	}
	fmt.Println("sli:",sli)

}

通讯录案例源码

package main

import "fmt"

func scanNum() {
	//1:给出相应的操作提示
	fmt.Println("添加联系人信息,请按1")
	fmt.Println("删除联系人信息,请按2")
	fmt.Println("查询联系人信息,请按3")
	fmt.Println("编辑联系人信息,请按4")

	//2:对用户输入的数字进行判断
	var num int //保存用户输入的数字

	_, _ = fmt.Scan(&num)

	switchType(num)
}

type person struct {
	userName     string
	addressPhone map[string]string //key 表示电话类型,value:电话
}

// 保存多个联系人的信息
var personList = make([]person, 0)

// 添加联系人
func addPerson() {
	//姓名,电话号码
	//定义结构体表示联系人的信息
	//定义切片保存多个人的联系信息

	var name string
	var address string
	var phone string
	var exit string                            //表示退出电话的录入
	var addressPhone = make(map[string]string) //保存电话的类型和电话,电话类型作为key
	//添加姓名
	fmt.Println("请输入姓名")
	_, _ = fmt.Scan(&name)

	for {
		//保存电话类型
		fmt.Println("请输入电话类型")
		_, _ = fmt.Scan(&address)
		//保存电话号码
		fmt.Println("请输入电话号码")
		_, _ = fmt.Scan(&phone)
		//将电话以及电话类型存储到addressPhone中
		addressPhone[address] = phone
		fmt.Println("如果结束电话的录入,请按Q")
		_, _ = fmt.Scan(&exit)
		if exit == "Q" {
			break
		} else {
			continue
		}
	}
	//将联系人的信息存储到切片中 //向切片中保存数据
	personList = append(personList, person{name, addressPhone})
	//fmt.Println(personList)
	showPersonList() //调用函数展示联系人的信息
}

// 删除联系人的操作
func deletePerson() {
	var name string

	index := -1 // 记录找到的联系人信息在切片中的下标
	//输入要删除的联系人的信息
	fmt.Println("输入要删除的联系人姓名")
	_, _ = fmt.Scan(&name)
	//判断切片是否存储了要删除的联系人的信息
	for i := 0; i < len(personList); i++ {
		if name == personList[i].userName {
			//记录要删除的联系人信息在切片中的位置(下标)
			index = i
			break
		}
	}
	//删除操作 	// index = 3  //   5,6,7,9,10,11,12
	if index != -1 {
		personList = append(personList[:index], personList[index+1:]...) //append 函数第二个参数如果是切片后面要给三个点
	}
	showPersonList()
}

// 查找联系人信息
func findPerson() *person {
	//1 输入要查询的联系人信息
	var name string
	index := -1 // 记录找到的联系人信息在切片中的下标
	fmt.Println("请输入要查询的联系人姓名:")
	_, _ = fmt.Scan(&name)
	//2 根据输入的联系人姓名,查找对应的联系信息
	for key, studentValue := range personList { //可以存在名字相同
		if studentValue.userName == name {
			index = key //从数据中取出下标
			fmt.Println("联系人姓名:", studentValue.userName)
			for PhoneType, Phone := range studentValue.addressPhone {
				fmt.Printf("%s:%s\n", PhoneType, Phone)
			}
			//break
		}
	}
	//3 打印输出结果
	if index == -1 {
		fmt.Println("没有找到联系人信息")
		return nil
	} else {
		return &personList[index]
	}
}

// 编辑联系人信息
func editPerson() {
	// 1:查找到要编辑的联系人信息
	var name string //存储新的联系人姓名
	var p *person
	p = findPerson()             //找到联系人地址
	var num int                  //存储修改数据的类型
	var menu = make([]string, 0) //保存电话类型,方便后面修改
	var pNum int                 // 编辑的电话类型编号
	var phone string             // 新的电话号码
	if p != nil {
		for {
			fmt.Println("编辑用户名称请按:5,编辑电话请按:6,退出请按:7")
			_, _ = fmt.Scan(&num)
			switch num {
			case 5:
				//修改联系人姓名
				fmt.Println("请输入新的姓名")
				_, _ = fmt.Scan(&name)
				p.userName = name
				showPersonList()
			case 6:
				//编辑联系电话
				//1:展示联系人所有的电话信息
				var j int
				for PhoneType, Phone := range p.addressPhone {
					fmt.Println("编辑(", PhoneType, ")", Phone, "请按: ", j)
					j++
					menu = append(menu, PhoneType)
				}
				fmt.Println("请输入编辑号码的类型")
				_, _ = fmt.Scan(&pNum)
				//2 完成修改
				for index, PhoneType := range menu {
					if index == pNum {
						fmt.Println("请输入新的电话号码")
						_, _ = fmt.Scan(&phone)
						p.addressPhone[PhoneType] = phone
					}
				}
			}
			if num == 7 {
				break
			}
		}

	} else {
		fmt.Println("没有找到要编辑的联系人信息")
	}
	// 进行编辑
}

// 展示切片中存储的联系人的信息
func showPersonList() {
	// 1 判断一下切片中是否有数据
	if len(personList) == 0 {
		fmt.Println("暂时没有联系人信息")
	} else {
		// 2 可以通过循环方式打印切片中的数据
		for _, value := range personList {
			fmt.Println("联系人姓名: ", value.userName)
			for address, phone := range value.addressPhone {
				fmt.Println("电话类型:", address)
				fmt.Println("电话号码", phone)
			}
		}
	}
}

// 对输入的内容进行判断,决定执行那块操作
func switchType(n int) {
	switch n {
	case 1:
		//添加联系人的操作
		addPerson()
	case 2:
		//删除联系人的操作
		deletePerson()
	case 3:
		//查询联系人的操作
		findPerson()
	case 4:
		//编辑联系人的操作
		editPerson()
	}
}

func main() {
	for {
		scanNum()
	}
}

你可能感兴趣的:(golang,java,服务器)