文档章节

go语言学习总结

 盼望明天
发布于 2018/08/22 13:21
字数 2051
阅读 19
收藏 0
Go

一、描述

go语言是直接将源码编译成二进制机器码的语言;它支持面向对象、也支持函数式编程;go是强类型语言;Go 编程语言原生支持并发。Go 使用 Go 协程(Goroutine) 和信道(Channel)来处理并发。

二、基本语法

1、切片与数组差别:切片是动态化数组,切片是注意两者初始化和函数的区别

a.初始化差别

数组需要指定大小,不指定也会根据初始化的自动推算出大小,不可改变 

a:=[...] int {1,2,3} ; a:=[3] int {1,2,3}

切片不需要指定大小

a:=[] int {1,2,3}; a:=make([]int,3); a:=make([] int ,3,5)

b.函数传递:

数组需要明确指定大小,数组是值传递,不同的数组总是代表不同的存储。

切片不需要明确指定大小,切片是地址传递。多个切片如果表示同一个数组的片段,它们可以共享数据;因此一个切片和相关数组的其他切片是共享存储的。

func changeArray(a [3]int) {//数组
    a[0] = 100
}
func changeSlice(s []int) {//切片
    s[0] = 100
}

func main(){

    a := [...]int{1, 2, 3}
    changeArray(a)
    fmt.Println(a[0]) //值传递,输出结果:1

    var s []int = []int{1, 2, 3, 4}
    fmt.Println(len(s), cap((s)))
    s = append(s, 6, 7, 8)
    fmt.Println(len(s), cap(s))
    changeSlice(s)
    fmt.Println(s[0]) //地址传递,输出结果:100

}

c.切片和垃圾回收

切片的底层指向一个数组,该数组的实际容量可能要大于切片所定义的容量。只有在没有任何切片指向的时候,底层的数组内层才会被释放,这种特性有时会导致程序占用多余的内存。

示例 函数 FindDigits 将一个文件加载到内存,然后搜索其中所有的数字并返回一个切片。

var digitRegexp = regexp.MustCompile("[0-9]+")

func FindDigits(filename string) []byte {
    b, _ := ioutil.ReadFile(filename)
    return digitRegexp.Find(b)
}

这段代码可以顺利运行,但返回的 []byte 指向的底层是整个文件的数据。只要该返回的切片不被释放,垃圾回收器就不能释放整个文件所占用的内存。换句话说,一点点有用的数据却占用了整个文件的内存。

想要避免这个问题,可以通过拷贝我们需要的部分到一个新的切片中:

func FindDigits(filename string) []byte {
   b, _ := ioutil.ReadFile(filename)
   b = digitRegexp.Find(b)
   c := make([]byte, len(b))
   copy(c, b)
   return c
}

2.数组和Map,数组的输出按照数组的放置顺序,但是Map是无序输出的,每次遍历的顺序不一样;

var m = map[string]int{
        "unix":         0,
        "python":       1,
        "go":           2,
        "javascript":   3,
        "testing":      4,
        "philosophy":   5,
        "startups":     6,
        "productivity": 7,
        "hn":           8,
        "reddit":       9,
        "C++":          10,
    }
    var keys []string
    for k := range m {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    for _, k := range keys {
        fmt.Println("Key:", k, "Value:", m[k])
    }

3.go语言中的指针

指针是一种存储变量内存地址(Memory Address)的变量。

如上图所示,变量 b 的值为 156,而 b 的内存地址为 0x1040a124。变量 a 存储了 b 的地址。我们就称 a 指向了 b

指针变量的类型为 *T,该指针指向一个 T 类型的变量。

&b  获取b的内存地址值;*a 则是获取a值对应物理地址值的b值:156;

向函数传递指针参数

func change(val *int) {  
    *val = 55
}
func main() {  
    a := 58
    fmt.Println("value of a before function call is",a)
    b := &a
    change(b)
    fmt.Println("value of a after function call is", a)
}

4.那么什么时候使用指针接收器,什么时候使用值接收器?

/*
使用值接收器的方法。
*/
func (e Employee) changeName(newName string) {
    e.name = newName
}

/*
使用指针接收器的方法。
*/
func (e *Employee) changeAge(newAge int) {
    e.age = newAge
}

一般来说,指针接收器可以使用在:对方法内部的接收器所做的改变应该对调用者可见时。

指针接收器也可以被使用在如下场景:当拷贝一个结构体的代价过于昂贵时。考虑下一个结构体有很多的字段。在方法内使用这个结构体做为值接收器需要拷贝整个结构体,这是很昂贵的。在这种情况下使用指针接收器,结构体不会被拷贝,只会传递一个指针到方法内部使用。

在其他的所有情况,值接收器都可以被使用。

5.在方法中使用值接收器 与 在函数中使用值参数

这个话题很多Go语言新手都弄不明白。我会尽量讲清楚。

当一个函数有一个值参数,它只能接受一个值参数。

当一个方法有一个值接收器,它可以接受值接收器和指针接收器。

让我们通过一个例子来理解这一点。

package main
import (
    "fmt"
)
type rectangle struct {
    length int
    width  int
}
func area(r rectangle) {
    fmt.Printf("Area Function result: %d\n", (r.length * r.width))
}
func (r rectangle) area() {
    fmt.Printf("Area Method result: %d\n", (r.length * r.width))
}
func main() {
    r := rectangle{
        length: 10,
        width:  5,
    }
    area(r)
    r.area()

    p := &r
    /*
       compilation error, cannot use p (type *rectangle) as type rectangle
       in argument to area
    */
    //area(p)
    p.area()//通过指针调用值接收器
}

6.在方法中使用指针接收器 与 在函数中使用指针参数

和值参数相类似,函数使用指针参数只接受指针,而使用指针接收器的方法可以使用值接收器和指针接收器。

package main
import (
    "fmt"
)
type rectangle struct {
    length int
    width  int
}
func perimeter(r *rectangle) {
    fmt.Println("perimeter function output:", 2*(r.length+r.width))

}
func (r *rectangle) perimeter() {
    fmt.Println("perimeter method output:", 2*(r.length+r.width))
}
func main() {
    r := rectangle{
        length: 10,
        width:  5,
    }
    p := &r //pointer to r
    perimeter(p)
    p.perimeter()
    /*
        cannot use r (type rectangle) as type *rectangle in argument to perimeter
    */
    //perimeter(r)
    r.perimeter()//使用值来调用指针接收器
}

7.并行和并发

并行不一定会加快运行速度,因为并行运行的组件之间可能需要相互通信。在我们浏览器的例子里,当文件下载完成后,应当对用户进行提醒,比如弹出一个窗口。于是,在负责下载的组件和负责渲染用户界面的组件之间,就产生了通信。在并发系统上,这种通信开销很小。但在多核的并行系统上,组件间的通信开销就很高了。所以,并行不一定会加快运行速度!

8.线程与协程区别

线程切换从系统层面远不止 保存和恢复 CPU上下文这么简单。操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。但是协程有一个问题,就是系统并不感知,所以操作系统不会帮你做切换。目前的协程框架一般都是设计成 1:N 模式。所谓 1:N 就是一个线程作为一个容器里面放置多个协程。那么谁来适时的切换这些协程?答案是有协程自己主动让出CPU,也就是每个协程池里面有一个调度器,这个调度器是被动调度的。意思就是他不会主动调度。协程的切换很轻。

9.缓冲信道和非缓冲信道

缓冲的channel:保证往缓冲中存数据先于对应的取数据,简单说就是在取的时候里面肯定有数据,否则就因取不到而阻塞。

非缓冲的channel:保证取数据先于存数据,就是保证存的时候肯定有其他的goroutine在取,否则就因放不进去而阻塞

三、疑问点

 

go系列教程:https://studygolang.com/subject/2

信道接入技术及协议:https://blog.csdn.net/fivedoumi/article/details/52776832

 

© 著作权归作者所有

下一篇: go语言工具
粉丝 7
博文 103
码字总数 174582
作品 0
广州
私信 提问
NLP 领域还有 5 大开放问题

雷锋网 AI 科技评论按:如题,虽然 NLP 研究领域已经在深度学习的帮助下取得了长足的发展,许多技术也已经商业化落地,但我们也需要知道,这个领域还有几个开放性问题等待解决 —— 如果它们...

杨晓凡
09/21
0
0
R语言学习历程回顾总结

感谢关注天善智能,走好数据之路↑↑↑ 欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定! 本文作者:天善智能社区专家...

天善智能
2017/11/27
0
0
软件开发者如何学会600多种编程语言

【IT168 评论】几周前,做为8th Light公司的实习生,我从CEO那里拿到了我的工作成绩报告。在与CEO的会见期间,我发现了一个对如何做一个程序员的认识上的盲区。起初我以为,想扩展自己的软件...

作者:佚名
2013/03/25
0
0
用R做数据分析(1)——R简介

R语言是由 Ross Ihaka、Robert Gentleman二位创建的,这也许可以解释为什么叫R语言。现在由“R开发核心团队”负责开发。R是基于S语言的一个GNU项目。 一、R语言介绍 R是为统计计算和作图的一...

师弟文
2015/11/30
119
0
R语言中文社区10篇最火的文章 | 2017大盘点

岁末年终,到了该谈终结的时候。 对此,小编特别精选出10篇,这一年来R社区最火的文章(阅读量最高),分享给一直默默关注社区的你们。 第十名: 如何七周成为数据分析师 “写这个系列,是希...

kmd8d5r
2017/12/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【jQuery基础学习】05 jQuery与Ajax以及序列化

本文转载于:专业的前端网站➭【jQuery基础学习】05 jQuery与Ajax以及序列化 好吧,这章不像上章那么水了,总是炒剩饭也不好。 关于AJAX 所谓Ajax,全名Asynchronous JavaScript and XML。(也...

前端老手
16分钟前
8
0
CVE-2019-14287(Linux sudo 漏洞)分析

作者:lu4nx@知道创宇404积极防御实验室 作者博客:《CVE-2019-14287(Linux sudo 漏洞)分析》 原文链接:https://paper.seebug.org/1057/ 近日 sudo 被爆光一个漏洞,非授权的特权用户可以...

极客君
17分钟前
4
0
关于分布式,你需要知道的真相

目录 一、分布式锁 数据库的唯一索引 Redis 的 SETNX 指令 Redis 的 RedLock 算法 Zookeeper 的有序节点 二、分布式事务 2PC 本地消息表 三、CAP 一致性 可用性 分区容忍性 权衡 四、BASE 基...

李红欧巴
17分钟前
5
0
读书笔记:深入理解ES6 (附录B)

附录B:了解ES7(2016)   ES6经历了4年的发展,之后TC-39决定将发布周期转换为每年一版,以确保新语言特性能够更快地发展。   ES6中添加了三个语法特性,下面一一来讲。 第1节 指数运算...

张森ZS
23分钟前
11
0
计算机公开课推荐 2019.8

欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN 面试求职交流群 724187166 ApacheCN 学习资源 编程 哈佛 CS50:计算机科学导论 视频 MIT 6.00.1x:计算机科...

ApacheCN_飞龙
23分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部