首页 > 其他 > 详细

关于go的疑问

时间:2020-05-28 17:47:17      阅读:55      评论:0      收藏:0      [点我收藏+]

这必然是一路风景

这一段在看go语言,也着实遇到了一些坑,所以此贴仅用于记录遇到的问题,后续会不停更新

1、go的时间time.sleep()其中的参数默认单位不是秒而是微秒 go中有专门的时间值time.Second/Minute/Hour...

2、channel的 make(chan int, arg)第二个参数定义channel buffer,默认是unbuffer,单线程使用的时候必须要定义,否则会被阻塞(unbuffer意思是只要我收到了,我就会阻塞在这个地方,等人来取,单线程就会直接报错了编不过,例子如下)https://www.jianshu.com/p/f12e1766c19f

func Ping(ping chan<- int, s int) {
	ping <- s
}

func Pong(ping <-chan int, pong chan<- int) {
	msg := <-ping
	pong <- msg
}

func ChannelDirect() {
	pi := make(chan int)          // 会报错当ping <- s的时候
	po := make(chan int)
	Ping(pi, 1)
	Pong(pi, po)
	fmt.Println(<-po)
}

3、fmt.printf("%T", arg) 判断arg的类型

4、channel synchronization 其实就是通过在goroutine里面放置channel的方式,保证goroutine中的代码运行完毕

func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    fmt.Println("done")

    done <- true
}

func main() {

    done := make(chan bool, 1)
    go worker(done)
    <-done                           // 这里阻塞直到goroutine运行完
}

5、goroutines leaking 永远不要在不知道它将如何停止的情况下启动一个goroutine,因为是并发的,所以会一直占用内存,其中一种情况就是channel没有设置buffer,则默认为阻塞的,如果channel阻塞且正好在goroutines中,则会造成此goroutine永远释放不了

6、数组和切片的区别:1.定义的时候数组必须定长度或者[...]让机器判定长度,切片则不用。多维数组只有第一层能使用[...]

7、数组传递的是值,是值类型,map和slice传递的是指针

8、切片是对底层数组的进一层封装,所以切片是由数组切来的时候,并不是复制了一份,而是直接的引用,改变数组的值会同时更改切片的值,切片的赋值也有相同效果,赋值的结果是复制了引用,底层数组是同一个

9、当切片append元素时,如果append后长度未超出cap长度,则依然适用上面的规则,如果append后超出了,则会复制一个新的底层数组重新指向,此时再更改上面的数组就不再影响slice

func ArraySlice() {
	new_array := [3]int{1, 3, 5}
	new_slice := new_array[:2]
	fmt.Println(new_slice)
	new_slice = append(new_slice, 9, 10)
	new_array[1] = 7
	fmt.Println(new_slice)
	fmt.Println(cap(new_slice))
}
stdout-->
[1 3]
[1 3 9 10]
6  // 原来是3

9、切片没有删除方法,可以append(slice[:index], slice[index+1:]...),删除掉index位置的元素就是从index+1开始append到index位置其实,注意第二个后面的三个点是go的语法糖,必须要加的,不然会直接append一个切片上去,其实就类似python的*args的*

10、切片是否为空必须要用len是否为0来判断,不能弄nil

11、new与make的区别:

  1. 二者都是用来做内存分配的。
  2. make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
  3. 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针

12、map是没有cap的,所以make(map, 111)第二个参数是没用的(目前暂时认为,不确定),map也是一个指向底层数据的指针,是引用类型

13、go的goroutine并发不是越多越好,因为协程是go的内部处理调度,绑定的是固定几个cpu的内核线程,所以当goroutine到达一定数量,cpu被一直满载占用,此时再创建协程运算效率就并不会有什么明显提升了,而go中协程的调度负荷反而会越来越重,有可能还会造成性能的下降(个人理解)

14、for index, stu := range stus {},这个时候index和stu是固定的内存空间,range的作用把stus解析后赋值给前面两个变量,前面两个变量的地址是不变的,所以在这里面尽量不要有关于前面两个变量的指针操作

15、go语言指针的使用需要声明后用new分配内存空间,struct的属性占用连续的内存空间,排列方法是属性内存和结构体内存的对齐,可以从这个方面优化大体积结构体

16、go语言的方法接收者用指针比较常见,struct是值类型,如果接收者是值类型则修改只在局部函数中生效,方法可以对任意本地类型生效,例如type MyInt int,那么给MyInt加一个方法完全可以

什么时候应该使用指针类型接收者
需要修改接收者中的值
接收者是拷贝代价比较大的大对象
保证一致性,如果有某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者。

17、go的继承通过结构体的嵌套实现,被嵌套的结构体是父类,结构体变量大写开头为公开,小写为私有(一定要注意,json.Marshal就不会读取私有的,如果是tag 小写是可以的例如`json:"name"`)

关于go的疑问

原文:https://www.cnblogs.com/seasen/p/12981788.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!