go基础2(代码片段)

骑着哈哥去旅行 骑着哈哥去旅行     2022-11-18     435

关键词:

目录

运算符

算术运算符

关系运算符

逻辑运算符

位运算符

赋值运算符

流程控制

if判断

if判断的特殊写法

for循环

死循环

for range 循环

练习

break和continue

switch case

goto(跳转到指定的标签)

(Array)数组

数组定义

数组的初始化

数组的遍历

多维数组

多维数组的遍历

数组是值类型

练习

(silce)切片

声明切片

make函数创建切片

切片的本质

切片不能直接比较

切片的切割

切片的遍历

切片的扩容(append )

copy函数

从切片中删除元素

练习

指针

new和make

new

make

new与make的区别


运算符

运算符用于在程序运行时执行数学或逻辑运算。

Go 语言内置的运算符有:

  1. 算术运算符

  2. 关系运算符

  3. 逻辑运算符

  4. 位运算符

  5. 赋值运算符

算术运算符

运算符描述
+相加
-相减
*相乘
/相除
%求余

注意: ++(自增)和--(自减)在Go语言中是单独的语句,并不是运算符。

package main

import "fmt"

func main() 
	a := 10
	b := 20

	fmt.Println(a + b)
	fmt.Println(a - b)
	fmt.Println(a * b)
	fmt.Println(a / b)
	fmt.Println(a % b)


30
-10
200
0
10

关系运算符

运算符描述
==检查两个值是否相等,如果相等返回 True 否则返回 False。
!=检查两个值是否不相等,如果不相等返回 True 否则返回 False。
>检查左边值是否大于右边值,如果是返回 True 否则返回 False。
>=检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。
<检查左边值是否小于右边值,如果是返回 True 否则返回 False。
<=检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。
package main

import "fmt"

func main() 
	a := 10
	b := 20
	fmt.Println(a == b) // false
	fmt.Println(a <= b) // true
	fmt.Println(a >= b) // false
	fmt.Println(a != b) // true
	fmt.Println(a > b)  // false
	fmt.Println(a < b)  // true


false
true
false
true
false
true

逻辑运算符

运算符描述
&&逻辑 and 运算符。 如果两边的操作数都是 True,则为 True,否则为 False。
||逻辑 or 运算符。 如果两边的操作数有一个 True,则为 True,否则为 False。
!逻辑 not 运算符。 如果条件为 True,则为 False,否则为 True。
package main

import "fmt"

func main() 
	a := 10
	b := 20

	fmt.Println(a < b && a == b) // false
	fmt.Println(a < b || a == b) // true
	fmt.Println(!(a > b))        // true


false
true
true

位运算符

运算符描述
&参与运算的两数各对应的二进位相与。 (两位均为1才为1)
|参与运算的两数各对应的二进位相或。 (两位有一个为1就为1)
^参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (两位不一样则为1)
<<左移n位就是乘以2的n次方。 “a<<b”是把a的各二进位全部左移b位,高位丢弃,低位补0。
>>右移n位就是除以2的n次方。 “a>>b”是把a的各二进位全部右移b位。
package main

import "fmt"

func main() 
	a := 2 // 010
	b := 3 // 011

	fmt.Println(a & b) // 010 --> 2(上下对应位置都是1就是1)
	fmt.Println(a | b) // 011 --> 3(上下对应位置只要有一个1就是1)
	fmt.Println(a ^ b) // 001 --> 1(上下对应位置只要不相等就是1)

	fmt.Println(a << b) // a*2^b --> 2*2^3 --> 16
	fmt.Println(a >> b) // a/2^b --> 2/2^3 --> 0.25


2
3
1
16
0

赋值运算符

运算符描述
=简单的赋值运算符,将一个表达式的值赋给一个左值
+=相加后再赋值
-=相减后再赋值
*=相乘后再赋值
/=相除后再赋值
%=求余后再赋值
<<=左移后赋值
>>=右移后赋值
&=按位与后赋值
|=按位或后赋值
^=按位异或后赋值
package main

import "fmt"

func main() 
	var a1 int
	a1 = 5 // 赋值运算符
	fmt.Println(a1)

	a1++ // a1+1
	fmt.Println(a1)

	a1-- // a1-1
	fmt.Println(a1)

	a1 += 5 // 相加之后再赋值
	fmt.Println(a1)

	a1 -= 3 // 相减之后再赋值
	fmt.Println(a1)

	a1 *= 2 // 相乘后再赋值
	fmt.Println(a1)

	a1 /= 3 // 相除后再赋值
	fmt.Println(a1)

	a1 %= 3 // 求余后再赋值
	fmt.Println(a1)


5
6
5
10
7
14
4
1

流程控制

流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,Go语言中最常用的流程控制有iffor,而switchgoto主要是为了简化代码、降低重复代码而生的结构,属于扩展类的流程控制。

if判断

if 表达式1 
    分支1
 else if 表达式2 
    分支2
 else
    分支3
package main

import "fmt"

func main() 
	age := 19
	if age > 18 
		fmt.Println("你已经成年了!")
	 else 
		fmt.Println("你还没有成年!")
	

	if age > 35 
		fmt.Println("人到中年了")
	 else if age > 18 
		fmt.Println("年轻就是好")
	 else 
		fmt.Println("好好学习,天天上当")
	


你已经成年了!
年轻就是好

Go语言规定与if匹配的左括号必须与if和表达式放在同一行,放在其他位置会触发编译错误。 同理,与else匹配的也必须与else写在同一行,else也必须与上一个ifelse if右边的大括号在同一行。

if判断的特殊写法

if条件判断还有一种特殊的写法,可以在 if 表达式之前添加一个执行语句,再根据变量值进行判断,举个例子:

func ifDemo2() 
	if score := 65; score >= 90 
		fmt.Println("A") 
	 else if score > 75 
		fmt.Println("B")
	 else 
		fmt.Println("C")
	

for循环

Go 语言中的所有循环类型均可以使用for关键字来完成。

for循环的基本格式如下:

for 初始语句;条件表达式;结束语句
    循环体语句

条件表达式返回true时循环体不停地进行循环,直到条件表达式返回false时自动退出循环。

package main

import "fmt"

func main() 
	for i := 0; i <= 10; i++ 
		fmt.Println(i)
	


0
1
2
3
4
5
6
7
8
9
10

for循环的初始语句可以被忽略,但是初始语句后的分号必须要写,例如:

package main

import "fmt"

func main() 
	num1 := 5
	for ; num1 <= 10; num1++ 
		fmt.Println(num1)
	


5
6
7
8
9

for循环的初始语句和结束语句都可以省略,例如:

package main

import "fmt"

func main() 

	/*num1 := 5
	for ; num1 < 10; num1++ 
		fmt.Println(num1)
	 */

	num1 := 5
	for num1 < 10 
		fmt.Println(num1)
		num1++
	



5
6
7
8
9

这种写法类似于其他编程语言中的while,在while后添加一个条件表达式,满足条件表达式时持续循环,否则结束循环。

死循环

注意:Go语言性能比较优异,切记不可操作此循环(了解即可),否则可能导致电脑卡死或蓝屏。

for 
    循环体语句

for循环可以通过breakgotoreturnpanic语句强制退出循环。

for range 循环

Go语言中可以使用for range遍历数组、切片、字符串、map 及通道(channel)。 通过for range遍历的返回值有以下规律:

  1. 数组、切片、字符串返回索引和值。

  2. map返回键和值。

  3. 通道(channel)只返回通道内的值。

package main

import "fmt"

func main() 
	name := "Hello Go语言"
	for index, value := range name 
		fmt.Printf("%d-%c\\n", index, value)
	


0-H
1-e
2-l
3-l
4-o
5- 
6-G
7-o
8-语
11-言

练习

  1. 九九乘法表
package main

import "fmt"

func main() 
	for i := 1; i <= 9; i++ 
		for j := 1; j <= i; j++ 
			fmt.Printf("%d*%d=%d\\t", j, i, i*j)
		
		fmt.Printf("\\n")
	


1*1=1	
1*2=2	2*2=4	
1*3=3	2*3=6	3*3=9	
1*4=4	2*4=8	3*4=12	4*4=16	
1*5=5	2*5=10	3*5=15	4*5=20	5*5=25	
1*6=6	2*6=12	3*6=18	4*6=24	5*6=30	6*6=36	
1*7=7	2*7=14	3*7=21	4*7=28	5*7=35	6*7=42	7*7=49	
1*8=8	2*8=16	3*8=24	4*8=32	5*8=40	6*8=48	7*8=56	8*8=64	
1*9=9	2*9=18	3*9=27	4*9=36	5*9=45	6*9=54	7*9=63	8*9=72	9*9=81	

break和continue

break为结束循环,continue为跳过本次循环继续执行下一次循环。

package main

import "fmt"

func main() 

	// 当i=5时结束当前循环
	/* for i := 0; i <= 10; i++ 
		if i == 5 
			break
		 else 
			fmt.Println(i)
		
	
	fmt.Println("Over!!!") */

	// 当i=5时跳过本次循环
	for i := 0; i <= 10; i++ 
		if i == 5 
			continue
		 else 
			fmt.Println(i)
		
	
	fmt.Println("Over!!!")


0
1
2
3
4
6
7
8
9
10
Over!!!

switch case

使用switch语句可方便地对大量的值进行条件判断。

package main

import "fmt"

func main() 
	num1 := 3
	switch num1 
	case 1:
		fmt.Println("张三")
	case 2:
		fmt.Println("李四")
	case 3:
		fmt.Println("王五")
	case 4:
		fmt.Println("赵六")
	case 5:
		fmt.Println("小七")
	default:
		fmt.Println("无效输入!!!")
	


王五

一个分支可以有多个值,多个case值中间使用英文逗号分隔。

package main

import "fmt"

func main() 
	switch num2 := 3; num2 
	case 1, 3, 5, 7, 9:
		fmt.Println("这是奇数")
	case 2, 4, 6, 8, 10:
		fmt.Println("这是偶数")
	default:
		fmt.Println(num2)
	


这是奇数

分支还可以使用表达式,这时候switch语句后面不需要再跟判断变量。例如:

package main

import "fmt"

func main() 
	age := -3
	switch 
	case age <= 18 && age > 0:
		fmt.Println("好好学习吧")
	case age <= 35 && age > 18:
		fmt.Println("好好赚钱奥")
	case age > 35:
		fmt.Println("还是身体重要!!!")
	default:
		fmt.Println("无效的输入")
	


无效的输入

goto(跳转到指定的标签)

goto语句通过标签进行代码间的无条件跳转。goto语句可以在快速跳出循环、避免重复退出上有一定的帮助。Go语言中使用goto语句能简化一些代码的实现过程。 例如双层嵌套的for循环要退出时:

package main

import "fmt"

func main() 
	var breakTag bool  // 初始化标志
	for i := 0; i < 10; i++ 
		for j := 0; j <= i; j++ 
			if j == 5 
				breakTag = true
			 else 
				fmt.Println(i, j)
			
		
		if breakTag 
			break
		
	

使用goto语句能简化代码:

package main

import "fmt"

func main() 
	for i := 0; i <= 10; i++ 
		for j := 1; j <= i; j++ 
			if j == 5 
				goto breakTag // 设置结束标志
			
			fmt.Print(j)
		
		fmt.Print("\\n")
	
	// 结束
breakTag:
	fmt.Println("循环已经结束")


1
12
123
1234
1234循环已经结束

(Array)数组

数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。基本语法如下:

package main

import "fmt"

func main() 
	var arr1 [3]bool
	fmt.Printf("%T\\n", arr1)
	fmt.Println(arr1)


[3]bool
[false false false]

注意:Go语言中数组的长度就是数组类型的一部分!!!

数组定义

var 数组的名字 [数组的数量]数组的类型

var arr [4]int

比如:var arr1 [5]int, 数组的长度必须是常量,并且长度是数组类型的一部分。一旦定义,长度不能变。 [5]int[10]int是不同的类型。

数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1,访问越界(下标在合法范围之外),则触发访问越界,会报错。

package main

import "fmt"

func main() 
	var arr1 [3]bool
	fmt.Println(arr1[5])


# command-line-arguments
day3\\数组.go:7:19: invalid argument: array index 5 out of bounds [0:3]

数组的初始化

如果不初始化,默认的元素都是零值(布尔值:false;整型和浮点型:0;字符串:"")。

方式1:

package main

import "fmt"

var name = [3]string"老王", "胖子", "大胖子"

func main() 
    fmt.Println(name)
    
    arr1 := [3]booltrue, true, false
	fmt.Println(arr1)


[老王 胖子 大胖子]
[true true false]

方式2:

根据初始值的个数自行推断数组的长度,例如:

package main

import "fmt"

func main() 
	// 方式1
    /* arr1 := [3]booltrue, true, false
	fmt.Println(arr1) */

	// 方式2
    arr2 := [...]string"hpl", "xxx", "aaa", "laowang"
	fmt.Println(arr2)


[hpl xxx aaa laowang]

方式3:

使用指定索引值的方式来初始化数组,例如:

package main

import "fmt"

func main() 
	// 方式1
    /* arr1 := [3]booltrue, true, false
	fmt.Println(arr1) */

	// 方式2
    /* arr2 := [...]string"hpl", "xxx", "aaa", "laowang"
	fmt.Println(arr2) */

	// 方式3
    arr3 := [5]int1: 2, 4: 666
	fmt.Println(arr3)


[0 2 0 0 666]

数组的遍历

数组的遍历有两种方式:

package main

import "fmt"

func main() 
    address := [...]string"西安", "北京", "汉中", "洛阳"

	// 方式1
	for i := 0; i < len(address); i++ 
		fmt.Println(address[i])
	

	fmt.Println("---------------------")

	// 方式2
	for index, value := range address 
		fmt.Println(index, value)
	


西安
北京
汉中
洛阳
---------------------
0 西安
1 北京
2 汉中
3 洛阳

多维数组

Go语言是支持多维数组的,我们这里以二维数组为例(数组中又嵌套数组)。

package main

import "fmt"

func main() 
	// 多维数组
    arr1 := [...][3]int1, 2, 3, 4, 5, 6, 7, 8, 9
	fmt.Println(arr1)



[[1 2 3] [4 5 6] [7 8 9]]

多维数组的遍历

package main

import "fmt"

func main() 
	// 多维数组
    arr1 := [...][3]int1, 2, 3, 4, 5, 6, 7, 8, 9
	// fmt.Println(arr1)

	// 二维数组的遍历
	for i := 0; i < len(arr1); i++ 
		for j := 0; j < len(arr1[i]); j++ 
			fmt.Printf("%d ", arr1[i][j])
		
		fmt.Print("\\n")
	



1 2 3 
4 5 6 
7 8 9 

注意: 多维数组只有第一层可以使用[...]来让编译器推导数组长度。例如:

//支持的写法
arr1 := [...][2]string
	"北京", "上海",
	"广州", "深圳",
	"成都", "重庆",

//不支持多维数组的内层使用[...]
arr2 := [3][...]string
	"北京", "上海",
	"广州", "深圳",
	"成都", "重庆",

数组是值类型

数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值。

package main

import "fmt"

func main() 
	arr4 := [...]int2, 5, 8
	arr5 := arr4
	arr5[1] = 666
	fmt.Println(arr4, arr5)
	fmt.Println(arr4 == arr5)
	fmt.Println(arr4 != arr5)



[2 5 8] [2 666 8]
false
true

练习

1.求数组[1, 3, 5, 7, 8]所有元素的和

package main

import "fmt"

func main() 
	arr1 := [...]int1, 3, 5, 7, 8
	var count int
	for _, value := range arr1 
		count += value
	
	fmt.Println("数组arr1的元素之和为:", count)


数组arr1的元素之和为: 24

2.找出数组中和为指定值的两个元素的下标,比如从数组[1, 3, 5, 7, 8]中找出和为8的两个元素的下标分别为(0,3)和(1,2)。

package main

import "fmt"

func main() 
	arr1 := [...]int1, 3, 5, 7, 8
		for i, v := range arr1 
		for j := i + 1; j < len(arr1); j++ 
			if v+arr1[j] == 8 
				fmt.Printf("(%d %d)\\n", i, j)
			
		
	


(0 3)
(1 2)

(silce)切片

切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。

切片是一个引用类型,它的内部结构包含地址长度容量。切片一般用于快速地操作一块数据集合。

声明切片

package main

func main() 
	var s []int
package main

import "fmt"

func main() 
	s1 := []int1, 3, 5
	s2 := []string"西安", "北京", "上海"
	fmt.Println(s1, s2)
	fmt.Println(s1 == nil) // nil表示空的意思


[1 3 5] [西安 北京 上海]
false

切片拥有自己的长度容量,我们可以通过使用内置的len()函数求长度,使用内置的cap()函数求切片的容量。

容量:切片的容量就是底层数组第一个元素到最后一个元素。

package main

import "fmt"

func main() 
	// 切片的长度和容量
	s3 := []string"西安", "北京", "上海"
	fmt.Println("切片的长度是:", len(s3), "切片的容量是:", cap(s3))


切片的长度是: 3 切片的容量是: 3
package main

import "fmt"

func main() 
	arr1 := []int1, 5, 7, 8, 9, 30, 50, 77, 666
	s1 := arr1[1:4]
	s2 := arr1[:3]
	s3 := arr1[3:]
	s4 := arr1[:]
	arr1[3] = 999
	fmt.Println(s1, len(s1), cap(s1))
	fmt.Println(s2, len(s2), cap(s2))
	fmt.Println(s3, len(s3), cap(s3))
	fmt.Println(s4, len(s4), cap(s4))


[5 7 999] 3 8
[1 5 7] 3 9
[999 9 30 50 77 666] 6 6
[1 5 7 999 9 30 50 77 666] 9 9

make函数创建切片

我们上面都是基于数组来创建的切片,如果需要动态的创建一个切片,我们就需要使用内置的make()函数,格式如下:

make([]T, size, cap)
  • T:切片的元素类型

  • size:切片中元素的数量

  • cap:切片的容量

package main

import "fmt"

func main() 
	// 使用make函数创建切片
	s1 := make([]int, 5, 10) // 类型、长度、容量(容量若不写,默认等于长度的值)
	fmt.Println(s1, len(s1), cap(s1))


[0 0 0 0 0] 5 10

上面代码中s1的内部存储空间已经分配了10个,但实际上只用了5个。 容量并不会影响当前元素的个数,所以len(s1)返回5,cap(s1)则返回该切片的容量10。

切片的本质

切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)

切片不能直接比较

切片之间是不能比较的,我们不能使用==操作符来判断两个切片是否含有全部相等元素。 切片唯一合法的比较操作是和nil比较。 一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0。但是我们不能说一个长度和容量都是0的切片一定是nil

package main

import "fmt"

func main() 
    var s1 []int
	s2 := make([]int, 0, 0)
	fmt.Println(s2, len(s2), cap(s2))
	fmt.Println(s1 == nil, s2 == nil)


[] 0 0
true false

所以要判断一个切片是否是空的,要是用len(s2) == 0来判断,不应该使用s2 == nil来判断

切片的切割

切割前后两个变量共享底层数组,对一个切片的修改会影响另一个切片的内容。

package main

import "fmt"

func main() 
	a1 := []int23, 45, 12, 66, 77, 99
	s3 := a1[2:]
	s4 := a1[:4]
	a1[3] = 6666
	fmt.Println(a1, s3, s4)


[23 45 12 6666 77 99] [12 6666 77 99] [23 45 12 6666]

切片的遍历

package main

import "fmt"

func main() 
	a1 := []int23, 45, 12, 66, 77, 99
	s3 := a1[:]
	a1[3] = 6666

	// 方式1
	for i := 0; i < len(s3); i++ 
		fmt.Println(s3[i])
	

	fmt.Println()

	// 方式2
	for index, value := range s3 
		fmt.Println(index, value)
	


23
45
12
6666
77
99

0 23
1 45
2 12
3 6666
4 77
5 99

切片的扩容(append )

package main

import "fmt"

func main() 
	s1 := []string"阿拉斯加", "哈士奇", "萨摩耶", "大黄", "小黑"
	s1 = append(s1, "老王")       // 调用append函数必须使用原来的变量进行接收
	s1 = append(s1, "老张", "老李") // 调用append函数必须使用原来的变量进行接收

	s2 := []string"王大审", "张大妈", "李大坡"
	s1 = append(s1, s2...) // ...在Go表示打散,类似于python中的*

	fmt.Println(s1)


[阿拉斯加 哈士奇 萨摩耶 大黄 小黑 老王 老张 老李 王大审 张大妈 李大坡]

注意:调用append函数建议使用原来的变量进行接收

提示:...在Go表示打散,类似于python中的

copy函数

Go语言内建的copy()函数可以迅速地将一个切片的数据复制到另外一个切片空间中,copy()函数的使用格式如下:

 copy(destSlice, srcSlice []T)
  • srcSlice: 数据来源切片

  • destSlice: 目标切片

package main

import "fmt"

func main() 
	s1 := []string"阿拉斯加", "哈士奇", "萨摩耶", "大黄", "小黑"
	s2 := make([]string, 5, 10)
	copy(s2, s1) // 将切片s1中的元素复制到s2中
	fmt.Println(s1)
	fmt.Println(s2)

	s1[1] = "哈哥"
	fmt.Println(s1)
	fmt.Println(s2)


[阿拉斯加 哈士奇 萨摩耶 大黄 小黑]
[阿拉斯加 哈士奇 萨摩耶 大黄 小黑]
[阿拉斯加 哈哥 萨摩耶 大黄 小黑]
[阿拉斯加 哈士奇 萨摩耶 大黄 小黑]

从切片中删除元素

Go语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。

package main

import "fmt"

func main() 
	// 从切片中删除元素
	arr1 := [...]int1, 2, 3, 4, 5, 6, 7 // 数组
	s1 := arr1[:]                         // 切片
	// 要删除的元素索引为2
	s1 = append(s1[:2], s1[3:]...)
	fmt.Println(arr1) // append会修改底层的数组
	fmt.Println(s1)



[1 2 4 5 6 7 7]
[1 2 4 5 6 7]

注意:append会修改底层的数组。

总结:要从切片a中删除索引为index的元素,操作方法是a = append(a[:index], a[index+1:]...

练习

1.写出下面代码的结果

package main

import (
	"fmt"
)

func main() 
	var a = make([]int, 5, 10)
	fmt.Println(a)
	for i := 0; i < 10; i++ 
		a = append(a, i)
	
	fmt.Println(a)



[0 0 0 0 0]
[0 0 0 0 0 0 1 2 3 4 5 6 7 8 9]
package main

import (
	"fmt"
)

func main() 
	var a = make([]string, 5, 10)
	fmt.Println(a)
	for i := 0; i < 10; i++ 
		a = append(a, fmt.Sprintf("%v", i))
	
	fmt.Println(a)



[    ]
[     0 1 2 3 4 5 6 7 8 9]

2.使用内置的sort包对数组var a = [...]int3, 7, 8, 9, 1进行排序

package main

import (
	"fmt"
	"sort"
)

func main() 
	s6 := []int3, 7, 8, 9, 1
	sort.Ints(s6)
	fmt.Println(s6)



[1 3 7 8 9]

指针

任何程序数据载入内存后,在内存都有他们的地址,这就是指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。

比如,“我喜欢你”这句话,我想把它写入程序中,程序一启动这句话是要加载到内存(假设内存地址0x123456),我在程序中把这段话赋值给变量A,把内存地址赋值给变量B。这时候变量B就是一个指针变量。通过变量A和变量B都能找到“我喜欢你”这句话。

Go语言中的指针不能进行偏移和运算,因此Go语言中的指针操作非常简单,我们只需要记住两个符号:&(取地址)和*(根据地址取值)。

package main

import (
	"fmt"
	"reflect"
)

func main() 
	n := 18
	p := &n // &符号表示取地址
	fmt.Println(n)
	fmt.Println(p, reflect.TypeOf(p)) //  *int表示int类型的指针

	m := *p //  *表示根据地址取值
	fmt.Println(m)


18
0xc0000aa058 *int
18

总结: 取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

  • 对变量进行取地址(&)操作,可以获得这个变量的指针变量。

  • 指针变量的值是指针地址。

  • 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。

new和make

new

使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。

package main

import (
	"fmt"
)

func main() 
	// var a *int // a表示一个int类型的空指针
	a := new(int) // 表示给a开辟内存空间
	*a = 666      // 根据a的内存地址给a赋值
	fmt.Println(*a)
	fmt.Println(&a)


666
0xc000006028

开始的代码中var a *int只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。应该按照如下方式使用内置的new函数对a进行初始化之后就可以正常对其赋值了

make

make也是用于内存分配的,区别于new,它只用于slice、map以及channel的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

new与make的区别

  1. 二者都是用来做内存分配的。

  2. make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;

  3. 而new用于值类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

go基础2(代码片段)

目录运算符算术运算符关系运算符逻辑运算符位运算符赋值运算符流程控制if判断if判断的特殊写法for循环死循环forrange循环练习break和continueswitchcasegoto(跳转到指定的标签)(Array)数组数组定义数组的初始化数组的遍历多... 查看详情

go基础2(代码片段)

目录运算符算术运算符关系运算符逻辑运算符位运算符赋值运算符流程控制if判断if判断的特殊写法for循环死循环forrange循环练习break和continueswitchcasegoto(跳转到指定的标签)(Array)数组数组定义数组的初始化数组的遍历多... 查看详情

go语言基础(代码片段)

一简介1定义Go是一种开源的程序设计语言,它意在使得人们能够方便地构建简单,可靠,高效的软件。2产生原因1计算机硬件技术更新频繁,性能提高很快,目前主流编程语言发展落后,不能合理利用多核CPU优势来提高系统性能2... 查看详情

go语法基础文档(代码片段)

go语法基础文档一:变量和作用域1.变量声明2.并行或同时赋值(两个变量的类型必须是相同)3.空白标识符(抛弃值)_二:常量1.显示定义2.隐式类型定义3.多个常量的声明4.枚举5.常量函数表达式(函数必须是内置函数:... 查看详情

go语言学习基础-编译文件(代码片段)

1、创建工程在go的src目录下,比如我的go目录为/Users/yinxin/go,我创建文件夹test路径为/Users/yinxin/go/src/test;2、创建文件main.go,输入如下代码,并保存。packagemainimport("fmt""time")functests(secondint,Manint,Falmanint)ifsecond%Falman==0fmt.Pr 查看详情

go语言入门指南零基础入门go语言|golang入门指南(代码片段)

...`https://github.com/CocaineCong/Golang-Learning`1.【第一轮】基础部分1.1教程1.2练习2.【第二轮】网络爬虫2.1教程2.2mod管理第三方包2.3git机制3.【第三轮】备忘录4.【第四轮】商城or视频网站5.【第五轮】IM即时通信6.【第六轮】微服务7.... 查看详情

go语言入门指南零基础入门go语言|golang入门指南(代码片段)

...`https://github.com/CocaineCong/Golang-Learning`1.【第一轮】基础部分1.1教程1.2练习2.【第二轮】网络爬虫2.1教程2.2mod管理第三方包2.3git机制3.【第三轮】备忘录4.【第四轮】商城or视频网站5.【第五轮】IM即时通信6.【第六轮】微服务7.... 查看详情

go语言学习记录2——基础语法包变量函数(代码片段)

一.包1.1包在Go语言里,一个文件就是一个包(如果我没理解错的话)。Go语言会从packagemain开始运行。按照约定,包名与导入路径的最后一个元素一致。例如,“math/rand”包中的源码均以packagerand语句开始。也... 查看详情

go语言基础(代码片段)

一运算符1运算符基础1算法:解决问题的过程,运算符和表达式来串联数据和指令。算数运算符赋值运算符比较运算符逻辑运算符位运算符其他相关运算符2算数运算符1简介算术运算符是对数值类型的变量进行运算的,如加减乘除... 查看详情

go基础之单元测试反射网络编程操作redis操作mysql(代码片段)

Go基础(四)之单元测试、反射、网络编程、操作Redis、操作MySQL一、单元测试二、反射2.1两个重要函数和类型2.2类型(Type)与种类(Kind)2.3通过反射获取值信息2.3.1从反射值对象获取值2.3.2通过反射访问结... 查看详情

go基础系列:go接口(代码片段)

接口用法简介接口(interface)是一种类型,用来定义行为(方法)。typeNamerinterfacemy_method1()my_method2(para)my_method3(para)return_type...但这些行为不会在接口上直接实现,而是需要用户自定义的方法来实现。所以,在上面的Namer接口类型中的... 查看详情

go基础之函数方法接口包(代码片段)

Go基础(二)之函数、方法、接口、包一、函数1.1函数参数1.2返回值1.3匿名函数1.4延迟处理defer1.5错误处理1.6内置函数1.7常用的相关函数二、方法2.1方法简介2.2通过方法封装三、接口3.1接口简介3.2类型转换四、包的基本概... 查看详情

go基础之程序结构数据类型(代码片段)

Go基础(一)之程序结构、数据类型一、简介1.1Go语言的介绍1.2环境配置1.3快速入门1.4Go开发的注意事项二、程序结构2.1标识符2.2变量2.3常量2.4运算符2.5流程控制2.7init函数三、数据类型3.1基本数据类型3.1.1整型3.1.2浮点型3.1... 查看详情

go基础之程序结构数据类型(代码片段)

Go基础(一)之程序结构、数据类型一、简介1.1Go语言的介绍1.2环境配置1.3快速入门1.4Go开发的注意事项二、程序结构2.1标识符2.2变量2.3常量2.4运算符2.5流程控制2.7init函数三、数据类型3.1基本数据类型3.1.1整型3.1.2浮点型3.1... 查看详情

go基础初识go语言(代码片段)

文章目录1.开发环境搭建2.第一个Go程序3.Go命令介绍1.开发环境搭建在https://studygolang.com/dl上下载需要的Go稳定版本,这里我选择的是17.5的版本对于Windows和macOS用户,直接双击即可安装,留意一下安装路径;对于Linux... 查看详情

go语言基础实例(代码片段)

一:变量1)变量声明funcmain()varv1intvarv2int//一次声明多个变量var(v3intv4int)//变量最开始会有一个零值fmt.Println(v1,v2,v3,v4)打印效果:2)变量初始化packagemainimport("fmt""reflect")funcmain()//1直接初始化并指定数据类型varv1int=10//2直接初始化v... 查看详情

go语言学习笔记—基础—高级数据类型—数据容器—数组:数组截取(代码片段)

简称“前闭后开”a[开始索引(包含):结束索引(不包含)]a:=[...]int1,2,3,4,5a[1:2]//2a[1:3]//2,3a[1:len(a)]//2,3,4,5a[1:]//2,3,4,5a[:3]//1,2,3数组截取之后,就变成slice了。vara=[5]int1,2,3,4,5varb=a[1:3] 查看详情

go基础语法-指针(代码片段)

1.基础定义golang的指针没有cpp等语言的指针复杂,具体表现在其不可用于运算、只有值传递语法:varvariableName*int=memoryAddrvara=2varp*int=&ap=p+1//编译器会报错:invalidoperation:...2.指针类型转换golang中不同类型的指针间不能相互转换... 查看详情