go基础语法50问,来看看你的go基础合格了吗?( 六 )


注意:并不是立刻把旧的数组中的元素转义到新的 bucket 当中,而是,只有当访问到具体的某个 bucket 的时候,会把 bucket 中的数据转移到新的 bucket 中 。
45. JSON 标准库对 nil slice 和 空 slice 的处理是一致的吗首先 JSON 标准库对 nil slice 和 空 slice 的处理是不一致 。
通常错误的用法 , 会报数组越界的错误 , 因为只是声明了slice,却没有给实例化的对象 。
var slice []intslice[1] = 0此时slice的值是nil,这种情况可以用于需要返回slice的函数,当函数出现异常的时候 , 保证函数依然会有nil的返回值 。
empty slice 是指slice不为nil , 但是slice没有值,slice的底层的空间是空的,此时的定义如下:
slice := make([]int,0)slice := []int{}当我们查询或者处理一个空的列表的时候,这非常有用,它会告诉我们返回的是一个列表,但是列表内没有任何值 。总之,nil slice 和 empty slice是不同的东西,需要我们加以区分的 。
46.Golang的内存模型,为什么小对象多了会造成gc压力通常小对象过多会导致 GC 三色法消耗过多的GPU 。优化思路是,减少对象分配 。
47.Data Race问题怎么解决?能不能不加锁解决这个问题同步访问共享数据是处理数据竞争的一种有效的方法 。
golang在 1.1 之后引入了竞争检测机制 , 可以使用 go run -race 或者 go build -race来进行静态检测 。其在内部的实现是,开启多个协程执行同一个命令, 并且记录下每个变量的状态 。
竞争检测器基于C/C++的ThreadSanitizer 运行时库,该库在Google内部代码基地和Chromium找到许多错误 。这个技术在2012年九月集成到Go中,从那时开始,它已经在标准库中检测到42个竞争条件 。现在,它已经是我们持续构建过程的一部分,当竞争条件出现时,它会继续捕捉到这些错误 。
竞争检测器已经完全集成到Go工具链中 , 仅仅添加-race标志到命令行就使用了检测器 。
$ go test -race mypkg// 测试包$ go run -race mysrc.go// 编译和运行程序 $ go build -race mycmd// 构建程序 $ go install -race mypkg // 安装程序要想解决数据竞争的问题可以使用互斥锁sync.Mutex,解决数据竞争(Data race),也可以使用管道解决,使用管道的效率要比互斥锁高 。
48.在 range 迭代 slice 时,你怎么修改值的在 range 迭代中,得到的值其实是元素的一份值拷贝,更新拷贝并不会更改原来的元素,即是拷贝的地址并不是原有元素的地址 。
func main() { data := []int{1, 2, 3} for _, v := range data {v *= 10// data 中原有元素是不会被修改的 } fmt.Println("data: ", data) // data:[1 2 3]}如果要修改原有元素的值,应该使用索引直接访问 。
func main() { data := []int{1, 2, 3} for i, v := range data {data[i] = v * 10 } fmt.Println("data: ", data) // data:[10 20 30]}如果你的集合保存的是指向值的指针,需稍作修改 。依旧需要使用索引访问元素,不过可以使用 range 出来的元素直接更新原有值 。
func main() { data := []*struct{ num int }{{1}, {2}, {3},} for _, v := range data {v.num *= 10 // 直接使用指针更新 } fmt.Println(data[0], data[1], data[2]) // &{10} &{20} &{30}}49.nil interface 和 nil interface 的区别虽然 interface 看起来像指针类型,但它不是 。interface 类型的变量只有在类型和值均为 nil 时才为 nil如果你的 interface 变量的值是跟随其他变量变化的,与 nil 比较相等时小心 。如果你的函数返回值类型是 interface,更要小心这个坑:
func main() {var data *bytevar in interface{}fmt.Println(data, data =https://www.huyubaike.com/biancheng/= nil) // truefmt.Println(in, in == nil) // truein = datafmt.Println(in, in == nil) // false // data 值为 nil,但 in 值不为 nil}// 正确示例func main() {doIt := func(arg int) interface{} {var result *struct{} = nilif arg > 0 {result = &struct{}{}} else {return nil // 明确指明返回 nil}return result}if res := doIt(-1); res != nil {fmt.Println("Good result: ", res)} else {fmt.Println("Bad result: ", res) // Bad result: <nil>}}50.select可以用于什么常用于goroutine的完美退出 。
golang 的 select 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作每个case语句里必须是一个IO操作,确切的说,应该是一个面向channel的IO操作 。
参考资料:公众号:晨梦思雨

推荐阅读