前言

最近在整理之前写程序,学习时所记录的有道云笔记,发现一些有意思的小点跟大家分享一下。如有错误请大家给指出

一、闭包 defer

闭包(匿名函数)

func test(){
i, n := ,;
defer func(a int){
fmt.Println("defer:", a , n); //n被闭包引用
}(i) //复制i的值
i , n = i+,n+;
fmt.Println(i , n);
}

我们看一下结果:

2 4
defer: 1 4

为什么会这样?是因为闭包复制的是原对象指针,出现了延迟引用现象 (加上defer的延迟调用,正好可以解释上面程序的延迟引用现象)。我们在使用闭包的时候要注意这个问题,同样在for 循环中 也会出现类似现象。

感谢“”小强”,增加一个闭包的例子,期望能给大家带来更多的理解

func b(){
i := []int{1,2,3,4}
for _,n := range i {
go func(){
fmt.Println(n); // n 被闭包引用,引用n的内存地址
// 协程G 实际上执行的是匿名函数对象 FuncVal { func_address, closure_var_pointer ... }
}();
fmt.Println(n);
}
time.Sleep(1*time.Second); }

  

 程序有一定的不确定性 ,但是输出结果反映了内存引用现象

1
2
3
4
4
4
4
4

二、Map

前一段时间在论坛看到一个问题

type Data struct{
AABB [2]float64
} var m map[string]Data = make(map[string]Data,1) m["xxx"] = Data{} m["xxx"].AABB[0]=1.0
m["xxx"].AABB[1]=2.0
#以上代码go build 通不过,错误提示cannot assign to m["xxx"].AABB[0]

这是一个网友给出的答案

type Data struct{
AABB [2]float64
} m := make(map[string]*Data,1)
m["xxxx"] = &Data{}
m["xxxx"].AABB[0] = 1.0
m["xxxx"].AABB[1] = 2.0
#这样写就对了,你的 m["xxxx"] 返回的是值,不是一个可取地址的变量

这个网友的答案可以编译成功,但是不可取,他犯了很多新手都容易出现的问题

why?Golang中的map元素属性被设计为只读的,并不期望被修改,并且从 map 中取回的是一个value也是临时复制品。并且map是一个hash 结构,当hash扩容时,键值的存储位置就会发生改变。如果这个时候我们对 m["xxxx"].AABB[0] = 1.0 修改,不知道指针会发什么。大家有兴趣可以看看Go Hashmap内存布局和实现

如果我们想修改最好这样

type Data struct{
AABB [2]float64
} m := make(map[string]*Data,1)
m["xxxx"] = Data{}
d := m["xxxx"]
d.AABB[0] = 1.0
d.AABB[1] = 2.0
m["xxxx"] = d

三、nil

先看一段代码,当然这种场景不常见,但是能让我们更好的理解nil

func t(){
var i *int = nil;
var n interface{} = i;
fmt.Println(n==nil); //false
}

可能很多小伙伴都会有疑问都是nil 为啥会不相等。我们先分别看一下pointer,interface的结构体和当pointer,interface为nil时的结构

uintptr
type interfaceStruct struct {
  v *_value // 实际值
  t *_type // 实际值的类型信息
}
uintptr(0) == nil
type interfaceStruct struct {
  v:uintptr(0)
  t:uintptr(0)
} == nil

  

由此我们可以看出nil其实就是指针 interface的零值

这时候我们在来解释为啥为flase就很容易了

func t(){
var i *int = nil; // (*int)nil
var n interface{} = i; // interace{}((*int)nil)
fmt.Println(n==nil); // type interfaceStruct struct {
                 // v: uintptr(0),
                 // t: (*int)
                 // }
}

  

官方文档规定可以为nil的类型还有 slice ,map ,channel ,function 。

可能有些朋友可能会问为啥没有error类型,那是因为error 只是程序预设的接口方法, err nil 也会出现类似的问题,官方有一个文档也给出了解释,传送门

type error interface {
Error() string
}  

感谢阅读,欢迎提供建议

golang关于一些新手不注意会出现的小问题的更多相关文章

  1. python新手如何编写一个猜数字小游戏

    此文章只针对新手,希望大家勿喷,感谢!话不多说先上代码: import random if __name__ == '__main__': yourname = input("你好! 你的名 ...

  2. 【新手向】自用的tooltip小插件,前端插件知识科普~

    上面的tooltip就是成品图,为了和自己站点的风格保持一致所以自己写的. 第一部分:你绝对碰到过的匿名函数闭包问题 第二部分:写个tooltip demo 第三部分:源码地址 第一部分 你绝对碰到过 ...

  3. Android入门-新手如何成功创建一个Android小应用

    原文:http://android.eoe.cn/topic/summary 第一课程:Building Your First App [本课内容简介]欢迎加入到安卓应用的开发大潮中!这门课程会教授你 ...

  4. 领域驱动(DDD)之我见,基于Golang实现

    分享一点不成熟的理解,还请本着交流进步的大原则喷之.从去年开始接触和套用DDD以来,已经有1年多时间了.也先后在2个生产项目中主导应用. 一.一些概念 DDD经典分层: 分层架构的一个重要原则是:每层 ...

  5. Golang 效率初(粗)测

    从接触 Golang 开始,断断续续已有差不多一年左右的时间了,都是业余自己学学看看,尚主要限于语法及语言特性,还没有用它写过实际的项目. 关于 Golang 的语法及语言特性,网上有很多资源可以学习 ...

  6. 微信小程序常见问题1----适合新手

    1.本地调试 1)微信小程序填坑之路之使用localhost在本地测试 2)本地代理创建:微信小程序之使用本地接口开发 2.页面跳转 1)页面跳转 2)小程序之间跳转 3.小程序尺寸 1)微信小程序尺 ...

  7. Golang核心编程

    源码地址: https://github.com/mikeygithub/GoCode 第1章 1Golang 的学习方向 Go 语言,我们可以简单的写成 Golang 1.2Golang 的应用领域 ...

  8. Golang入门(2):一天学完GO的基本语法

    摘要 在配置好环境之后,要研究的就是这个语言的语法了.在这篇文章中,作者希望可以简单的介绍一下Golang的各种语法,并与C和Java作一些简单的对比以加深记忆.因为这篇文章只是入门Golang的第二 ...

  9. 换人!golang面试官:连怎么避免内存逃逸都不知道?

    问题 怎么避免内存逃逸? 怎么答 在runtime/stubs.go:133有个函数叫noescape.noescape可以在逃逸分析中隐藏一个指针.让这个指针在逃逸分析中不会被检测为逃逸. // n ...

随机推荐

  1. C++函数返回值(02)

    对象作为返回值 编译器会将函数栈中的返回值数据拷贝到返回栈中 指针作为返回值 函数的返回值可以是存储某种类型数据的内存地址,称这种函数为指针函数.它们的一般定义形式如下:  类型标识符 *函数名(参数 ...

  2. Java基础笔记5

    方法(函数) 就是一块可以重复调用的代码块. 比如.100行代码. 在多处使用. 方法的格式 public static 返回类型 方法名称(参数列表){ } 返回类型:当方法被调用时,把返回内容 交 ...

  3. 用户 'IIS APPPOOL\Private' 登录失败。

    用户 'IIS APPPOOL\Private' 登录失败. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详细 ...

  4. sphinx实时索引和高亮显示

    sphinx实时索引和高亮显示 时间 2014-06-25 14:50:58  linux技术分享 -欧阳博客 原文  http://www.wantlearn.net/825 主题 Sphinx数据 ...

  5. Leetcode题解(32)

    107. Binary Tree Level Order Traversal II 题目 直接代码: /** * Definition for a binary tree node. * struct ...

  6. awk命令练习

    文件 file.txt的内容格式: 文件中包含名字,电话号码和过去三个月里的捐款 具体内容如下: Mike Harrington:[510] 548-1278:250:100:175 Christia ...

  7. HDFS的接口(命令行接口和Java接口)--笔记

    HDFS 文件的系统访问的接口 1.Hadoop的shell命令脚本 hadoop fs -ls   列出某一个目录下的文件 hadoop fs -lsr 递归的方式列出所有文件 hadoop fs ...

  8. 使用Mongodb+Shiro+SpringMVC实现动态权限分配

    此次的文档只对Mongodb整合Shiro并且实现动态权限分配做整理,其它的内容以后会补上. 第一步.创建在web.xml中配置 Spring .Shiro shiroFilter 过滤器是用来将请求 ...

  9. 跨域请求CORS

    参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS http://www.ruanyifeng.com/b ...

  10. 事件 event

    添加移除函数(removeEventListener)时三个参数保持一致,否则会失败,而且不会有错误提示 var btn = document.getElementById(“myBtn”); btn ...