Go语言学习 day20

golang遍历map是有序还是无序,为什么?

无序,因为go的map基于哈希表,可以实现快速插入和查找,不保证顺序。会根据key的哈希值来决定存放kv对的哈希桶的索引,对key的哈希值的计算没有固定顺序。

定义一个局部变量,默认是分配到堆上还是栈上,什么情况是堆上?

默认在栈上。
分配到堆上的话,靠go的逃逸分析机制,编译器用逃逸分析,如果一个变量生存周期大于函数作用域,就是堆上,或者被外部引用(局部变量作为返回值)。

逃逸分析在什么阶段完成?

编译阶段。

sync包的once实现原理?

sync包中的一个结构体,确保某个操作被执行一次,无论多少个协程并发调用Once.Do方法,其中的操作只执行一次。
once结构体主要包含int用原子操作表示操作是否正在执行。互斥锁保证协程间的并发。

package sync

import (
    "sync/atomic"
)

type Once struct {
    done uint32
    m    Mutex
}

Do方法
如果int值==0,表示操作没有执行,当前协程可以利用doSlow函数执行f。==1代表执行完了,直接返回即可。

func (o *Once) Do(f func()) {
    if atomic.LoadUint32(&o.done) == 0 {
        // Outlined slow-path to allow inlining of the fast-path.
        o.doSlow(f)
    }
}

doSlow函数
对函数的执行用锁加固,执行完将int值设为1。

func (o *Once) doSlow(f func()) {
    o.m.Lock()
    defer o.m.Unlock()
    if o.done == 0 {
        defer atomic.StoreUint32(&o.done, 1)
        f()
    }
}

在一个package可以定义多个init方法吗,执行顺序是怎样的?

Go语言的一个包中,可以定义多个init方法,这些init方法可以在不同的源文件中。
init函数:
没有参数和返回值,不能被显式调用,Go运行时系统调用的。
主要用于包被导入时,执行一些初始化操作。
init函数执行顺序:
同一个源文件的多个init函数:按照声明顺序执行
不同源文件的init函数:源文件的编译顺序执行函数
不同包下的init函数:导入顺序,main包是最后

我们常用的排序算法当中冒泡排序是稳定的吗?

冒泡排序:重复的比对每对相邻的元素,如果顺序出错就调整他们。
步骤:从前两个开始,放置正确的顺序,遍历到最后,最大的在最后。
重复从头遍历,到到数第二个停止。
直到没有元素需要调整。
稳定性:在排序过程中,如果两个元素值相等,他们的相对顺序在排序后不变,就是稳定的。

插入排序稳定吗?

插入排序:将需要排序数组划分为已排序和未排序两种。它通过遍历数组,将每个元素 arr[i] 与其前面已排序部分的元素进行比较,找到合适的位置插入。
步骤:1.初始第一个为已排序,后面的为未排序,将遍历未排序的部分,将元素插到已排序中的位置。
稳定性:插入排序是稳定的,如果遇到当前元素与之前元素相等,就放到之前元素的后面,相对顺序保证了。

你可能感兴趣的:(Go语言基础,golang,学习,算法)