其他分享
首页 > 其他分享> > Golang基础-2

Golang基础-2

作者:互联网

Golang基础2

指针

如果声明变量var x int ,则&x是获取x值所在的地址,类型是整型指针(*int),即我们可以声明一个变量来接收其返回值

var p *int=&x

那么p就是一个指针变量

		age:=18
		// 这里是输出i变量对应的地址通过&+名字获取
		fmt.Println(&age)

image-20220826192254508

image-20220826193110085

这里我们要得到通过ptr指针获得age具体值我们可以用*ptr,*ptr和age是等价的,*ptr一改变age的值也会改变

		age:=18
		p:=&age
		fmt.Printf("age的值为%d",age)
		fmt.Println()
		*p=22
		fmt.Printf("age的值为%d",age)

image-20220826193842144

指针属于复杂数据类型,其零值为nil

两个指针都指向同一个变量或者都为nil时才相等

如果一个方法的返回值是一个指针,则每次调用该方法返回的值都不同

如上例子我们可以称*p是age的别名(别名可以有多个)

标识(zhi)符

image-20220826195424614

image-20220826200513782

main包是我们程序的入口,main方法所在的包取名为main包才能完成编译

利用标识符的首字母大小写实现权限的控制

image-20220826201807925

运算符

image-20220826201930948

注意:go语言中只有v++、v--没有++v,--v,且只能单独使用不能参与运算

image-20220826211946507

获取用户终端输入

image-20220830142939242

image-20220830142956467

func main(){

 var age byte

fmt.Println("请录入学生的年龄:")

// 该方法传入已有变量的地址,在Scanln函数中对地址的值进行改变后,原变量的值也发生改变

// 录入数据的时候如果与传入的变量类型不匹配是不能录入成功的

fmt.Scanln(&age)

fmt.Printf("学生的年龄是:%d",age)

}

image-20220830144740186

第二种方式需要指定录入的格式

image-20220830145930292

这里我在书上看到了第三种方式

	//开启输入流
	reader := bufio.NewReader(os.Stdin)
//从键盘输入的值存入input,错误信息出入err
		input, err := reader.ReadString('\n')

流程控制

分支

if单分支

image-20220830150729823

在go语言里,if后面可以并列的加入变量的定义,如

if count:=20;count<30{
fmt.Println("库存不足")
}

if双分支

image-20220830151417144

if多分支

即java中的else if 只是要注意格式每个else必须跟在}后面

image-20220830151738459

switch分支

基本和java中一模一样

其余的情况同样用:

default:
	...........

image-20220830152103871

image-20220830152345723

这里有一些特殊的

即:

go语言中case后可以有多个表达式或者值,用逗号隔开就行了

case后面不用加break

default的位置随意,也不是必须的

switch后面可以不写表达式,当成是if来使用(一般不推荐使用)

image-20220830153324864

switch后可以直接定义一个变量(以分号进行结尾)

switch b:=7;{
	case b>6 :
		fmt.Println("大于6")
		fallthrough
	case b<=6 :
		fmt.Println("小于等于6")
}

go语言中可以手动穿透一个case

如下两个语句都会输出

switch b:=7;{
	case b>6 :
		fmt.Println("大于6")
		fallthrough
	case b<=6 :
		fmt.Println("小于等于6")
}

image-20220830154214779

循环

在go语言中只有for循环,格式如下

和java中基本一样

for guesses := 5; guesses > 0; guesses-- {
		要循环执行的代码块
		}
var sum int=0
for i:=1;i<=5;i++{
	sum+=i
}

细节:

格式灵活

image-20220830155248489

死循环直接

for{
.........
}
或者
for ;;{
.........
}

for range

是go语言特有的迭代结构,可以用于遍历数组,切片,字符串,map以及通道,语法上类似于java中的foreach

//key接受当前索引,val接受索引对应的值,coll为要遍历的变量名
for key,val:=range coll{
....
}

以下以遍历字符串为例子

	var str string="hello golang你好"
	for i:=0;i<len(str);i++{
		fmt.Printf("%c",str[i])
		fmt.Println()
	}

image-20220830172159817

普通的for循环是以字节为单位遍历的,而一个汉字对应了三个字节所以会出现乱码

但是如果我们使用for range遍历就不会出现这种情况

	for i,value:=range str{
		fmt.Printf("索引为:%d,具体值为:%c",i,value)
		fmt.Println()
	}

image-20220830172526017

关键字

break

用与跳出循环体(多重循环情况跳出离他最近的循环)

可以通过加标签的方式跳出指定的循环

image-20220830173745242

如上程序会直接跳出外层循环

continue

结束本次循环(continue下面的代码不再执行),开始下一次

goto(不建议使用)

无条件跳到程序指定行(通过lable实现)

return

除了在函数中返回值,还可用与结束函数

函数

image-20220830174836204

以下通过实现一个求两数和的函数来说明

func sum(num1 int,num2 int) (int){

 var s int = 0

 s+=num1

 s+=num2

 return s

}

func main(){

 e:=sum(10,5)

 fmt.Printf("和为:%d",e)



}

image-20220830195612291

image-20220830195726246

如果没有返回值,那么返回值列表什么都不写就可以了

如果返回值只有一个那么返回值类型列表的括号可以不写

return返回多个参数时,用逗号隔开

内存分析

以下代码说明方法调用后即销毁对应的栈空间

image-20220830201837545

image-20220830201939282

可变参数例子:

func test(args...int){
    //函数内部处理可变参数的时候,将可变参数当做切片来处理
    //遍历可变参数
    for i:=0;i<len(args);i++{
        fmt.Println(args[i])
    }
    //也可以使用for range
    for i,value:=range args{
        fmt.Println(value)
    }
}

image-20220831093040919

注意在go语言中基本类型和数组作为参数时都是值传递,即在函数内部改变其值不会改变原数据

image-20220831093620258

要想通过函数直接改变变量的值,可以将函数的参数改成指针类型,传入变量的地址

image-20220831093955571

image-20220831094223437

image-20220831094333052

10:

image-20220831094740850

11:

image-20220831095106686

自定义类型相当于起别名

image-20220831095655797

对函数的类型起别名后,可以方便函数当作参数传入的情况

image-20220831095934347

一般我们不给返回值命名的时候要严格按照类型的顺序返回,明明后不用手动返回其顺序了

image-20220831100418722

之前我们试过导包,首先要

go env -w GO111MODULE=off  或者  go env -w GO111MODULE=auto

这样程序才能先去GOPATH环境变量中找路径,才能识别你导入的自己的包在哪

还有就是因为golang语言中不存在方法的重载所以同名的函数我们写在不同的包中完成不同的功能

image-20220902145713113

每个程序的第一句

package xxx 是进行包的声明,理论上包的名字和文件夹的名字一致

main包是程序的入口包,一般main函数放在main包下

注意函数或变量首字母大写才能被其他包访问

image-20220902151807517

如果有多个包一次性导入

import(
	"fmt"
	"gocode/testProject01/test"
)

包名和文件夹名字可以不一样

一个文件夹下的程序必须属于同一个包才行

可以在引入包的时候给包起别名,但是起了别名就只能使用别名调用包中的函数或变量,再用包名就无效了

image-20220902153403575

image-20220902153417399

image-20220902153533023

init函数

image-20220902153822138

2:

image-20220902154146097

3:

会先执行导入的包中的init函数

再按顺序执行自身包下的内容(顺序见上面第二点)

image-20220902154813807

image-20220902154859372

image-20220902155050765

匿名函数

只用一次的情况多用匿名函数

image-20220902155537136

其中定义的时候调用使用的最多

image-20220902160050873

闭包

闭包是一个函数和与其相关的引用环境组合的一个整体

案例:

image-20220902161234180

根据以上例子的运行结果可以发现匿名函数中引用的那个变量会一致保存在内存中,可以一直使用

image-20220902161646122

以上例子不使用闭包的情况可以考虑全局变量的使用

package main
import "fmt"
import a "gocode/testProject01/test"
var sum int=0

func main(){

	fmt.Println("------------")
	a.Smile()
	fmt.Println(getSum(1))
	fmt.Println(getSum(2))
	fmt.Println(getSum(3))
	fmt.Println("------------")


}
func getSum(num int) int{
	sum+=num
	return sum
}

defer关键字

为了在函数执行完毕之后,及时的释放资源,go的设计者提供defer关键字

在golang中,程序遇到defer关键字,不会立即执行defer后的语句,而是将defer后的语句压入到一个栈中(先进后出),然后继续执行后面非defer修饰的语句,在函数执行完毕之后,取出栈中的语句开始执行

image-20220902163404296

在存入栈之后对变量的改变不会影响栈中语句的结果

应用场景:

当你想关闭某个使用的资源,你在使用的时候就用defer修饰,因为defer有延迟执行机制(函数执行完毕再执行defer压入栈的语句),执行完压入语句,压入语句使用的资源会被释放

标签:函数,int,fmt,基础,Golang,go,Println,age
来源: https://www.cnblogs.com/qwerty-wy/p/16652073.html