Golang基础-2
作者:互联网
Golang基础2
指针
如果声明变量var x int ,则&x是获取x值所在的地址,类型是整型指针(*int),即我们可以声明一个变量来接收其返回值
var p *int=&x
那么p就是一个指针变量
age:=18
// 这里是输出i变量对应的地址通过&+名字获取
fmt.Println(&age)
这里我们要得到通过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)
指针属于复杂数据类型,其零值为nil
两个指针都指向同一个变量或者都为nil时才相等
如果一个方法的返回值是一个指针,则每次调用该方法返回的值都不同
如上例子我们可以称*p是age的别名(别名可以有多个)
标识(zhi)符
main包是我们程序的入口,main方法所在的包取名为main包才能完成编译
利用标识符的首字母大小写实现权限的控制
运算符
注意:go语言中只有v++、v--没有++v,--v,且只能单独使用不能参与运算
获取用户终端输入
func main(){
var age byte
fmt.Println("请录入学生的年龄:")
// 该方法传入已有变量的地址,在Scanln函数中对地址的值进行改变后,原变量的值也发生改变
// 录入数据的时候如果与传入的变量类型不匹配是不能录入成功的
fmt.Scanln(&age)
fmt.Printf("学生的年龄是:%d",age)
}
第二种方式需要指定录入的格式
这里我在书上看到了第三种方式
//开启输入流
reader := bufio.NewReader(os.Stdin)
//从键盘输入的值存入input,错误信息出入err
input, err := reader.ReadString('\n')
流程控制
分支
if单分支
在go语言里,if后面可以并列的加入变量的定义,如
if count:=20;count<30{
fmt.Println("库存不足")
}
if双分支
if多分支
即java中的else if 只是要注意格式每个else必须跟在}后面
switch分支
基本和java中一模一样
其余的情况同样用:
default:
...........
这里有一些特殊的
即:
go语言中case后可以有多个表达式或者值,用逗号隔开就行了
case后面不用加break
default的位置随意,也不是必须的
switch后面可以不写表达式,当成是if来使用(一般不推荐使用)
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")
}
循环
在go语言中只有for循环,格式如下
和java中基本一样
for guesses := 5; guesses > 0; guesses-- {
要循环执行的代码块
}
var sum int=0
for i:=1;i<=5;i++{
sum+=i
}
细节:
格式灵活
死循环直接
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()
}
普通的for循环是以字节为单位遍历的,而一个汉字对应了三个字节所以会出现乱码
但是如果我们使用for range遍历就不会出现这种情况
for i,value:=range str{
fmt.Printf("索引为:%d,具体值为:%c",i,value)
fmt.Println()
}
关键字
break
用与跳出循环体(多重循环情况跳出离他最近的循环)
可以通过加标签的方式跳出指定的循环
如上程序会直接跳出外层循环
continue
结束本次循环(continue下面的代码不再执行),开始下一次
goto(不建议使用)
无条件跳到程序指定行(通过lable实现)
return
除了在函数中返回值,还可用与结束函数
函数
以下通过实现一个求两数和的函数来说明
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)
}
如果没有返回值,那么返回值列表什么都不写就可以了
如果返回值只有一个那么返回值类型列表的括号可以不写
return返回多个参数时,用逗号隔开
内存分析
以下代码说明方法调用后即销毁对应的栈空间
可变参数例子:
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)
}
}
注意在go语言中基本类型和数组作为参数时都是值传递,即在函数内部改变其值不会改变原数据
要想通过函数直接改变变量的值,可以将函数的参数改成指针类型,传入变量的地址
10:
11:
自定义类型相当于起别名
对函数的类型起别名后,可以方便函数当作参数传入的情况
一般我们不给返回值命名的时候要严格按照类型的顺序返回,明明后不用手动返回其顺序了
包
之前我们试过导包,首先要
go env -w GO111MODULE=off 或者 go env -w GO111MODULE=auto
这样程序才能先去GOPATH环境变量中找路径,才能识别你导入的自己的包在哪
还有就是因为golang语言中不存在方法的重载所以同名的函数我们写在不同的包中完成不同的功能
每个程序的第一句
package xxx 是进行包的声明,理论上包的名字和文件夹的名字一致
main包是程序的入口包,一般main函数放在main包下
注意函数或变量首字母大写才能被其他包访问
如果有多个包一次性导入
import(
"fmt"
"gocode/testProject01/test"
)
包名和文件夹名字可以不一样
一个文件夹下的程序必须属于同一个包才行
可以在引入包的时候给包起别名,但是起了别名就只能使用别名调用包中的函数或变量,再用包名就无效了
init函数
2:
3:
会先执行导入的包中的init函数
再按顺序执行自身包下的内容(顺序见上面第二点)
匿名函数
只用一次的情况多用匿名函数
其中定义的时候调用使用的最多
闭包
闭包是一个函数和与其相关的引用环境组合的一个整体
案例:
根据以上例子的运行结果可以发现匿名函数中引用的那个变量会一致保存在内存中,可以一直使用
以上例子不使用闭包的情况可以考虑全局变量的使用
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修饰的语句,在函数执行完毕之后,取出栈中的语句开始执行
在存入栈之后对变量的改变不会影响栈中语句的结果
应用场景:
当你想关闭某个使用的资源,你在使用的时候就用defer修饰,因为defer有延迟执行机制(函数执行完毕再执行defer压入栈的语句),执行完压入语句,压入语句使用的资源会被释放
标签:函数,int,fmt,基础,Golang,go,Println,age 来源: https://www.cnblogs.com/qwerty-wy/p/16652073.html