Go语言高级编程(Advanced Go Programming)

Go语言高级编程(Advanced Go Programming)

  1. golang都是传值,与其他语言不同的是数组作为参数时,也是传值!
    但是,lambda闭包引用的外部变量,则是引用!
    另外,slice、string虽然也是传值,但其本质上是一个引用信息(指针、长度等信息),不涉及具体的内容。

  2. 空数组 [0]int{}、空结构体struct{}{} 本质上都不占用内存空间,非常好用,当然后者用的更多。

  3. 空切片 sc[:0] 在特定场合下非常有用!例如字符串的去除空格、过滤等功能。见代码

    
    
    func RemoveBlank(s string)[]byte{
    b := s[:0] for(i := 0; i < len(s); i++){
    if s[i] != ' '{
    b = append(b, s[i]) //在原内存上操作,且肯定不会超出,效率非常高
    }
    }
    }
  4. 切片底层是数组,如果切片一直存在,那么数组也不会被释放。所以这里可能存在严重的内存浪费行为。
    例如从文件内容中查找指定的内容,则可能会发生这种情况:读取了整个文件,返回了一个很大的[]byte,但最终返回的是一个很小的[]byte,这时候底层的数组不会被释放!
    这时,最好就是将获取到的结果append到全新的切片中。

    
    
    func FindPhoneNumber(file string)[]byte{
    b, _ := ioutil.ReadFile(file)
    //return regexp.MustCompile(`[0-9]+`).Find(b) //FIXME 不推荐!存在浪费的可能! b = regexp.MustCompile(`[0-9]+`).Find(b)
    return append([]byte{}, b...) //这样就OK了
    }

    另外,还有一种可能,就是切片中存的是指针,当缩小切片的范围时,范围外的指针仍然存在!同样会阻碍GC的进行!

    
    
    //bad demo
    var a[]*int{ ... }
    a = a[:len(a)-1] //注意:此时最后一个元素仍然存在,不会被GC!

    那需要怎么做呢? 首先将不需要的元素置为nil,再切片就OK啦:

    
    
    //good demo
    var a[]*int{ ... }
    a[len(a)-1] = nil //
    a = a[:len(a)-1]

    如果切片存在的周期很短的话,可以不用刻意处理这个问题!

  5. 在main.main函数执行之前所有代码都运行在同一个goroutine,也就是程序的主系统线程中。
    因此,如果某个init函数内部用go关键字启动了新的goroutine的话,新的goroutine只有在进入main.main函数之后才可能被执行到。

    
    
    package main
    
    import (
    "fmt"
    "time"
    ) // main.main()执行之前,只有一个main goroutine,因此,哪怕init中有goroutine,也只能等到main.main()执行时才能执行
    func init() {
    fmt.Println("init in")
    go func() {
    fmt.Println("init goroutine in") //看看这行信息出现的时间
    time.Sleep(time.Second * 5)
    fmt.Println("init goroutine out")
    }()
    fmt.Println("init out")
    } func main() {
    fmt.Println("-----main") time.Sleep(time.Second * 10)
    }
  6. Go语言函数的递归调用深度逻辑上没有限制,函数调用的栈是不会出现溢出错误的(相对而言),因为Go语言运行时会根据需要动态地调整函数栈的大小。每个goroutine刚启动时只会分配很小的栈(4或8KB,具体依赖实现),根据需要动态调整栈的大小,栈最大可以达到GB级(依赖具体实现)。

    
    
    package main
    
    import "fmt"
    
    //golang 的栈不能超过 1000000000-byte limit
    func main() {
    defer func() {
    if e := recover(); e != nil {
    fmt.Println(e)
    } }() n := 500000000
    r := factorial(n)
    fmt.Printf("%v 的阶乘是:%v\n", n, r)
    } //factorial 计算阶乘 - 不考虑溢出
    func factorial(n int) int {
    if n == 0 {
    return 1
    }
    return n * factorial(n-1)
    }

    因为,Go语言函数的栈不会溢出,所以普通Go程序员已经很少需要关心栈的运行机制的。
    在Go语言规范中甚至故意没有讲到栈和堆的概念。
    我们无法知道函数参数或局部变量到底是保存在栈中还是堆中,我们只需要知道它们能够正常工作就可以了。

  7. 因为不需要考虑堆、栈问题,所以完全可以这么写

    
    
    func tmp()*int{
    x := 10
    return &x //这是C/CPP中是完全不允许的,因为局部变量在栈上,函数执行完毕就会被销毁 - 但是golang足够智能,会自动在堆上创建 - 如果你非要关注堆、栈的话。
    }

    golang足够智能,会自行判断。

未完待续

Golang查缺补漏(一)的更多相关文章

  1. Android查缺补漏--Activity生命周期和启动模式

    一.生命周期 onCreate():启动Activity时,首次创建Activity时回调. onRestart():再次启动Activity时回调. onStart():首次启动Activity时在 ...

  2. Android查缺补漏--BroadcastReceiver的类型与使用

    Broadcast 是一种被用于应用内和应用之间传递信息的机制.一个广播可以对应多个接受者.一个完整的广播机制,需要具有以下三个要素: 发送广播的Broadcast 接受广播的BroadcastRec ...

  3. Android查缺补漏(View篇)--在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0?

    在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0 ? @Override protected void onCreate(Bundle savedInstanc ...

  4. Android查缺补漏--ContentProvider的使用

    ContentProvider (内容提供者)是一种共享型组件,可以为系统内应用于与应用之间提供访问接口. ContentProvide要想正常工作需要三个关键点: ContentProvider:对 ...

  5. Android查缺补漏--Service和IntentService

    Service的运行不依赖界面,即使程序被切换到后台,Service仍然能够保持正常运行.当某个应用程序进程被杀掉时,所有依赖于该进程的Service也会停止运行. Service 分为启动状态和绑定 ...

  6. Android查缺补漏(View篇)--自定义 View 的基本流程

    View是Android很重要的一部分,常用的View有Button.TextView.EditView.ListView.GridView.各种layout等等,开发者通过对这些View的各种组合以 ...

  7. Android查缺补漏(View篇)--自定义View利器Canvas和Paint详解

    上篇文章介绍了自定义View的创建流程,从宏观上给出了一个自定义View的创建步骤,本篇是上一篇文章的延续,介绍了自定义View中两个必不可少的工具Canvas和Paint,从细节上更进一步的讲解自定 ...

  8. Android查缺补漏(View篇)--事件分发机制

    事件分发机制是Android中非常重要的一个知识点,同时也是难点,相信到目前为止很多Android开发者对事件分发机制并没有一个非常系统的认识,当然也包括博主个人在内.可能在平时的开发工作中我们并没有 ...

  9. Android查缺补漏(View篇)--事件分发机制源码分析

    在上一篇博文中分析了事件分发的流程及规则,本篇会从源码的角度更进一步理解事件分发机制的原理,如果对事件分发规则还不太清楚的童鞋,建议先看一下上一篇博文 <Android查缺补漏(View篇)-- ...

随机推荐

  1. java多态的向上转型与向下转型(与编译时类型与运行时类型有关)

    1.编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定. 当编译时类型和运行时类型不一致时,就会出现所谓的多态. 因为子类是一个特殊的父类,因此java允许把一个子类对象直接 ...

  2. redis(二)

    基本配置 在源文件/usr/local/redis目录下,文件redis.conf为配置文件 绑定地址:如果需要远程访问,可将此行注释 bind 127.0.0.1 端口,默认为6379 port 6 ...

  3. EasyAR 开发实例---AR礼物(简单demo)

    一个节日礼物效果 --显示模型 在本次的案例中,我使用的是unity5.6.3版本,EasyAR 为2.0.(用1.0的版本,在渲染那块有问题) [导入SDK]到EasyAR官网(http://www ...

  4. 如何提高sql查询速度

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  5. oracle 10g 11g 12c区别

    oracle 10g 11g 12c区别

  6. CentOS下双网卡双IP不同IP段配置

    环境: eth0:10.0.7.2  gw :10.0.7.254 netmask:255.255.255.0 eth1:168.6.101.2    gw :168.6.101.254    net ...

  7. openjdk for window

    https://developers.redhat.com/products/openjdk/download/ https://github.com/dmlloyd/openjdk

  8. C#轻量级配置文件组件EasyJsonConfig

    一.课程介绍 一.本次分享课程<C#轻量级配置文件EasyJsonConfig>适合人群如下: 1.有一定的NET开发基础. 2.喜欢阿笨的干货分享课程的童鞋们. 二.今天我们要如何优雅解 ...

  9. ASP.NET Core 发布

    ASP.NET Core 发布,asp.netcore发布 第一步:运行 dotnet restore 命令,以还原项目中指定的依赖项 dotnet restore 第二步:使用 dotnet bui ...

  10. HEVC与VP9之间的对比

    在streamingmedia上看到的一篇对比HEVC与VP9的文章,挺不错.另外这边文章的几个comment也是不错的. 下面是全文.   The Great UHD Codec Debate: G ...