go语言基础

Go 是一种轻量级的线程 由go关键字启动
和系统级线程的区别在于:
系统级线程都会有一个固定大小的栈(一般默认为2MB),这个栈主要用来存储函数递归时的参数和局部变量。导致在运行过程中存在两个问题:1、对于只需要很小的栈空间的线程是一个巨大的浪费;2、对于少量需要大量栈空间的线程又面临栈溢出的风险。
解决方案:1、降低固定栈大小,提升空间的利用率 2、增大栈的大小以允许更深的函数递归调用。
在golang中 一个goroutine会以一个很小的栈启动(可能是2KB或4KB),当遇到深度递归导致当前栈空间不足时,goroutine会根据需要动态的伸缩栈的大小(主流实现中栈的最大值可达到1GB)。由于goroutine启动的代价很小,所以我们可以轻易地启动成千上万个goroutine

go调度器可以在n个操作系统中多工调度m个协程。协程采用地是半抢占式的协作调度,只有在当前协程发生阻塞时 才会导致调度;同时调度发生在用户态,调度器根据具体函数只保存必要的寄存器,切换所使用的资源是轻量级的。
运行时通过指定runtime.GOMAXPROCS变量,用于控制当前运行正常非阻塞的协程的系统协程数目

执行go build value.go编译生成可执行文件value 执行./value即可调用程序
直接执行go run value.go不会编译,直接运行出结果
在这里插入图片描述
定义变量

package main
import (
	"fmt"
)
func main() {
	var v1 uint        //   定义为无符号uint类型 默认为0
	var x, y = 123, "hello"    // 定义多个参数,根据=后值确定变量类型
	u, t := 456, "world"        //直接使用:=定义变量
	fmt.Println(v1, x, y, u, t)
	var c1 complex64 = 3 + 4i     //定义复数
	fmt.Println(c1)
}

定义常量

package main
import (
	"fmt"
)
func main() {
	const l int = 10     // 通过const关键字定义常量  定义常量规则 可指定常量类型
	const w = 5    //直接赋值  不用指定变量类型
	const a, b, c = 1, false, "01"      //一次定义多个常量
	fmt.Println(a, b, c)
	area := l * w           //定义变量
	fmt.Println(area)
}

定义遍历迭代 ioat
ioat在每个const关键词内从0开始迭代递增

package main
import (
	"fmt"
)
const (
	a = iota + 1      //ioat=0
	b                      //b是go中声明const时的缩略写法,表示值和它前面表达式等号右边的值是一样的,完整写法是 b=ioat+1      ioat=1
	c = iota + 1      // ioat=2
	d = iota          //ioat=3   
)
const (
	e, f = iota + 1, iota + 2     //ioat=0
	g, h           //表示go语言的省略模式 值与前面表达式保持一致   ioat=1
	i, j             //go语言的省略写法  值与前面表达式保持一致  ioat=2
)
func main() {
	fmt.Println(a, b, c, d)
	fmt.Println(e, f, g, h, i, j)
}

在这里插入图片描述
go语言的指针
共有两种指针运算符,一种是取地址运算符 &,一种是间接寻址运算符 *。

package main
import (
	"fmt"
)
func main() {
	a := 10
	var b *int = &a   //b指向a的内存地址
	fmt.Println(*b, b)  //输出b内存地址的值
	*b = 100//b寻址地址的值重新赋值
	fmt.Println(*b, b, a)
}

在这里插入图片描述

1、 可以赋值成nil的变量类型有7种:1)任意类型的指针变量,2)函数变量,3)接口,4)error,5)map, 6)切片 7)通道。这些变量默认值就是nil,实际上都不用赋值成nil。
2、切片赋值时,最后一个元素后面如果有逗号则“}”可以换行或者不换行,否则”}“必须和最后一个元素保持在同一行。
3、数组切片新增元素 append追加另一个切片时需要加"…" 或者copy函数
4、Go目前只支持后置自增自减运算符,而且不能用于赋值或者作为参数传递给函数。
5、panic异常:空指针解析、下表越界、除数为0、调用panic函数
6、panic执行流程:
再正常流程中,调用recover异常捕获函数始终返回nil。
在异常流程中,出现 panic情况时,将会体哦那个之执行后续的普通语句。之前注册的defer函数仍然保证会被执行。
如果另起一个协程触发panic时,main函数里在协程之前注册的defer延迟函数不会被执行
如果当前defer函数是由之前的panic触发的并且当前defer函数会触发新的panic,则前一个panic停止执行
7、golang 中的类型比如:channel(通道)、complex(复数类型)、func(函数)均不能进行 JSON 格式化。
8、Gostub可以对全局变量、函数、过程打桩,可以打动态桩(对一个函数打桩后,多次调用函数会有不同的行为)
9、for循环遍历下的go协程的输出
1,golang是值拷贝传递;2,for循环很快就执行完了,但是创建的协程需要做初始化:上下文准备,堆栈,和内核态的线程映射关系的工作,是需要时间的,比for慢,等都准备好了的时候,会同时访问变量 。这个时候的变量肯定是for执行完成后的。所以协程都打印t最终的变量。解决方案为:闭包,给匿名函数增加入参,因为是值传递,所以每次for创建一个协程的时候,会拷贝一份变量传到这个协程里面去,这样就可以实现切片数组的打印了。修改后的代码和实验结果也在下面。
在这里插入图片描述
10 defer执行
1 执行在非函数环境下defer 关键字,作用和栈一样,先进后出
2 执行在函数环境下时 defer func(){}(),defer作用在函数返回前,函数内部赋值语句赋值后
在这里插入图片描述
3 defer 关键字同于函数的连续执行时,之后延迟最后一次函数的调用
在这里插入图片描述
如果想要连续函数的延迟 调用defer func(){}()函数在这里插入图片描述
10 golang调用C代码的方式可以通过cgo或者是swig,而cgo是不能使用C++相关的东西的,比如标准库或者C++的面向对象特性。怎么办,将c++的功能函数封装成C接口,然后编译成动态库,或者是功能较为简单的可以直接嵌入到go源文件中
11 golang中根据首字母的大小写来确定可以访问的权限。无论是方法名、常量、变量名还是结构体的名称
如果首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用
12 goto关键字,用来改变函数内代码的执行顺序,跳转到函数内指定的标签地方运行,goto不能跨函数代码块跳转
在这里插入图片描述
13 switch 语句后不需要加条件判断,支持多条件匹配,使用逗号分隔,例如:case val1,val2,val3。
不同的case之间不使用break分隔,默认自带break,只会执行一个case;
如果想要执行多个case,需要使用fallthrought关键字,且不会判断下一个case的表达式是否 为true;也可以使用break终止
14 go 的 := 赋值符初始化声明变量,它只能被用在函数体内,而不可以用于全局变量的声明与赋值
15 golang中大多数数据类型都可以转化为有效的JSON文本,除了channel、complex、函数等。在golang指针中可进行隐式转换,对指针取值,对所指对象进行序列化
16 在设计函数异常返回值的时候,如果函数异常值只有一个,则返回bool类型。如果异常值超过一个,则返回error。没有失败原因,则不返回bool或error。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值